1/*
2 * Various util-ish functions for event handling.
3 *
4 * Many, probably most, are internal to the event code, but a few are
5 * used elsewhere.
6 */
7
8#include "ctwm.h"
9
10#include <stdio.h>
11
12#include "event_handlers.h"
13#include "event_internal.h"
14#include "events.h"
15#include "list.h"
16#include "otp.h"
17#include "screen.h"
18#include "vscreen.h"
19#include "win_iconify.h"
20#include "workspace_manager.h"
21
22
23static ScreenInfo *FindScreenInfo(Window w);
24
25
26void
27AutoRaiseWindow(TwmWindow *tmp)
28{
29	OtpRaise(tmp, WinWin);
30
31	if(ActiveMenu && ActiveMenu->w) {
32		XRaiseWindow(dpy, ActiveMenu->w);
33	}
34	XSync(dpy, 0);
35	enter_win = NULL;
36	enter_flag = true;
37	raise_win = tmp;
38	WMapRaise(tmp);
39}
40
41void
42SetRaiseWindow(TwmWindow *tmp)
43{
44	enter_flag = true;
45	enter_win = NULL;
46	raise_win = tmp;
47	leave_win = NULL;
48	leave_flag = false;
49	lower_win = NULL;
50	XSync(dpy, 0);
51}
52
53void
54AutoPopupMaybe(TwmWindow *tmp)
55{
56	if(LookInList(Scr->AutoPopupL, tmp->name, &tmp->class)
57	                || Scr->AutoPopup) {
58		if(OCCUPY(tmp, Scr->currentvs->wsw->currentwspc)) {
59			if(!tmp->mapped) {
60				DeIconify(tmp);
61				SetRaiseWindow(tmp);
62			}
63		}
64		else {
65			tmp->mapped = true;
66		}
67	}
68}
69
70void
71AutoLowerWindow(TwmWindow *tmp)
72{
73	OtpLower(tmp, WinWin);
74
75	if(ActiveMenu && ActiveMenu->w) {
76		XRaiseWindow(dpy, ActiveMenu->w);
77	}
78	XSync(dpy, 0);
79	enter_win = NULL;
80	enter_flag = false;
81	raise_win = NULL;
82	leave_win = NULL;
83	leave_flag = true;
84	lower_win = tmp;
85	WMapLower(tmp);
86}
87
88
89/*
90 * WindowOfEvent - return the window about which this event is concerned; this
91 * window may not be the same as XEvent.xany.window (the first window listed
92 * in the structure).
93 */
94Window
95WindowOfEvent(XEvent *e)
96{
97	/*
98	 * Each window subfield is marked with whether or not it is the same as
99	 * XEvent.xany.window or is different (which is the case for some of the
100	 * notify events).
101	 */
102	switch(e->type) {
103		case KeyPress:
104		case KeyRelease:
105			return e->xkey.window;                       /* same */
106		case ButtonPress:
107		case ButtonRelease:
108			return e->xbutton.window;                 /* same */
109		case MotionNotify:
110			return e->xmotion.window;                  /* same */
111		case EnterNotify:
112		case LeaveNotify:
113			return e->xcrossing.window;                 /* same */
114		case FocusIn:
115		case FocusOut:
116			return e->xfocus.window;                       /* same */
117		case KeymapNotify:
118			return e->xkeymap.window;                  /* same */
119		case Expose:
120			return e->xexpose.window;                        /* same */
121		case GraphicsExpose:
122			return e->xgraphicsexpose.drawable;      /* same */
123		case NoExpose:
124			return e->xnoexpose.drawable;                  /* same */
125		case VisibilityNotify:
126			return e->xvisibility.window;          /* same */
127		case CreateNotify:
128			return e->xcreatewindow.window;            /* DIFF */
129		case DestroyNotify:
130			return e->xdestroywindow.window;          /* DIFF */
131		case UnmapNotify:
132			return e->xunmap.window;                    /* DIFF */
133		case MapNotify:
134			return e->xmap.window;                        /* DIFF */
135		case MapRequest:
136			return e->xmaprequest.window;                /* DIFF */
137		case ReparentNotify:
138			return e->xreparent.window;              /* DIFF */
139		case ConfigureNotify:
140			return e->xconfigure.window;            /* DIFF */
141		case ConfigureRequest:
142			return e->xconfigurerequest.window;    /* DIFF */
143		case GravityNotify:
144			return e->xgravity.window;                /* DIFF */
145		case ResizeRequest:
146			return e->xresizerequest.window;          /* same */
147		case CirculateNotify:
148			return e->xcirculate.window;            /* DIFF */
149		case CirculateRequest:
150			return e->xcirculaterequest.window;    /* DIFF */
151		case PropertyNotify:
152			return e->xproperty.window;              /* same */
153		case SelectionClear:
154			return e->xselectionclear.window;        /* same */
155		case SelectionRequest:
156			return e->xselectionrequest.requestor;  /* DIFF */
157		case SelectionNotify:
158			return e->xselection.requestor;         /* same */
159		case ColormapNotify:
160			return e->xcolormap.window;              /* same */
161		case ClientMessage:
162			return e->xclient.window;                 /* same */
163		case MappingNotify:
164			return None;
165	}
166	return None;
167}
168
169
170void
171FixRootEvent(XEvent *e)
172{
173	if(Scr->Root == Scr->RealRoot) {
174		return;
175	}
176
177	switch(e->type) {
178		case KeyPress:
179		case KeyRelease:
180			e->xkey.x_root -= Scr->rootx;
181			e->xkey.y_root -= Scr->rooty;
182			e->xkey.root    = Scr->Root;
183			break;
184		case ButtonPress:
185		case ButtonRelease:
186			e->xbutton.x_root -= Scr->rootx;
187			e->xbutton.y_root -= Scr->rooty;
188			e->xbutton.root    = Scr->Root;
189			break;
190		case MotionNotify:
191			e->xmotion.x_root -= Scr->rootx;
192			e->xmotion.y_root -= Scr->rooty;
193			e->xmotion.root    = Scr->Root;
194			break;
195		case EnterNotify:
196		case LeaveNotify:
197			e->xcrossing.x_root -= Scr->rootx;
198			e->xcrossing.y_root -= Scr->rooty;
199			e->xcrossing.root    = Scr->Root;
200			break;
201		default:
202			break;
203	}
204}
205
206
207/* Move this next to GetTwmWindow()? */
208ScreenInfo *
209GetTwmScreen(XEvent *event)
210{
211	ScreenInfo *scr;
212
213	if(XFindContext(dpy, event->xany.window, ScreenContext,
214	                (XPointer *)&scr) == XCNOENT) {
215		scr = FindScreenInfo(WindowOfEvent(event));
216	}
217
218	return scr;
219}
220
221
222/***********************************************************************
223 *
224 *  Procedure:
225 *      FindScreenInfo - get ScreenInfo struct associated with a given window
226 *
227 *  Returned Value:
228 *      ScreenInfo struct
229 *
230 *  Inputs:
231 *      w       - the window
232 *
233 ***********************************************************************
234 */
235static ScreenInfo *
236FindScreenInfo(Window w)
237{
238	XWindowAttributes attr;
239	int scrnum;
240
241	attr.screen = NULL;
242	if(XGetWindowAttributes(dpy, w, &attr)) {
243		for(scrnum = 0; scrnum < NumScreens; scrnum++) {
244			if(ScreenList[scrnum] != NULL &&
245			                (ScreenOfDisplay(dpy, ScreenList[scrnum]->screen) ==
246			                 attr.screen)) {
247				return ScreenList[scrnum];
248			}
249		}
250	}
251
252	return NULL;
253}
254
255
256void
257SynthesiseFocusOut(Window w)
258{
259	XEvent event;
260
261#ifdef TRACE_FOCUS
262	fprintf(stderr, "Synthesizing FocusOut on %x\n", w);
263#endif
264
265	event.type = FocusOut;
266	event.xfocus.window = w;
267	event.xfocus.mode = NotifyNormal;
268	event.xfocus.detail = NotifyPointer;
269
270	XPutBackEvent(dpy, &event);
271}
272
273
274void
275SynthesiseFocusIn(Window w)
276{
277	XEvent event;
278
279#ifdef TRACE_FOCUS
280	fprintf(stderr, "Synthesizing FocusIn on %x\n", w);
281#endif
282
283	event.type = FocusIn;
284	event.xfocus.window = w;
285	event.xfocus.mode = NotifyNormal;
286	event.xfocus.detail = NotifyPointer;
287
288	XPutBackEvent(dpy, &event);
289
290}
291
292
293/*
294 * This is actually never called anywhere in event code, but it digs into
295 * the innards of events to do somewhat scary things.
296 */
297void
298SimulateMapRequest(Window w)
299{
300	Event.xmaprequest.window = w;
301	HandleMapRequest();
302}
303