73
73
#include <stdlib.h>
74
75
#include <sys/time.h>
76
77
#include <X11/Xatom.h>
77
78
#include <X11/extensions/shape.h>
80
#include "ctwm_atoms.h"
79
81
#include "add_window.h"
82
#include "decorations.h"
81
83
#include "clicktofocus.h"
82
#include "colormaps.h"
83
#include "ctwm_atoms.h"
84
#include "decorations.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"
92
94
#include "iconmgr.h"
96
#include "occupation.h"
103
#include "win_iconify.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"
104
#include "gram.tab.h"
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 */
114
/* Only called from HandleFocusChange() */
115
static void HandleFocusIn(void);
116
static void HandleFocusOut(void);
110
static bool StashEventTime(XEvent *ev);
112
FILE *tracefile = NULL;
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 */
119
XEvent Event; /* the current event */
120
static TwmWindow *Tmp_win; /* the current twm window */
122
Window DragWindow; /* variables used in moving windows */
127
unsigned int DragWidth;
128
unsigned int DragHeight;
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;
138
int ButtonPressed = -1;
141
void HandleCreateNotify(void);
142
void HandleShapeNotify(void);
143
void HandleFocusChange(void);
144
void HandleSelectionClear(void);
147
/*#define TRACE_FOCUS*/
150
static void dumpevent(XEvent *e);
122
152
static unsigned int set_mask_ignore(unsigned int modifier)
159
void AutoRaiseWindow(TwmWindow *tmp)
161
OtpRaise(tmp, WinWin);
163
if(ActiveMenu && ActiveMenu->w) {
164
XRaiseWindow(dpy, ActiveMenu->w);
173
void SetRaiseWindow(TwmWindow *tmp)
184
void AutoPopupMaybe(TwmWindow *tmp)
186
if(LookInList(Scr->AutoPopupL, tmp->full_name, &tmp->class)
188
if(OCCUPY(tmp, Scr->currentvs->wsw->currentwspc)) {
200
void AutoLowerWindow(TwmWindow *tmp)
202
OtpLower(tmp, WinWin);
204
if(ActiveMenu && ActiveMenu->w) {
205
XRaiseWindow(dpy, ActiveMenu->w);
218
/***********************************************************************
221
* InitEvents - initialize the event jump table
223
***********************************************************************
226
void InitEvents(void)
231
ResizeWindow = (Window) 0;
232
DragWindow = (Window) 0;
234
enter_win = raise_win = NULL;
236
leave_win = lower_win = NULL;
238
for(i = 0; i < MAX_X_EVENT; i++) {
239
EventHandler[i] = HandleUnknown;
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;
264
EventHandler[ShapeEventBase + ShapeNotify] = HandleShapeNotify;
267
EventHandler[SelectionClear] = HandleSelectionClear;
273
Time lastTimestamp = CurrentTime; /* until Xlib does this for us */
276
StashEventTime(XEvent *ev)
281
lastTimestamp = ev->xkey.time;
285
lastTimestamp = ev->xbutton.time;
288
lastTimestamp = ev->xmotion.time;
292
lastTimestamp = ev->xcrossing.time;
295
lastTimestamp = ev->xproperty.time;
298
lastTimestamp = ev->xselectionclear.time;
300
case SelectionRequest:
301
lastTimestamp = ev->xselectionrequest.time;
303
case SelectionNotify:
304
lastTimestamp = ev->xselection.time;
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
316
Window WindowOfEvent(XEvent *e)
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
326
return e->xkey.window; /* same */
329
return e->xbutton.window; /* same */
331
return e->xmotion.window; /* same */
334
return e->xcrossing.window; /* same */
337
return e->xfocus.window; /* same */
339
return e->xkeymap.window; /* same */
341
return e->xexpose.window; /* same */
343
return e->xgraphicsexpose.drawable; /* same */
345
return e->xnoexpose.drawable; /* same */
346
case VisibilityNotify:
347
return e->xvisibility.window; /* same */
349
return e->xcreatewindow.window; /* DIFF */
351
return e->xdestroywindow.window; /* DIFF */
353
return e->xunmap.window; /* DIFF */
355
return e->xmap.window; /* DIFF */
357
return e->xmaprequest.window; /* DIFF */
359
return e->xreparent.window; /* DIFF */
360
case ConfigureNotify:
361
return e->xconfigure.window; /* DIFF */
362
case ConfigureRequest:
363
return e->xconfigurerequest.window; /* DIFF */
365
return e->xgravity.window; /* DIFF */
367
return e->xresizerequest.window; /* same */
368
case CirculateNotify:
369
return e->xcirculate.window; /* DIFF */
370
case CirculateRequest:
371
return e->xcirculaterequest.window; /* DIFF */
373
return e->xproperty.window; /* same */
375
return e->xselectionclear.window; /* same */
376
case SelectionRequest:
377
return e->xselectionrequest.requestor; /* DIFF */
378
case SelectionNotify:
379
return e->xselection.requestor; /* same */
381
return e->xcolormap.window; /* same */
383
return e->xclient.window; /* same */
390
void FixRootEvent(XEvent *e)
392
if(Scr->Root == Scr->RealRoot) {
399
e->xkey.x_root -= Scr->rootx;
400
e->xkey.y_root -= Scr->rooty;
401
e->xkey.root = Scr->Root;
405
e->xbutton.x_root -= Scr->rootx;
406
e->xbutton.y_root -= Scr->rooty;
407
e->xbutton.root = Scr->Root;
410
e->xmotion.x_root -= Scr->rootx;
411
e->xmotion.y_root -= Scr->rooty;
412
e->xmotion.root = Scr->Root;
416
e->xcrossing.x_root -= Scr->rootx;
417
e->xcrossing.y_root -= Scr->rooty;
418
e->xcrossing.root = Scr->Root;
426
/* Move this next to GetTwmWindow()? */
427
static ScreenInfo *GetTwmScreen(XEvent *event)
431
if(XFindContext(dpy, event->xany.window, ScreenContext,
432
(XPointer *)&scr) == XCNOENT) {
433
scr = FindScreenInfo(WindowOfEvent(event));
439
/***********************************************************************
443
* handle a single X event stored in global var Event
444
* this routine for is for a call during an f.move
446
***********************************************************************
451
Window w = Event.xany.window;
454
StashEventTime(&Event);
455
Tmp_win = GetTwmWindow(w);
456
thisScr = GetTwmScreen(&Event);
465
FixRootEvent(&Event);
468
play_sound(Event.type);
471
if(menuFromFrameOrWindowOrTitlebar) {
472
if(Event.type == Expose) {
477
if(Event.type >= 0 && Event.type < MAX_X_EVENT) {
478
(*EventHandler[Event.type])();
485
/***********************************************************************
488
* DispatchEvent - handle a single X event stored in global var Event
490
***********************************************************************
495
Window w = Event.xany.window;
498
StashEventTime(&Event);
499
Tmp_win = GetTwmWindow(w);
500
thisScr = GetTwmScreen(&Event);
509
if(CLarg.is_captive) {
510
if((Event.type == ConfigureNotify)
511
&& (Event.xconfigure.window == Scr->CaptiveRoot)) {
512
ConfigureRootWindow(&Event);
516
FixRootEvent(&Event);
517
if(Event.type >= 0 && Event.type < MAX_X_EVENT) {
519
play_sound(Event.type);
521
(*EventHandler[Event.type])();
527
/***********************************************************************
530
* HandleEvents - handle X events
532
***********************************************************************
535
void HandleEvents(void)
538
if(enter_flag && !QLength(dpy)) {
539
if(enter_win && enter_win != raise_win) {
540
AutoRaiseWindow(enter_win); /* sets enter_flag T */
546
if(leave_flag && !QLength(dpy)) {
547
if(leave_win && leave_win != lower_win) {
548
AutoLowerWindow(leave_win); /* sets leave_flag T */
554
if(ColortableThrashing && !QLength(dpy) && Scr) {
555
InstallColormaps(ColormapNotify, NULL);
559
CtwmNextEvent(dpy, &Event);
561
if(Event.type < 0 || Event.type >= MAX_X_EVENT) {
562
XtDispatchEvent(&Event);
565
(void) DispatchEvent();
571
static void CtwmNextEvent(Display *display, XEvent *event)
576
struct timeval timeout, *tout = NULL;
577
const bool animate = (AnimationActive && MaybeAnimate);
579
#define nextEvent(event) XtAppNextEvent(appContext, event);
582
DoRestart(CurrentTime);
584
if(XEventsQueued(display, QueuedAfterFlush) != 0) {
588
fd = ConnectionNumber(display);
594
DoRestart(CurrentTime);
601
tout = (AnimationSpeed > 0) ? &timeout : NULL;
607
timeout = AnimateTimeout;
609
found = select(fd + 1, &mask, NULL, NULL, tout);
611
DoRestart(CurrentTime);
619
if(FD_ISSET(fd, &mask)) {
628
DoRestart(CurrentTime);
130
644
/***********************************************************************
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);
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);
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);
325
844
while(XCheckWindowEvent(dpy, w, FocusChangeMask, &new));
331
* Focus change handlers.
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.
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.
349
HandleFocusChange(void)
852
void HandleFocusIn(XFocusInEvent *event)
353
/* If there's no event window, nothing to do */
359
* Consume all the focus events for the window we're called about and
360
* grab the last one to process.
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?
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.
370
event = LastFocusEvent(Event.xany.window, &Event);
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.
381
if(Tmp_win->isiconmgr) {
385
855
#ifdef TRACE_FOCUS
386
fprintf(stderr, "HandleFocus%s(): 0x%x (0x%x, 0x%x), mode=%d, "
388
(event->type == FocusIn ? "In" : "Out"),
389
Tmp_win, Tmp_win->w, event->window, event->mode,
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);
393
/* And call actual handler */
394
if(event->type == FocusIn) {
860
if(Tmp_win->isiconmgr) {
406
863
if(Tmp_win->wmhints && ! Tmp_win->wmhints->input) {
1939
static void RedoIcon(void)
1941
Icon *icon, *old_icon;
1944
old_icon = Tmp_win->icon;
1947
old_icon->w_not_ours ||
1948
old_icon->match != match_list)) {
1953
if((pattern = LookPatternInNameList(Scr->IconNames, Tmp_win->icon_name))) {
1954
icon = (Icon *) LookInNameList(Tmp_win->iconslist, pattern);
1956
else if((pattern = LookPatternInNameList(Scr->IconNames, Tmp_win->full_name))) {
1957
icon = (Icon *) LookInNameList(Tmp_win->iconslist, pattern);
1959
else if((pattern = LookPatternInList(Scr->IconNames, Tmp_win->full_name,
1960
&Tmp_win->class))) {
1961
icon = (Icon *) LookInNameList(Tmp_win->iconslist, pattern);
1963
if(pattern == NULL) {
1968
if(old_icon == icon) {
1972
if(Tmp_win->icon_on && visible(Tmp_win)) {
1974
if(old_icon && old_icon->w) {
1975
XUnmapWindow(dpy, old_icon->w);
1977
Tmp_win->icon = icon;
1978
OtpReassignIcon(Tmp_win, old_icon);
1980
OtpRaise(Tmp_win, IconWin);
1981
XMapWindow(dpy, Tmp_win->icon->w);
1984
Tmp_win->icon = icon;
1985
OtpReassignIcon(Tmp_win, old_icon);
1990
if(Tmp_win->icon_on && visible(Tmp_win)) {
1992
if(old_icon && old_icon->w) {
1993
XUnmapWindow(dpy, old_icon->w);
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)
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);
2011
OtpFreeIcon(Tmp_win);
2012
Tmp_win->icon = NULL;
2013
WMapUpdateIconName(Tmp_win);
2019
/***********************************************************************
2022
* RedoIconName - procedure to re-position the icon window and name
2024
***********************************************************************
2027
void RedoIconName(void)
2030
XRectangle ink_rect;
2031
XRectangle logical_rect;
2033
if(Scr->NoIconTitlebar ||
2034
LookInNameList(Scr->NoIconTitle, Tmp_win->icon_name) ||
2035
LookInList(Scr->NoIconTitle, Tmp_win->full_name, &Tmp_win->class)) {
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);
2042
if(Scr->SortIconMgr) {
2043
SortIconManager(Tmp_win->iconmanagerlist->iconmgr);
2047
if(!Tmp_win->icon || !Tmp_win->icon->w) {
2051
if(Tmp_win->icon->w_not_ours) {
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;
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;
2070
Tmp_win->icon->x = Scr->IconManagerShadowDepth + ICON_MGR_IBORDER;
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);
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) {
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);
2092
else if(Tmp_win->icon->has_title) {
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);
2100
if(Tmp_win->icon->has_title) {
2101
if(Scr->ShrinkIconTitles && Tmp_win->icon->title_shrunk) {
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;
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;
2113
XShapeCombineRectangles(dpy, Tmp_win->icon->w, ShapeBounding, 0,
2114
0, &rect, 1, ShapeUnion, 0);
2117
if(Scr->ShrinkIconTitles &&
2118
Tmp_win->icon->title_shrunk &&
2119
Tmp_win->icon_on && (visible(Tmp_win))) {
2123
if(Tmp_win->isicon) {
2124
XClearArea(dpy, Tmp_win->icon->w, 0, 0, 0, 0, True);
2127
WMapUpdateIconName(Tmp_win);
1401
2131
/***********************************************************************
4483
/***********************************************************************
4486
* InstallWindowColormaps - install the colormaps for one twm window
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.
4493
***********************************************************************
4496
int InstallWindowColormaps(int type, TwmWindow *tmp)
4499
return InstallColormaps(type, &tmp->cmaps);
4502
return InstallColormaps(type, NULL);
4506
int InstallColormaps(int type, Colormaps *cmaps)
4508
int i, j, n, number_cwins, state;
4509
ColormapWindow **cwins, *cwin, **maxcwin = NULL;
4511
char *row, *scoreboard;
4518
/* Save the colormap to be loaded for when force loading of
4519
* root colormap(s) ends.
4521
Scr->cmapInfo.pushed_cmaps = cmaps;
4522
/* Don't load any new colormap if root colormap(s) has been
4525
if(Scr->cmapInfo.root_pushes) {
4528
/* Don't reload the current window colormap list.
4529
if (Scr->cmapInfo.cmaps == cmaps)
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;
4538
Scr->cmapInfo.cmaps = cmaps;
4541
case PropertyNotify:
4542
case VisibilityNotify:
4543
case ColormapNotify:
4547
number_cwins = Scr->cmapInfo.cmaps->number_cwins;
4548
cwins = Scr->cmapInfo.cmaps->cwins;
4549
scoreboard = Scr->cmapInfo.cmaps->scoreboard;
4551
ColortableThrashing = false; /* in case installation aborted */
4553
state = CM_INSTALLED;
4555
for(i = n = 0; i < number_cwins; i++) {
4556
cwins[i]->colormap->state &= ~CM_INSTALL;
4558
for(i = n = 0; i < number_cwins && n < Scr->cmapInfo.maxCmaps; i++) {
4560
cmap = cwin->colormap;
4561
if(cmap->state & CM_INSTALL) {
4564
cmap->state |= CM_INSTALLABLE;
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)) {
4576
maxcwin = &cwins[i];
4577
state &= (cmap->state & CM_INSTALLED);
4578
cmap->state |= CM_INSTALL;
4581
Scr->cmapInfo.first_req = NextRequest(dpy);
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);
4592
cmap->state |= CM_INSTALLED;
4600
/***********************************************************************
4603
* <Uni/I>nstallRootColormap - Force (un)loads root colormap(s)
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.
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
***********************************************************************
4619
void InstallRootColormap(void)
4622
if(Scr->cmapInfo.root_pushes == 0) {
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.
4628
tmp = Scr->cmapInfo.pushed_cmaps;
4629
InstallColormaps(0, &Scr->RootColormaps);
4630
Scr->cmapInfo.pushed_cmaps = tmp;
4632
Scr->cmapInfo.root_pushes++;
4637
static Bool UninstallRootColormapQScanner(Display *display, XEvent *ev,
4641
if(ev->type == EnterNotify) {
4642
if(ev->xcrossing.mode != NotifyGrab) {
4646
else if(ev->type == LeaveNotify) {
4647
if(ev->xcrossing.mode == NotifyNormal) {
4657
void UninstallRootColormap(void)
4662
if(Scr->cmapInfo.root_pushes) {
4663
Scr->cmapInfo.root_pushes--;
4666
if(!Scr->cmapInfo.root_pushes) {
4668
* If we have subsequent Enter or Leave Notify events,
4669
* we can skip the reload of pushed colormaps.
4673
(void) XCheckIfEvent(dpy, &dummy, UninstallRootColormapQScanner, &args);
4676
InstallColormaps(0, Scr->cmapInfo.pushed_cmaps);
4681
void ConfigureRootWindow(XEvent *ev)
4685
unsigned int w, h, bw, d, oldw, oldh;
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);
4693
Scr->crootw = ev->xconfigure.width;
4694
Scr->crooth = ev->xconfigure.height;
4696
fprintf (stderr, "ConfigureRootWindow: cx = %d, cy = %d, cw = %d, ch = %d\n",
4697
Scr->crootx, Scr->crooty, Scr->crootw, Scr->crooth);
4699
if(Scr->currentvs) {
4700
Scr->rootx = Scr->crootx + Scr->currentvs->x;
4701
Scr->rooty = Scr->crooty + Scr->currentvs->y;
4703
Scr->rootw = Scr->crootw;
4704
Scr->rooth = Scr->crooth;
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",
4714
static void dumpevent(XEvent *e)
4716
const char *name = "Unknown event";
4723
name = event_name_by_num(e->type);
4725
name = "Unknown event";
4729
fprintf(tracefile, "event: %s in window 0x%x\n", name,
4730
(unsigned int)e->xany.window);
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);
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);