~ctwm/ctwm/trunk

« back to all changes in this revision

Viewing changes to events.c

  • Committer: Matthew Fuller
  • Date: 2016-08-16 10:37:18 UTC
  • mfrom: (514.2.49 build)
  • Revision ID: fullermd@over-yonder.net-20160816103718-7ay3cpxxzlkaw1er
Implement a parallel minimal build system, which can at least yield a
runnable ctwm in situations where the cmake chain is unavailable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
71
71
 
72
72
#include <stdio.h>
73
73
#include <stdlib.h>
 
74
#include <errno.h>
74
75
#include <sys/time.h>
75
76
 
76
77
#include <X11/Xatom.h>
77
78
#include <X11/extensions/shape.h>
78
79
 
 
80
#include "ctwm_atoms.h"
79
81
#include "add_window.h"
80
 
#include "animate.h"
 
82
#include "decorations.h"
81
83
#include "clicktofocus.h"
82
 
#include "colormaps.h"
83
 
#include "ctwm_atoms.h"
84
 
#include "decorations.h"
 
84
#include "menus.h"
85
85
#include "events.h"
86
 
#include "event_handlers.h"
87
 
#include "event_internal.h"
88
86
#include "event_names.h"
89
 
#include "functions.h"
90
 
#include "functions_defs.h"
91
 
#include "gram.tab.h"
 
87
#include "resize.h"
 
88
#include "parse.h"
 
89
#include "util.h"
 
90
#include "animate.h"
 
91
#include "otp.h"
 
92
#include "screen.h"
 
93
#include "icons.h"
92
94
#include "iconmgr.h"
93
 
#include "icons.h"
 
95
#include "version.h"
94
96
#include "image.h"
95
 
#include "list.h"
96
 
#include "occupation.h"
97
 
#include "otp.h"
98
 
#include "parse.h"
99
 
#include "resize.h"
100
 
#include "screen.h"
101
 
#include "util.h"
102
 
#include "vscreen.h"
103
 
#include "win_iconify.h"
104
 
#include "win_ops.h"
105
 
#include "win_regions.h"
106
 
#include "win_utils.h"
 
97
#include "functions.h"
107
98
#include "workspace_manager.h"
108
99
#include "workspace_utils.h"
109
 
 
110
 
 
 
100
#ifdef SOUNDS
 
101
#include "sound.h"
 
102
#endif
 
103
 
 
104
#include "gram.tab.h"
 
105
 
 
106
static void CtwmNextEvent(Display *display, XEvent  *event);
 
107
static void RedoIcon(void);
111
108
static void do_key_menu(MenuRoot *menu,         /* menu to pop up */
112
109
                        Window w);             /* invoking window or None */
113
 
 
114
 
/* Only called from HandleFocusChange() */
115
 
static void HandleFocusIn(void);
116
 
static void HandleFocusOut(void);
117
 
 
 
110
static bool StashEventTime(XEvent *ev);
 
111
 
 
112
FILE *tracefile = NULL;
 
113
 
 
114
#define MAX_X_EVENT 256
 
115
event_proc EventHandler[MAX_X_EVENT]; /* event handler jump table */
118
116
static char *Action;            /* XXX This may be narrowable */
 
117
int Context = C_NO_CONTEXT;     /* current button press context */
119
118
static TwmWindow *ButtonWindow; /* button press window structure */
120
 
 
 
119
XEvent Event;                   /* the current event */
 
120
static TwmWindow *Tmp_win;      /* the current twm window */
 
121
 
 
122
Window DragWindow;              /* variables used in moving windows */
 
123
int origDragX;
 
124
int origDragY;
 
125
int DragX;
 
126
int DragY;
 
127
unsigned int DragWidth;
 
128
unsigned int DragHeight;
 
129
unsigned int DragBW;
 
130
int CurrentDragX;
 
131
int CurrentDragY;
 
132
 
 
133
static bool enter_flag;
 
134
static bool leave_flag;
 
135
static bool ColortableThrashing;
 
136
static TwmWindow *enter_win, *raise_win, *leave_win, *lower_win;
 
137
 
 
138
int ButtonPressed = -1;
 
139
bool Cancel = false;
 
140
 
 
141
void HandleCreateNotify(void);
 
142
void HandleShapeNotify(void);
 
143
void HandleFocusChange(void);
 
144
void HandleSelectionClear(void);
 
145
 
 
146
 
 
147
/*#define TRACE_FOCUS*/
 
148
/*#define TRACE*/
 
149
 
 
150
static void dumpevent(XEvent *e);
121
151
 
122
152
static unsigned int set_mask_ignore(unsigned int modifier)
123
153
{
126
156
        return modifier;
127
157
}
128
158
 
 
159
void AutoRaiseWindow(TwmWindow *tmp)
 
160
{
 
161
        OtpRaise(tmp, WinWin);
 
162
 
 
163
        if(ActiveMenu && ActiveMenu->w) {
 
164
                XRaiseWindow(dpy, ActiveMenu->w);
 
165
        }
 
166
        XSync(dpy, 0);
 
167
        enter_win = NULL;
 
168
        enter_flag = true;
 
169
        raise_win = tmp;
 
170
        WMapRaise(tmp);
 
171
}
 
172
 
 
173
void SetRaiseWindow(TwmWindow *tmp)
 
174
{
 
175
        enter_flag = true;
 
176
        enter_win = NULL;
 
177
        raise_win = tmp;
 
178
        leave_win = NULL;
 
179
        leave_flag = false;
 
180
        lower_win = NULL;
 
181
        XSync(dpy, 0);
 
182
}
 
183
 
 
184
void AutoPopupMaybe(TwmWindow *tmp)
 
185
{
 
186
        if(LookInList(Scr->AutoPopupL, tmp->full_name, &tmp->class)
 
187
                        || Scr->AutoPopup) {
 
188
                if(OCCUPY(tmp, Scr->currentvs->wsw->currentwspc)) {
 
189
                        if(!tmp->mapped) {
 
190
                                DeIconify(tmp);
 
191
                                SetRaiseWindow(tmp);
 
192
                        }
 
193
                }
 
194
                else {
 
195
                        tmp->mapped = true;
 
196
                }
 
197
        }
 
198
}
 
199
 
 
200
void AutoLowerWindow(TwmWindow *tmp)
 
201
{
 
202
        OtpLower(tmp, WinWin);
 
203
 
 
204
        if(ActiveMenu && ActiveMenu->w) {
 
205
                XRaiseWindow(dpy, ActiveMenu->w);
 
206
        }
 
207
        XSync(dpy, 0);
 
208
        enter_win = NULL;
 
209
        enter_flag = false;
 
210
        raise_win = NULL;
 
211
        leave_win = NULL;
 
212
        leave_flag = true;
 
213
        lower_win = tmp;
 
214
        WMapLower(tmp);
 
215
}
 
216
 
 
217
 
 
218
/***********************************************************************
 
219
 *
 
220
 *  Procedure:
 
221
 *      InitEvents - initialize the event jump table
 
222
 *
 
223
 ***********************************************************************
 
224
 */
 
225
 
 
226
void InitEvents(void)
 
227
{
 
228
        int i;
 
229
 
 
230
 
 
231
        ResizeWindow = (Window) 0;
 
232
        DragWindow = (Window) 0;
 
233
        enter_flag = false;
 
234
        enter_win = raise_win = NULL;
 
235
        leave_flag = false;
 
236
        leave_win = lower_win = NULL;
 
237
 
 
238
        for(i = 0; i < MAX_X_EVENT; i++) {
 
239
                EventHandler[i] = HandleUnknown;
 
240
        }
 
241
 
 
242
        EventHandler[Expose] = HandleExpose;
 
243
        EventHandler[CreateNotify] = HandleCreateNotify;
 
244
        EventHandler[DestroyNotify] = HandleDestroyNotify;
 
245
        EventHandler[MapRequest] = HandleMapRequest;
 
246
        EventHandler[MapNotify] = HandleMapNotify;
 
247
        EventHandler[UnmapNotify] = HandleUnmapNotify;
 
248
        EventHandler[MotionNotify] = HandleMotionNotify;
 
249
        EventHandler[ButtonRelease] = HandleButtonRelease;
 
250
        EventHandler[ButtonPress] = HandleButtonPress;
 
251
        EventHandler[EnterNotify] = HandleEnterNotify;
 
252
        EventHandler[LeaveNotify] = HandleLeaveNotify;
 
253
        EventHandler[ConfigureRequest] = HandleConfigureRequest;
 
254
        EventHandler[ClientMessage] = HandleClientMessage;
 
255
        EventHandler[PropertyNotify] = HandlePropertyNotify;
 
256
        EventHandler[KeyPress] = HandleKeyPress;
 
257
        EventHandler[KeyRelease] = HandleKeyRelease;
 
258
        EventHandler[ColormapNotify] = HandleColormapNotify;
 
259
        EventHandler[VisibilityNotify] = HandleVisibilityNotify;
 
260
        EventHandler[FocusIn] = HandleFocusChange;
 
261
        EventHandler[FocusOut] = HandleFocusChange;
 
262
        EventHandler[CirculateNotify] = HandleCirculateNotify;
 
263
        if(HasShape) {
 
264
                EventHandler[ShapeEventBase + ShapeNotify] = HandleShapeNotify;
 
265
        }
 
266
#ifdef EWMH
 
267
        EventHandler[SelectionClear] = HandleSelectionClear;
 
268
#endif
 
269
}
 
270
 
 
271
 
 
272
 
 
273
Time lastTimestamp = CurrentTime;       /* until Xlib does this for us */
 
274
 
 
275
static bool
 
276
StashEventTime(XEvent *ev)
 
277
{
 
278
        switch(ev->type) {
 
279
                case KeyPress:
 
280
                case KeyRelease:
 
281
                        lastTimestamp = ev->xkey.time;
 
282
                        return true;
 
283
                case ButtonPress:
 
284
                case ButtonRelease:
 
285
                        lastTimestamp = ev->xbutton.time;
 
286
                        return true;
 
287
                case MotionNotify:
 
288
                        lastTimestamp = ev->xmotion.time;
 
289
                        return true;
 
290
                case EnterNotify:
 
291
                case LeaveNotify:
 
292
                        lastTimestamp = ev->xcrossing.time;
 
293
                        return true;
 
294
                case PropertyNotify:
 
295
                        lastTimestamp = ev->xproperty.time;
 
296
                        return true;
 
297
                case SelectionClear:
 
298
                        lastTimestamp = ev->xselectionclear.time;
 
299
                        return true;
 
300
                case SelectionRequest:
 
301
                        lastTimestamp = ev->xselectionrequest.time;
 
302
                        return true;
 
303
                case SelectionNotify:
 
304
                        lastTimestamp = ev->xselection.time;
 
305
                        return true;
 
306
        }
 
307
        return false;
 
308
}
 
309
 
 
310
 
 
311
/*
 
312
 * WindowOfEvent - return the window about which this event is concerned; this
 
313
 * window may not be the same as XEvent.xany.window (the first window listed
 
314
 * in the structure).
 
315
 */
 
316
Window WindowOfEvent(XEvent *e)
 
317
{
 
318
        /*
 
319
         * Each window subfield is marked with whether or not it is the same as
 
320
         * XEvent.xany.window or is different (which is the case for some of the
 
321
         * notify events).
 
322
         */
 
323
        switch(e->type) {
 
324
                case KeyPress:
 
325
                case KeyRelease:
 
326
                        return e->xkey.window;                       /* same */
 
327
                case ButtonPress:
 
328
                case ButtonRelease:
 
329
                        return e->xbutton.window;                 /* same */
 
330
                case MotionNotify:
 
331
                        return e->xmotion.window;                  /* same */
 
332
                case EnterNotify:
 
333
                case LeaveNotify:
 
334
                        return e->xcrossing.window;                 /* same */
 
335
                case FocusIn:
 
336
                case FocusOut:
 
337
                        return e->xfocus.window;                       /* same */
 
338
                case KeymapNotify:
 
339
                        return e->xkeymap.window;                  /* same */
 
340
                case Expose:
 
341
                        return e->xexpose.window;                        /* same */
 
342
                case GraphicsExpose:
 
343
                        return e->xgraphicsexpose.drawable;      /* same */
 
344
                case NoExpose:
 
345
                        return e->xnoexpose.drawable;                  /* same */
 
346
                case VisibilityNotify:
 
347
                        return e->xvisibility.window;          /* same */
 
348
                case CreateNotify:
 
349
                        return e->xcreatewindow.window;            /* DIFF */
 
350
                case DestroyNotify:
 
351
                        return e->xdestroywindow.window;          /* DIFF */
 
352
                case UnmapNotify:
 
353
                        return e->xunmap.window;                    /* DIFF */
 
354
                case MapNotify:
 
355
                        return e->xmap.window;                        /* DIFF */
 
356
                case MapRequest:
 
357
                        return e->xmaprequest.window;                /* DIFF */
 
358
                case ReparentNotify:
 
359
                        return e->xreparent.window;              /* DIFF */
 
360
                case ConfigureNotify:
 
361
                        return e->xconfigure.window;            /* DIFF */
 
362
                case ConfigureRequest:
 
363
                        return e->xconfigurerequest.window;    /* DIFF */
 
364
                case GravityNotify:
 
365
                        return e->xgravity.window;                /* DIFF */
 
366
                case ResizeRequest:
 
367
                        return e->xresizerequest.window;          /* same */
 
368
                case CirculateNotify:
 
369
                        return e->xcirculate.window;            /* DIFF */
 
370
                case CirculateRequest:
 
371
                        return e->xcirculaterequest.window;    /* DIFF */
 
372
                case PropertyNotify:
 
373
                        return e->xproperty.window;              /* same */
 
374
                case SelectionClear:
 
375
                        return e->xselectionclear.window;        /* same */
 
376
                case SelectionRequest:
 
377
                        return e->xselectionrequest.requestor;  /* DIFF */
 
378
                case SelectionNotify:
 
379
                        return e->xselection.requestor;         /* same */
 
380
                case ColormapNotify:
 
381
                        return e->xcolormap.window;              /* same */
 
382
                case ClientMessage:
 
383
                        return e->xclient.window;                 /* same */
 
384
                case MappingNotify:
 
385
                        return None;
 
386
        }
 
387
        return None;
 
388
}
 
389
 
 
390
void FixRootEvent(XEvent *e)
 
391
{
 
392
        if(Scr->Root == Scr->RealRoot) {
 
393
                return;
 
394
        }
 
395
 
 
396
        switch(e->type) {
 
397
                case KeyPress:
 
398
                case KeyRelease:
 
399
                        e->xkey.x_root -= Scr->rootx;
 
400
                        e->xkey.y_root -= Scr->rooty;
 
401
                        e->xkey.root    = Scr->Root;
 
402
                        break;
 
403
                case ButtonPress:
 
404
                case ButtonRelease:
 
405
                        e->xbutton.x_root -= Scr->rootx;
 
406
                        e->xbutton.y_root -= Scr->rooty;
 
407
                        e->xbutton.root    = Scr->Root;
 
408
                        break;
 
409
                case MotionNotify:
 
410
                        e->xmotion.x_root -= Scr->rootx;
 
411
                        e->xmotion.y_root -= Scr->rooty;
 
412
                        e->xmotion.root    = Scr->Root;
 
413
                        break;
 
414
                case EnterNotify:
 
415
                case LeaveNotify:
 
416
                        e->xcrossing.x_root -= Scr->rootx;
 
417
                        e->xcrossing.y_root -= Scr->rooty;
 
418
                        e->xcrossing.root    = Scr->Root;
 
419
                        break;
 
420
                default:
 
421
                        break;
 
422
        }
 
423
}
 
424
 
 
425
 
 
426
/* Move this next to GetTwmWindow()? */
 
427
static ScreenInfo *GetTwmScreen(XEvent *event)
 
428
{
 
429
        ScreenInfo *scr;
 
430
 
 
431
        if(XFindContext(dpy, event->xany.window, ScreenContext,
 
432
                        (XPointer *)&scr) == XCNOENT) {
 
433
                scr = FindScreenInfo(WindowOfEvent(event));
 
434
        }
 
435
 
 
436
        return scr;
 
437
}
 
438
 
 
439
/***********************************************************************
 
440
 *
 
441
 *  Procedure:
 
442
 *      DispatchEvent2 -
 
443
 *      handle a single X event stored in global var Event
 
444
 *      this routine for is for a call during an f.move
 
445
 *
 
446
 ***********************************************************************
 
447
 */
 
448
bool
 
449
DispatchEvent2(void)
 
450
{
 
451
        Window w = Event.xany.window;
 
452
        ScreenInfo *thisScr;
 
453
 
 
454
        StashEventTime(&Event);
 
455
        Tmp_win = GetTwmWindow(w);
 
456
        thisScr = GetTwmScreen(&Event);
 
457
 
 
458
        dumpevent(&Event);
 
459
 
 
460
        if(!thisScr) {
 
461
                return false;
 
462
        }
 
463
        Scr = thisScr;
 
464
 
 
465
        FixRootEvent(&Event);
 
466
 
 
467
#ifdef SOUNDS
 
468
        play_sound(Event.type);
 
469
#endif
 
470
 
 
471
        if(menuFromFrameOrWindowOrTitlebar) {
 
472
                if(Event.type == Expose) {
 
473
                        HandleExpose();
 
474
                }
 
475
        }
 
476
        else {
 
477
                if(Event.type >= 0 && Event.type < MAX_X_EVENT) {
 
478
                        (*EventHandler[Event.type])();
 
479
                }
 
480
        }
 
481
 
 
482
        return true;
 
483
}
 
484
 
 
485
/***********************************************************************
 
486
 *
 
487
 *  Procedure:
 
488
 *      DispatchEvent - handle a single X event stored in global var Event
 
489
 *
 
490
 ***********************************************************************
 
491
 */
 
492
bool
 
493
DispatchEvent(void)
 
494
{
 
495
        Window w = Event.xany.window;
 
496
        ScreenInfo *thisScr;
 
497
 
 
498
        StashEventTime(&Event);
 
499
        Tmp_win = GetTwmWindow(w);
 
500
        thisScr = GetTwmScreen(&Event);
 
501
 
 
502
        dumpevent(&Event);
 
503
 
 
504
        if(!thisScr) {
 
505
                return false;
 
506
        }
 
507
        Scr = thisScr;
 
508
 
 
509
        if(CLarg.is_captive) {
 
510
                if((Event.type == ConfigureNotify)
 
511
                                && (Event.xconfigure.window == Scr->CaptiveRoot)) {
 
512
                        ConfigureRootWindow(&Event);
 
513
                        return false;
 
514
                }
 
515
        }
 
516
        FixRootEvent(&Event);
 
517
        if(Event.type >= 0 && Event.type < MAX_X_EVENT) {
 
518
#ifdef SOUNDS
 
519
                play_sound(Event.type);
 
520
#endif
 
521
                (*EventHandler[Event.type])();
 
522
        }
 
523
        return true;
 
524
}
 
525
 
 
526
 
 
527
/***********************************************************************
 
528
 *
 
529
 *  Procedure:
 
530
 *      HandleEvents - handle X events
 
531
 *
 
532
 ***********************************************************************
 
533
 */
 
534
 
 
535
void HandleEvents(void)
 
536
{
 
537
        while(1) {
 
538
                if(enter_flag && !QLength(dpy)) {
 
539
                        if(enter_win && enter_win != raise_win) {
 
540
                                AutoRaiseWindow(enter_win);   /* sets enter_flag T */
 
541
                        }
 
542
                        else {
 
543
                                enter_flag = false;
 
544
                        }
 
545
                }
 
546
                if(leave_flag && !QLength(dpy)) {
 
547
                        if(leave_win && leave_win != lower_win) {
 
548
                                AutoLowerWindow(leave_win);  /* sets leave_flag T */
 
549
                        }
 
550
                        else {
 
551
                                leave_flag = false;
 
552
                        }
 
553
                }
 
554
                if(ColortableThrashing && !QLength(dpy) && Scr) {
 
555
                        InstallColormaps(ColormapNotify, NULL);
 
556
                }
 
557
                WindowMoved = false;
 
558
 
 
559
                CtwmNextEvent(dpy, &Event);
 
560
 
 
561
                if(Event.type < 0 || Event.type >= MAX_X_EVENT) {
 
562
                        XtDispatchEvent(&Event);
 
563
                }
 
564
                else {
 
565
                        (void) DispatchEvent();
 
566
                }
 
567
        }
 
568
}
 
569
 
 
570
 
 
571
static void CtwmNextEvent(Display *display, XEvent  *event)
 
572
{
 
573
        int         found;
 
574
        fd_set      mask;
 
575
        int         fd;
 
576
        struct timeval timeout, *tout = NULL;
 
577
        const bool animate = (AnimationActive && MaybeAnimate);
 
578
 
 
579
#define nextEvent(event) XtAppNextEvent(appContext, event);
 
580
 
 
581
        if(RestartFlag) {
 
582
                DoRestart(CurrentTime);
 
583
        }
 
584
        if(XEventsQueued(display, QueuedAfterFlush) != 0) {
 
585
                nextEvent(event);
 
586
                return;
 
587
        }
 
588
        fd = ConnectionNumber(display);
 
589
 
 
590
        if(animate) {
 
591
                TryToAnimate();
 
592
        }
 
593
        if(RestartFlag) {
 
594
                DoRestart(CurrentTime);
 
595
        }
 
596
        if(! MaybeAnimate) {
 
597
                nextEvent(event);
 
598
                return;
 
599
        }
 
600
        if(animate) {
 
601
                tout = (AnimationSpeed > 0) ? &timeout : NULL;
 
602
        }
 
603
        while(1) {
 
604
                FD_ZERO(&mask);
 
605
                FD_SET(fd, &mask);
 
606
                if(animate) {
 
607
                        timeout = AnimateTimeout;
 
608
                }
 
609
                found = select(fd + 1, &mask, NULL, NULL, tout);
 
610
                if(RestartFlag) {
 
611
                        DoRestart(CurrentTime);
 
612
                }
 
613
                if(found < 0) {
 
614
                        if(errno != EINTR) {
 
615
                                perror("select");
 
616
                        }
 
617
                        continue;
 
618
                }
 
619
                if(FD_ISSET(fd, &mask)) {
 
620
                        nextEvent(event);
 
621
                        return;
 
622
                }
 
623
                if(found == 0) {
 
624
                        if(animate) {
 
625
                                TryToAnimate();
 
626
                        }
 
627
                        if(RestartFlag) {
 
628
                                DoRestart(CurrentTime);
 
629
                        }
 
630
                        if(! MaybeAnimate) {
 
631
                                nextEvent(event);
 
632
                                return;
 
633
                        }
 
634
                        continue;
 
635
                }
 
636
        }
 
637
 
 
638
#undef nextEvent
 
639
 
 
640
        /* NOTREACHED */
 
641
}
 
642
 
129
643
 
130
644
/***********************************************************************
131
645
 *
313
827
                                   )) {
314
828
                        current = new;
315
829
                        last = &current;
316
 
                }
317
 
 
318
 
#ifdef TRACE_FOCUS
319
 
                fprintf(stderr, "%s(): Focus%s 0x%x mode=%d, detail=%d\n",
320
 
                        __func__, new.xfocus.type == FocusIn ? "In" : "Out",
321
 
                        Tmp_win, new.xfocus.mode, new.xfocus.detail);
322
 
#endif
323
 
 
 
830
#ifdef TRACE_FOCUS
 
831
                        fprintf(stderr, "! %s 0x%x mode=%d, detail=%d\n",
 
832
                                new.xfocus.type == FocusIn ? "in" : "out",
 
833
                                Tmp_win, new.xfocus.mode, new.xfocus.detail);
 
834
#endif
 
835
                }
 
836
                else {
 
837
#ifdef TRACE_FOCUS
 
838
                        fprintf(stderr, "~ %s 0x%x mode=%d, detail=%d\n",
 
839
                                new.xfocus.type == FocusIn ? "in" : "out",
 
840
                                Tmp_win, new.xfocus.mode, new.xfocus.detail);
 
841
#endif
 
842
                }
324
843
        }
325
844
        while(XCheckWindowEvent(dpy, w, FocusChangeMask, &new));
326
845
        return last;
327
846
}
328
847
 
329
 
 
330
848
/*
331
 
 * Focus change handlers.
332
 
 *
333
 
 * Depending on how events get called, these are sometimes redundant, as
334
 
 * the Enter event handler does practically all of this anyway.  But
335
 
 * there are presumably ways we can wind up Focus'ing a window without
336
 
 * Enter'ing it as well.
337
 
 *
338
 
 * It's also a little convoluted how these wind up getting called.  With
339
 
 * most events, we call a handler, then handle that event.  However, with
340
 
 * focus, we troll through our list of pending Focus-related events for
341
 
 * the window and just handle the last one, since some could pile up
342
 
 * fast.  That means that, even if we get called for a FocusIn event,
343
 
 * there might be a FocusOut later in the queue, and _that_'s the one we
344
 
 * pick up and handle, and we discard the rest [for that window].  So,
345
 
 * the event handling code calls a single entry point for both types, and
346
 
 * then it figures out which backend handler to actually fire.
 
849
 * HandleFocusIn -- deal with the focus moving under us.
347
850
 */
348
 
void
349
 
HandleFocusChange(void)
 
851
 
 
852
void HandleFocusIn(XFocusInEvent *event)
350
853
{
351
 
        XEvent *event;
352
 
 
353
 
        /* If there's no event window, nothing to do */
354
 
        if(!Tmp_win) {
355
 
                return;
356
 
        }
357
 
 
358
 
        /*
359
 
         * Consume all the focus events for the window we're called about and
360
 
         * grab the last one to process.
361
 
         *
362
 
         * XXX It should be guaranteed that the window in the X event in our
363
 
         * global Event is the same as Tmp_win->w as the event dispatcher
364
 
         * sets it so.  Maybe we should do both checks on the same var for
365
 
         * consistency though?
366
 
         *
367
 
         * It's not immediately clear how this can wind up returning nothing,
368
 
         * but if it does, we don't have anything to do either.
369
 
         */
370
 
        event = LastFocusEvent(Event.xany.window, &Event);
371
 
        if(event == NULL) {
372
 
                return;
373
 
        }
374
 
 
375
 
        /*
376
 
         * Icon managers don't do anything with focus events on themselves,
377
 
         * so just skip back if this is one.  Done after LastFocusEvent()
378
 
         * call for efficiency, so we don't fall into this func multiple
379
 
         * times if multiple events are queued for it.
380
 
         */
381
 
        if(Tmp_win->isiconmgr) {
382
 
                return;
383
 
        }
384
854
 
385
855
#ifdef TRACE_FOCUS
386
 
        fprintf(stderr, "HandleFocus%s(): 0x%x (0x%x, 0x%x), mode=%d, "
387
 
                "detail=%d\n",
388
 
                (event->type == FocusIn ? "In" : "Out"),
389
 
                Tmp_win, Tmp_win->w, event->window, event->mode,
390
 
                event->detail);
 
856
        fprintf(stderr, "HandleFocusIn : +0x%x (0x%x, 0x%x), mode=%d, detail=%d\n",
 
857
                Tmp_win, Tmp_win->w, event->window, event->mode, event->detail);
391
858
#endif
392
859
 
393
 
        /* And call actual handler */
394
 
        if(event->type == FocusIn) {
395
 
                HandleFocusIn();
396
 
        }
397
 
        else {
398
 
                HandleFocusOut();
399
 
        }
400
 
}
401
 
 
402
 
 
403
 
static void
404
 
HandleFocusIn(void)
405
 
{
 
860
        if(Tmp_win->isiconmgr) {
 
861
                return;
 
862
        }
406
863
        if(Tmp_win->wmhints && ! Tmp_win->wmhints->input) {
407
864
                return;
408
865
        }
421
878
        Scr->Focus = Tmp_win;
422
879
}
423
880
 
424
 
 
425
 
static void
426
 
HandleFocusOut(void)
 
881
void HandleFocusOut(XFocusOutEvent *event)
427
882
{
 
883
#ifdef TRACE_FOCUS
 
884
        fprintf(stderr, "HandleFocusOut : -0x%x (0x%x, 0x%x), mode=%d, detail=%d\n",
 
885
                Tmp_win, Tmp_win->w, event->window, event->mode, event->detail);
 
886
#endif
 
887
 
 
888
        if(Tmp_win->isiconmgr) {
 
889
                return;
 
890
        }
428
891
        if(Scr->Focus != Tmp_win) {
429
892
                return;
430
893
        }
443
906
        Scr->Focus = NULL;
444
907
}
445
908
 
446
 
 
 
909
void HandleFocusChange(void)
 
910
{
 
911
        XEvent *event;
 
912
 
 
913
        if(Tmp_win) {
 
914
                event = LastFocusEvent(Event.xany.window, &Event);
 
915
 
 
916
                if(event != NULL) {
 
917
                        if(event->type == FocusIn) {
 
918
                                HandleFocusIn(&event->xfocus);
 
919
                        }
 
920
                        else {
 
921
                                HandleFocusOut(&event->xfocus);
 
922
                        }
 
923
                }
 
924
        }
 
925
}
 
926
 
 
927
void SynthesiseFocusOut(Window w)
 
928
{
 
929
        XEvent event;
 
930
 
 
931
#ifdef TRACE_FOCUS
 
932
        fprintf(stderr, "Synthesizing FocusOut on %x\n", w);
 
933
#endif
 
934
 
 
935
        event.type = FocusOut;
 
936
        event.xfocus.window = w;
 
937
        event.xfocus.mode = NotifyNormal;
 
938
        event.xfocus.detail = NotifyPointer;
 
939
 
 
940
        XPutBackEvent(dpy, &event);
 
941
}
 
942
 
 
943
 
 
944
void SynthesiseFocusIn(Window w)
 
945
{
 
946
        XEvent event;
 
947
 
 
948
#ifdef TRACE_FOCUS
 
949
        fprintf(stderr, "Synthesizing FocusIn on %x\n", w);
 
950
#endif
 
951
 
 
952
        event.type = FocusIn;
 
953
        event.xfocus.window = w;
 
954
        event.xfocus.mode = NotifyNormal;
 
955
        event.xfocus.detail = NotifyPointer;
 
956
 
 
957
        XPutBackEvent(dpy, &event);
 
958
 
 
959
}
447
960
 
448
961
/*
449
962
 * Only sent if SubstructureNotifyMask is selected on the (root) window.
977
1490
}
978
1491
 
979
1492
 
 
1493
void free_cwins(TwmWindow *tmp)
 
1494
{
 
1495
        int i;
 
1496
        TwmColormap *cmap;
 
1497
 
 
1498
        if(tmp->cmaps.number_cwins) {
 
1499
                for(i = 0; i < tmp->cmaps.number_cwins; i++) {
 
1500
                        if(--tmp->cmaps.cwins[i]->refcnt == 0) {
 
1501
                                cmap = tmp->cmaps.cwins[i]->colormap;
 
1502
                                if(--cmap->refcnt == 0) {
 
1503
                                        XDeleteContext(dpy, cmap->c, ColormapContext);
 
1504
                                        free(cmap);
 
1505
                                }
 
1506
                                XDeleteContext(dpy, tmp->cmaps.cwins[i]->w, ColormapContext);
 
1507
                                free(tmp->cmaps.cwins[i]);
 
1508
                        }
 
1509
                }
 
1510
                free(tmp->cmaps.cwins);
 
1511
                if(tmp->cmaps.number_cwins > 1) {
 
1512
                        free(tmp->cmaps.scoreboard);
 
1513
                        tmp->cmaps.scoreboard = NULL;
 
1514
                }
 
1515
                tmp->cmaps.number_cwins = 0;
 
1516
        }
 
1517
}
 
1518
 
 
1519
 
980
1520
/***********************************************************************
981
1521
 *
982
1522
 *  Procedure:
1003
1543
 
1004
1544
        /* watch for standard colormap changes */
1005
1545
        if(Event.xproperty.window == Scr->Root) {
 
1546
                XStandardColormap *maps = NULL;
 
1547
                int nmaps;
1006
1548
 
1007
1549
                if(Event.xproperty.atom == XA_WM_CURRENTWORKSPACE) {
1008
1550
                        switch(Event.xproperty.state) {
1023
1565
                        }
1024
1566
                }
1025
1567
                switch(Event.xproperty.state) {
1026
 
                        case PropertyNewValue: {
1027
 
                                XStandardColormap *maps = NULL;
1028
 
                                int nmaps;
1029
 
 
 
1568
                        case PropertyNewValue:
1030
1569
                                if(XGetRGBColormaps(dpy, Scr->Root, &maps, &nmaps,
1031
1570
                                                    Event.xproperty.atom)) {
1032
1571
                                        /* if got one, then replace any existing entry */
1033
1572
                                        InsertRGBColormap(Event.xproperty.atom, maps, nmaps, true);
1034
1573
                                }
1035
1574
                                return;
1036
 
                        }
1037
1575
 
1038
1576
                        case PropertyDelete:
1039
1577
                                RemoveRGBColormap(Event.xproperty.atom);
1132
1670
                        }
1133
1671
                        if(name_change || icon_change) {
1134
1672
                                if(icon_change) {
1135
 
                                        RedoIcon(Tmp_win);
 
1673
                                        RedoIcon();
1136
1674
                                }
1137
1675
                                AutoPopupMaybe(Tmp_win);
1138
1676
                        }
1156
1694
                        Tmp_win->icon_name = (char *) prop;
1157
1695
 
1158
1696
                        if(icon_change) {
1159
 
                                RedoIcon(Tmp_win);
 
1697
                                RedoIcon();
1160
1698
                                AutoPopupMaybe(Tmp_win);
1161
1699
                        }
1162
1700
                        break;
1275
1813
 
1276
1814
                                if(icon->image) {
1277
1815
                                        /* Release the existing Image: it may be a shared one (UnknownIcon) */
1278
 
                                        ReleaseIconImage(icon);
 
1816
                                        ReleaseImage(icon);
1279
1817
                                        /* conjure up a new Image */
1280
1818
                                        Image *image = AllocImage();
1281
1819
                                        image->pixmap = pm;
1312
1850
                                                                0, &rect, 1, ShapeUnion, 0);
1313
1851
                                }
1314
1852
                                XMapSubwindows(dpy, icon->w);
1315
 
                                RedoIconName(Tmp_win);
 
1853
                                RedoIconName();
1316
1854
                        }
1317
1855
                        if(icon && icon->w &&
1318
1856
                                        (Tmp_win->wmhints->flags & IconMaskHint) &&
1355
1893
                                                XFreePixmap(dpy, icon->image->mask);
1356
1894
                                        }
1357
1895
                                        icon->image->mask = mask;
1358
 
                                        RedoIconName(Tmp_win);
 
1896
                                        RedoIconName();
1359
1897
                                }
1360
1898
                        }
1361
1899
                        if(Tmp_win->wmhints->flags & IconPixmapHint) {
1398
1936
}
1399
1937
 
1400
1938
 
 
1939
static void RedoIcon(void)
 
1940
{
 
1941
        Icon *icon, *old_icon;
 
1942
        char *pattern;
 
1943
 
 
1944
        old_icon = Tmp_win->icon;
 
1945
 
 
1946
        if(old_icon && (
 
1947
                                old_icon->w_not_ours ||
 
1948
                                old_icon->match != match_list)) {
 
1949
                RedoIconName();
 
1950
                return;
 
1951
        }
 
1952
        icon = NULL;
 
1953
        if((pattern = LookPatternInNameList(Scr->IconNames, Tmp_win->icon_name))) {
 
1954
                icon = (Icon *) LookInNameList(Tmp_win->iconslist, pattern);
 
1955
        }
 
1956
        else if((pattern = LookPatternInNameList(Scr->IconNames, Tmp_win->full_name))) {
 
1957
                icon = (Icon *) LookInNameList(Tmp_win->iconslist, pattern);
 
1958
        }
 
1959
        else if((pattern = LookPatternInList(Scr->IconNames, Tmp_win->full_name,
 
1960
                                             &Tmp_win->class))) {
 
1961
                icon = (Icon *) LookInNameList(Tmp_win->iconslist, pattern);
 
1962
        }
 
1963
        if(pattern == NULL) {
 
1964
                RedoIconName();
 
1965
                return;
 
1966
        }
 
1967
        if(icon != NULL) {
 
1968
                if(old_icon == icon) {
 
1969
                        RedoIconName();
 
1970
                        return;
 
1971
                }
 
1972
                if(Tmp_win->icon_on && visible(Tmp_win)) {
 
1973
                        IconDown(Tmp_win);
 
1974
                        if(old_icon && old_icon->w) {
 
1975
                                XUnmapWindow(dpy, old_icon->w);
 
1976
                        }
 
1977
                        Tmp_win->icon = icon;
 
1978
                        OtpReassignIcon(Tmp_win, old_icon);
 
1979
                        IconUp(Tmp_win);
 
1980
                        OtpRaise(Tmp_win, IconWin);
 
1981
                        XMapWindow(dpy, Tmp_win->icon->w);
 
1982
                }
 
1983
                else {
 
1984
                        Tmp_win->icon = icon;
 
1985
                        OtpReassignIcon(Tmp_win, old_icon);
 
1986
                }
 
1987
                RedoIconName();
 
1988
        }
 
1989
        else {
 
1990
                if(Tmp_win->icon_on && visible(Tmp_win)) {
 
1991
                        IconDown(Tmp_win);
 
1992
                        if(old_icon && old_icon->w) {
 
1993
                                XUnmapWindow(dpy, old_icon->w);
 
1994
                        }
 
1995
                        /*
 
1996
                         * If the icon name/class was found on one of the above lists,
 
1997
                         * the call to CreateIconWindow() will find it again there
 
1998
                         * and keep track of it on Tmp_win->iconslist for eventual
 
1999
                         * deallocation. (It is now checked that the current struct
 
2000
                         * Icon is also already on that list)
 
2001
                         */
 
2002
                        OtpFreeIcon(Tmp_win);
 
2003
                        int saveForceIcon = Scr->ForceIcon;
 
2004
                        Scr->ForceIcon = true;
 
2005
                        CreateIconWindow(Tmp_win, -100, -100);
 
2006
                        Scr->ForceIcon = saveForceIcon;
 
2007
                        OtpRaise(Tmp_win, IconWin);
 
2008
                        XMapWindow(dpy, Tmp_win->icon->w);
 
2009
                }
 
2010
                else {
 
2011
                        OtpFreeIcon(Tmp_win);
 
2012
                        Tmp_win->icon = NULL;
 
2013
                        WMapUpdateIconName(Tmp_win);
 
2014
                }
 
2015
                RedoIconName();
 
2016
        }
 
2017
}
 
2018
 
 
2019
/***********************************************************************
 
2020
 *
 
2021
 *  Procedure:
 
2022
 *      RedoIconName - procedure to re-position the icon window and name
 
2023
 *
 
2024
 ***********************************************************************
 
2025
 */
 
2026
 
 
2027
void RedoIconName(void)
 
2028
{
 
2029
        int x;
 
2030
        XRectangle ink_rect;
 
2031
        XRectangle logical_rect;
 
2032
 
 
2033
        if(Scr->NoIconTitlebar ||
 
2034
                        LookInNameList(Scr->NoIconTitle, Tmp_win->icon_name) ||
 
2035
                        LookInList(Scr->NoIconTitle, Tmp_win->full_name, &Tmp_win->class)) {
 
2036
                goto wmapupd;
 
2037
        }
 
2038
        if(Tmp_win->iconmanagerlist) {
 
2039
                /* let the expose event cause the repaint */
 
2040
                XClearArea(dpy, Tmp_win->iconmanagerlist->w, 0, 0, 0, 0, True);
 
2041
 
 
2042
                if(Scr->SortIconMgr) {
 
2043
                        SortIconManager(Tmp_win->iconmanagerlist->iconmgr);
 
2044
                }
 
2045
        }
 
2046
 
 
2047
        if(!Tmp_win->icon  || !Tmp_win->icon->w) {
 
2048
                goto wmapupd;
 
2049
        }
 
2050
 
 
2051
        if(Tmp_win->icon->w_not_ours) {
 
2052
                goto wmapupd;
 
2053
        }
 
2054
 
 
2055
        XmbTextExtents(Scr->IconFont.font_set,
 
2056
                       Tmp_win->icon_name, strlen(Tmp_win->icon_name),
 
2057
                       &ink_rect, &logical_rect);
 
2058
        Tmp_win->icon->w_width = logical_rect.width;
 
2059
        Tmp_win->icon->w_width += 2 * (Scr->IconManagerShadowDepth + ICON_MGR_IBORDER);
 
2060
        if(Tmp_win->icon->w_width > Scr->MaxIconTitleWidth) {
 
2061
                Tmp_win->icon->w_width = Scr->MaxIconTitleWidth;
 
2062
        }
 
2063
 
 
2064
        if(Tmp_win->icon->w_width < Tmp_win->icon->width) {
 
2065
                Tmp_win->icon->x = (Tmp_win->icon->width - Tmp_win->icon->w_width) / 2;
 
2066
                Tmp_win->icon->x += Scr->IconManagerShadowDepth + ICON_MGR_IBORDER;
 
2067
                Tmp_win->icon->w_width = Tmp_win->icon->width;
 
2068
        }
 
2069
        else {
 
2070
                Tmp_win->icon->x = Scr->IconManagerShadowDepth + ICON_MGR_IBORDER;
 
2071
        }
 
2072
 
 
2073
        x = GetIconOffset(Tmp_win->icon);
 
2074
        Tmp_win->icon->y = Tmp_win->icon->height + Scr->IconFont.height +
 
2075
                           Scr->IconManagerShadowDepth;
 
2076
        Tmp_win->icon->w_height = Tmp_win->icon->height + Scr->IconFont.height +
 
2077
                                  2 * (Scr->IconManagerShadowDepth + ICON_MGR_IBORDER);
 
2078
 
 
2079
        XResizeWindow(dpy, Tmp_win->icon->w, Tmp_win->icon->w_width,
 
2080
                      Tmp_win->icon->w_height);
 
2081
        if(Tmp_win->icon->bm_w) {
 
2082
                XRectangle rect;
 
2083
 
 
2084
                XMoveWindow(dpy, Tmp_win->icon->bm_w, x, 0);
 
2085
                XMapWindow(dpy, Tmp_win->icon->bm_w);
 
2086
                if(Tmp_win->icon->image && Tmp_win->icon->image->mask) {
 
2087
                        XShapeCombineMask(dpy, Tmp_win->icon->bm_w, ShapeBounding, 0, 0,
 
2088
                                          Tmp_win->icon->image->mask, ShapeSet);
 
2089
                        XShapeCombineMask(dpy, Tmp_win->icon->w, ShapeBounding, x, 0,
 
2090
                                          Tmp_win->icon->image->mask, ShapeSet);
 
2091
                }
 
2092
                else if(Tmp_win->icon->has_title) {
 
2093
                        rect.x      = x;
 
2094
                        rect.y      = 0;
 
2095
                        rect.width  = Tmp_win->icon->width;
 
2096
                        rect.height = Tmp_win->icon->height;
 
2097
                        XShapeCombineRectangles(dpy, Tmp_win->icon->w, ShapeBounding,
 
2098
                                                0, 0, &rect, 1, ShapeSet, 0);
 
2099
                }
 
2100
                if(Tmp_win->icon->has_title) {
 
2101
                        if(Scr->ShrinkIconTitles && Tmp_win->icon->title_shrunk) {
 
2102
                                rect.x      = x;
 
2103
                                rect.y      = Tmp_win->icon->height;
 
2104
                                rect.width  = Tmp_win->icon->width;
 
2105
                                rect.height = Tmp_win->icon->w_height - Tmp_win->icon->height;
 
2106
                        }
 
2107
                        else {
 
2108
                                rect.x      = 0;
 
2109
                                rect.y      = Tmp_win->icon->height;
 
2110
                                rect.width  = Tmp_win->icon->w_width;
 
2111
                                rect.height = Tmp_win->icon->w_height - Tmp_win->icon->height;
 
2112
                        }
 
2113
                        XShapeCombineRectangles(dpy,  Tmp_win->icon->w, ShapeBounding, 0,
 
2114
                                                0, &rect, 1, ShapeUnion, 0);
 
2115
                }
 
2116
        }
 
2117
        if(Scr->ShrinkIconTitles &&
 
2118
                        Tmp_win->icon->title_shrunk &&
 
2119
                        Tmp_win->icon_on && (visible(Tmp_win))) {
 
2120
                IconDown(Tmp_win);
 
2121
                IconUp(Tmp_win);
 
2122
        }
 
2123
        if(Tmp_win->isicon) {
 
2124
                XClearArea(dpy, Tmp_win->icon->w, 0, 0, 0, 0, True);
 
2125
        }
 
2126
wmapupd:
 
2127
        WMapUpdateIconName(Tmp_win);
 
2128
}
 
2129
 
 
2130
 
1401
2131
/***********************************************************************
1402
2132
 *
1403
2133
 *  Procedure:
1776
2506
}
1777
2507
 
1778
2508
 
1779
 
void
1780
 
HandleCreateNotify(void)
 
2509
void HandleCreateNotify(void)
1781
2510
{
1782
2511
#ifdef DEBUG_EVENTS
1783
2512
        fprintf(stderr, "CreateNotify w = 0x%x\n",
1830
2559
                 * in the icon manager.  Add it again, if requested.
1831
2560
                 */
1832
2561
                if(Tmp_win->iconmanagerlist == NULL) {
1833
 
                        AddIconManager(Tmp_win);
 
2562
                        (void) AddIconManager(Tmp_win);
1834
2563
                }
1835
2564
        }
1836
2565
 
1938
2667
}
1939
2668
 
1940
2669
 
 
2670
void SimulateMapRequest(Window w)
 
2671
{
 
2672
        Event.xmaprequest.window = w;
 
2673
        HandleMapRequest();
 
2674
}
 
2675
 
 
2676
 
1941
2677
/***********************************************************************
1942
2678
 *
1943
2679
 *  Procedure:
2396
3132
                int h = Scr->TBInfo.width - Scr->TBInfo.border;
2397
3133
                Window child;
2398
3134
 
2399
 
                XTranslateCoordinates(dpy, w, Scr->Root, 0, h, &x, &y, &child);
 
3135
                (void) XTranslateCoordinates(dpy, w, Scr->Root, 0, h, &x, &y, &child);
2400
3136
                center = false;
2401
3137
        }
2402
3138
        else {
2424
3160
                int h = Scr->TBInfo.width - Scr->TBInfo.border;
2425
3161
                Window child;
2426
3162
 
2427
 
                XTranslateCoordinates(dpy, w, Scr->Root, 0, h, &x, &y, &child);
 
3163
                (void) XTranslateCoordinates(dpy, w, Scr->Root, 0, h, &x, &y, &child);
2428
3164
                center = false;
2429
3165
        }
2430
3166
        else {
2925
3661
                 */
2926
3662
                scanArgs.w = ewp->window;
2927
3663
                scanArgs.leaves = scanArgs.enters = False;
2928
 
                XCheckIfEvent(dpy, &dummy, HENQueueScanner, (void *) &scanArgs);
 
3664
                (void) XCheckIfEvent(dpy, &dummy, HENQueueScanner, (void *) &scanArgs);
2929
3665
 
2930
3666
                /*
2931
3667
                 * if entering root window, restore twm default colormap so that
2997
3733
                                                /* Did we leave this window already? */
2998
3734
                                                scanArgs.w = ewp->window;
2999
3735
                                                scanArgs.leaves = scanArgs.enters = False;
3000
 
                                                XCheckIfEvent(dpy, &dummy, HENQueueScanner,
3001
 
                                                              (void *) &scanArgs);
 
3736
                                                (void) XCheckIfEvent(dpy, &dummy, HENQueueScanner,
 
3737
                                                                     (void *) &scanArgs);
3002
3738
                                                if(scanArgs.leaves && !scanArgs.inferior) {
3003
3739
                                                        return;
3004
3740
                                                }
3025
3761
                         */
3026
3762
                        scanArgs.w = ewp->window;
3027
3763
                        scanArgs.leaves = scanArgs.enters = False;
3028
 
                        XCheckIfEvent(dpy, &dummy, HENQueueScanner, (void *) &scanArgs);
 
3764
                        (void) XCheckIfEvent(dpy, &dummy, HENQueueScanner, (void *) &scanArgs);
3029
3765
 
3030
3766
                        /*
3031
3767
                         * if entering root window, restore twm default colormap so that
3393
4129
                                 */
3394
4130
                                scanArgs.w = Event.xcrossing.window;
3395
4131
                                scanArgs.enters = scanArgs.matches = False;
3396
 
                                XCheckIfEvent(dpy, &dummy, HLNQueueScanner,
3397
 
                                              (char *) &scanArgs);
 
4132
                                (void) XCheckIfEvent(dpy, &dummy, HLNQueueScanner,
 
4133
                                                     (char *) &scanArgs);
3398
4134
 
3399
4135
                                if(Event.xcrossing.window == Tmp_win->frame && !scanArgs.matches) {
3400
4136
                                        if(Scr->TitleFocus ||
3625
4361
 *
3626
4362
 ***********************************************************************
3627
4363
 */
3628
 
void
3629
 
HandleShapeNotify(void)
 
4364
void HandleShapeNotify(void)
3630
4365
{
3631
4366
        XShapeEvent     *sev = (XShapeEvent *) &Event;
3632
4367
 
3652
4387
 ***********************************************************************
3653
4388
 */
3654
4389
#ifdef EWMH
3655
 
void
3656
 
HandleSelectionClear(void)
 
4390
void HandleSelectionClear(void)
3657
4391
{
3658
4392
        XSelectionClearEvent    *sev = (XSelectionClearEvent *) &Event;
3659
4393
 
3680
4414
}
3681
4415
 
3682
4416
 
 
4417
/***********************************************************************
 
4418
 *
 
4419
 *  Procedure:
 
4420
 *      Transient - checks to see if the window is a transient
 
4421
 *
 
4422
 *  Returned Value:
 
4423
 *      true    - window is a transient
 
4424
 *      false   - window is not a transient
 
4425
 *
 
4426
 *  Inputs:
 
4427
 *      w       - the window to check
 
4428
 *
 
4429
 ***********************************************************************
 
4430
 */
 
4431
 
 
4432
bool
 
4433
Transient(Window w, Window *propw)
 
4434
{
 
4435
        return (bool)XGetTransientForHint(dpy, w, propw);
 
4436
}
 
4437
 
 
4438
 
 
4439
/***********************************************************************
 
4440
 *
 
4441
 *  Procedure:
 
4442
 *      FindScreenInfo - get ScreenInfo struct associated with a given window
 
4443
 *
 
4444
 *  Returned Value:
 
4445
 *      ScreenInfo struct
 
4446
 *
 
4447
 *  Inputs:
 
4448
 *      w       - the window
 
4449
 *
 
4450
 ***********************************************************************
 
4451
 */
 
4452
 
 
4453
ScreenInfo *FindScreenInfo(Window w)
 
4454
{
 
4455
        XWindowAttributes attr;
 
4456
        int scrnum;
 
4457
 
 
4458
        attr.screen = NULL;
 
4459
        if(XGetWindowAttributes(dpy, w, &attr)) {
 
4460
                for(scrnum = 0; scrnum < NumScreens; scrnum++) {
 
4461
                        if(ScreenList[scrnum] != NULL &&
 
4462
                                        (ScreenOfDisplay(dpy, ScreenList[scrnum]->screen) ==
 
4463
                                         attr.screen)) {
 
4464
                                return ScreenList[scrnum];
 
4465
                        }
 
4466
                }
 
4467
        }
 
4468
 
 
4469
        return NULL;
 
4470
}
 
4471
 
 
4472
 
3683
4473
static void flush_expose(Window w)
3684
4474
{
3685
4475
        XEvent dummy;
3688
4478
                /* nada */;
3689
4479
        }
3690
4480
}
 
4481
 
 
4482
 
 
4483
/***********************************************************************
 
4484
 *
 
4485
 *  Procedure:
 
4486
 *      InstallWindowColormaps - install the colormaps for one twm window
 
4487
 *
 
4488
 *  Inputs:
 
4489
 *      type    - type of event that caused the installation
 
4490
 *      tmp     - for a subset of event types, the address of the
 
4491
 *                window structure, whose colormaps are to be installed.
 
4492
 *
 
4493
 ***********************************************************************
 
4494
 */
 
4495
 
 
4496
int InstallWindowColormaps(int type, TwmWindow *tmp)
 
4497
{
 
4498
        if(tmp) {
 
4499
                return InstallColormaps(type, &tmp->cmaps);
 
4500
        }
 
4501
        else {
 
4502
                return InstallColormaps(type, NULL);
 
4503
        }
 
4504
}
 
4505
 
 
4506
int InstallColormaps(int type, Colormaps *cmaps)
 
4507
{
 
4508
        int i, j, n, number_cwins, state;
 
4509
        ColormapWindow **cwins, *cwin, **maxcwin = NULL;
 
4510
        TwmColormap *cmap;
 
4511
        char *row, *scoreboard;
 
4512
 
 
4513
        switch(type) {
 
4514
                case EnterNotify:
 
4515
                case LeaveNotify:
 
4516
                case DestroyNotify:
 
4517
                default:
 
4518
                        /* Save the colormap to be loaded for when force loading of
 
4519
                         * root colormap(s) ends.
 
4520
                         */
 
4521
                        Scr->cmapInfo.pushed_cmaps = cmaps;
 
4522
                        /* Don't load any new colormap if root colormap(s) has been
 
4523
                         * force loaded.
 
4524
                         */
 
4525
                        if(Scr->cmapInfo.root_pushes) {
 
4526
                                return (0);
 
4527
                        }
 
4528
                        /* Don't reload the current window colormap list.
 
4529
                        if (Scr->cmapInfo.cmaps == cmaps)
 
4530
                            return (0);
 
4531
                         */
 
4532
                        if(Scr->cmapInfo.cmaps) {
 
4533
                                for(i = Scr->cmapInfo.cmaps->number_cwins,
 
4534
                                                cwins = Scr->cmapInfo.cmaps->cwins; i-- > 0; cwins++) {
 
4535
                                        (*cwins)->colormap->state &= ~CM_INSTALLABLE;
 
4536
                                }
 
4537
                        }
 
4538
                        Scr->cmapInfo.cmaps = cmaps;
 
4539
                        break;
 
4540
 
 
4541
                case PropertyNotify:
 
4542
                case VisibilityNotify:
 
4543
                case ColormapNotify:
 
4544
                        break;
 
4545
        }
 
4546
 
 
4547
        number_cwins = Scr->cmapInfo.cmaps->number_cwins;
 
4548
        cwins = Scr->cmapInfo.cmaps->cwins;
 
4549
        scoreboard = Scr->cmapInfo.cmaps->scoreboard;
 
4550
 
 
4551
        ColortableThrashing = false; /* in case installation aborted */
 
4552
 
 
4553
        state = CM_INSTALLED;
 
4554
 
 
4555
        for(i = n = 0; i < number_cwins; i++) {
 
4556
                cwins[i]->colormap->state &= ~CM_INSTALL;
 
4557
        }
 
4558
        for(i = n = 0; i < number_cwins && n < Scr->cmapInfo.maxCmaps; i++) {
 
4559
                cwin = cwins[i];
 
4560
                cmap = cwin->colormap;
 
4561
                if(cmap->state & CM_INSTALL) {
 
4562
                        continue;
 
4563
                }
 
4564
                cmap->state |= CM_INSTALLABLE;
 
4565
                cmap->w = cwin->w;
 
4566
                if(cwin->visibility != VisibilityFullyObscured) {
 
4567
                        row = scoreboard + (i * (i - 1) / 2);
 
4568
                        for(j = 0; j < i; j++)
 
4569
                                if(row[j] && (cwins[j]->colormap->state & CM_INSTALL)) {
 
4570
                                        break;
 
4571
                                }
 
4572
                        if(j != i) {
 
4573
                                continue;
 
4574
                        }
 
4575
                        n++;
 
4576
                        maxcwin = &cwins[i];
 
4577
                        state &= (cmap->state & CM_INSTALLED);
 
4578
                        cmap->state |= CM_INSTALL;
 
4579
                }
 
4580
        }
 
4581
        Scr->cmapInfo.first_req = NextRequest(dpy);
 
4582
 
 
4583
        for(; n > 0 && maxcwin >= &cwins[0]; maxcwin--) {
 
4584
                cmap = (*maxcwin)->colormap;
 
4585
                if(cmap->state & CM_INSTALL) {
 
4586
                        cmap->state &= ~CM_INSTALL;
 
4587
                        if(!(state & CM_INSTALLED)) {
 
4588
                                cmap->install_req = NextRequest(dpy);
 
4589
                                /* printf ("XInstallColormap : %x, %x\n", cmap, cmap->c); */
 
4590
                                XInstallColormap(dpy, cmap->c);
 
4591
                        }
 
4592
                        cmap->state |= CM_INSTALLED;
 
4593
                        n--;
 
4594
                }
 
4595
        }
 
4596
        return (1);
 
4597
}
 
4598
 
 
4599
 
 
4600
/***********************************************************************
 
4601
 *
 
4602
 *  Procedures:
 
4603
 *      <Uni/I>nstallRootColormap - Force (un)loads root colormap(s)
 
4604
 *
 
4605
 *         These matching routines provide a mechanism to insure that
 
4606
 *         the root colormap(s) is installed during operations like
 
4607
 *         rubber banding or menu display that require colors from
 
4608
 *         that colormap.  Calls may be nested arbitrarily deeply,
 
4609
 *         as long as there is one UninstallRootColormap call per
 
4610
 *         InstallRootColormap call.
 
4611
 *
 
4612
 *         The final UninstallRootColormap will cause the colormap list
 
4613
 *         which would otherwise have be loaded to be loaded, unless
 
4614
 *         Enter or Leave Notify events are queued, indicating some
 
4615
 *         other colormap list would potentially be loaded anyway.
 
4616
 ***********************************************************************
 
4617
 */
 
4618
 
 
4619
void InstallRootColormap(void)
 
4620
{
 
4621
        Colormaps *tmp;
 
4622
        if(Scr->cmapInfo.root_pushes == 0) {
 
4623
                /*
 
4624
                 * The saving and restoring of cmapInfo.pushed_window here
 
4625
                 * is a slimy way to remember the actual pushed list and
 
4626
                 * not that of the root window.
 
4627
                 */
 
4628
                tmp = Scr->cmapInfo.pushed_cmaps;
 
4629
                InstallColormaps(0, &Scr->RootColormaps);
 
4630
                Scr->cmapInfo.pushed_cmaps = tmp;
 
4631
        }
 
4632
        Scr->cmapInfo.root_pushes++;
 
4633
}
 
4634
 
 
4635
 
 
4636
/* ARGSUSED*/
 
4637
static Bool UninstallRootColormapQScanner(Display *display, XEvent *ev,
 
4638
                char *args)
 
4639
{
 
4640
        if(!*args) {
 
4641
                if(ev->type == EnterNotify) {
 
4642
                        if(ev->xcrossing.mode != NotifyGrab) {
 
4643
                                *args = 1;
 
4644
                        }
 
4645
                }
 
4646
                else if(ev->type == LeaveNotify) {
 
4647
                        if(ev->xcrossing.mode == NotifyNormal) {
 
4648
                                *args = 1;
 
4649
                        }
 
4650
                }
 
4651
        }
 
4652
 
 
4653
        return (False);
 
4654
}
 
4655
 
 
4656
 
 
4657
void UninstallRootColormap(void)
 
4658
{
 
4659
        char args;
 
4660
        XEvent dummy;
 
4661
 
 
4662
        if(Scr->cmapInfo.root_pushes) {
 
4663
                Scr->cmapInfo.root_pushes--;
 
4664
        }
 
4665
 
 
4666
        if(!Scr->cmapInfo.root_pushes) {
 
4667
                /*
 
4668
                 * If we have subsequent Enter or Leave Notify events,
 
4669
                 * we can skip the reload of pushed colormaps.
 
4670
                 */
 
4671
                XSync(dpy, 0);
 
4672
                args = 0;
 
4673
                (void) XCheckIfEvent(dpy, &dummy, UninstallRootColormapQScanner, &args);
 
4674
 
 
4675
                if(!args) {
 
4676
                        InstallColormaps(0, Scr->cmapInfo.pushed_cmaps);
 
4677
                }
 
4678
        }
 
4679
}
 
4680
 
 
4681
void ConfigureRootWindow(XEvent *ev)
 
4682
{
 
4683
        Window       root, child;
 
4684
        int          x, y;
 
4685
        unsigned int w, h, bw, d, oldw, oldh;
 
4686
 
 
4687
        XGetGeometry(dpy, Scr->CaptiveRoot, &root, &x, &y, &w, &h, &bw, &d);
 
4688
        XTranslateCoordinates(dpy, Scr->CaptiveRoot, root, 0, 0, &Scr->crootx,
 
4689
                              &Scr->crooty, &child);
 
4690
 
 
4691
        oldw = Scr->crootw;
 
4692
        oldh = Scr->crooth;
 
4693
        Scr->crootw = ev->xconfigure.width;
 
4694
        Scr->crooth = ev->xconfigure.height;
 
4695
        /*
 
4696
        fprintf (stderr, "ConfigureRootWindow: cx = %d, cy = %d, cw = %d, ch = %d\n",
 
4697
             Scr->crootx, Scr->crooty, Scr->crootw, Scr->crooth);
 
4698
        */
 
4699
        if(Scr->currentvs) {
 
4700
                Scr->rootx = Scr->crootx + Scr->currentvs->x;
 
4701
                Scr->rooty = Scr->crooty + Scr->currentvs->y;
 
4702
        }
 
4703
        Scr->rootw = Scr->crootw;
 
4704
        Scr->rooth = Scr->crooth;
 
4705
 
 
4706
        if(CLarg.is_captive && ((Scr->crootw != oldw) || (Scr->crooth != oldh))) {
 
4707
                fprintf(stderr, "%s: You cannot change root window geometry "
 
4708
                        "with virtual screens active,\n"
 
4709
                        "from now on, the ctwm behaviour is unpredictable.\n",
 
4710
                        ProgramName);
 
4711
        }
 
4712
}
 
4713
 
 
4714
static void dumpevent(XEvent *e)
 
4715
{
 
4716
        const char *name = "Unknown event";
 
4717
 
 
4718
        if(! tracefile) {
 
4719
                return;
 
4720
        }
 
4721
 
 
4722
        /* Whatsit? */
 
4723
        name = event_name_by_num(e->type);
 
4724
        if(!name) {
 
4725
                name = "Unknown event";
 
4726
        }
 
4727
 
 
4728
        /* Tell about it */
 
4729
        fprintf(tracefile, "event:  %s in window 0x%x\n", name,
 
4730
                (unsigned int)e->xany.window);
 
4731
        switch(e->type) {
 
4732
                case KeyPress:
 
4733
                case KeyRelease:
 
4734
                        fprintf(tracefile, "     :  +%d,+%d (+%d,+%d)  state=%d, keycode=%d\n",
 
4735
                                e->xkey.x, e->xkey.y,
 
4736
                                e->xkey.x_root, e->xkey.y_root,
 
4737
                                e->xkey.state, e->xkey.keycode);
 
4738
                        break;
 
4739
                case ButtonPress:
 
4740
                case ButtonRelease:
 
4741
                        fprintf(tracefile, "     :  +%d,+%d (+%d,+%d)  state=%d, button=%d\n",
 
4742
                                e->xbutton.x, e->xbutton.y,
 
4743
                                e->xbutton.x_root, e->xbutton.y_root,
 
4744
                                e->xbutton.state, e->xbutton.button);
 
4745
                        break;
 
4746
        }
 
4747
}