10bbfda8aSnia/*
20bbfda8aSnia * Various util-ish functions for event handling.
30bbfda8aSnia *
40bbfda8aSnia * Many, probably most, are internal to the event code, but a few are
50bbfda8aSnia * used elsewhere.
60bbfda8aSnia */
70bbfda8aSnia
80bbfda8aSnia#include "ctwm.h"
90bbfda8aSnia
100bbfda8aSnia#include <stdio.h>
110bbfda8aSnia
120bbfda8aSnia#include "event_handlers.h"
130bbfda8aSnia#include "event_internal.h"
140bbfda8aSnia#include "events.h"
150bbfda8aSnia#include "list.h"
160bbfda8aSnia#include "otp.h"
170bbfda8aSnia#include "screen.h"
180bbfda8aSnia#include "vscreen.h"
190bbfda8aSnia#include "win_iconify.h"
200bbfda8aSnia#include "workspace_manager.h"
210bbfda8aSnia
220bbfda8aSnia
230bbfda8aSniastatic ScreenInfo *FindScreenInfo(Window w);
240bbfda8aSnia
250bbfda8aSnia
260bbfda8aSniavoid
270bbfda8aSniaAutoRaiseWindow(TwmWindow *tmp)
280bbfda8aSnia{
290bbfda8aSnia	OtpRaise(tmp, WinWin);
300bbfda8aSnia
310bbfda8aSnia	if(ActiveMenu && ActiveMenu->w) {
320bbfda8aSnia		XRaiseWindow(dpy, ActiveMenu->w);
330bbfda8aSnia	}
340bbfda8aSnia	XSync(dpy, 0);
350bbfda8aSnia	enter_win = NULL;
360bbfda8aSnia	enter_flag = true;
370bbfda8aSnia	raise_win = tmp;
380bbfda8aSnia	WMapRaise(tmp);
390bbfda8aSnia}
400bbfda8aSnia
410bbfda8aSniavoid
420bbfda8aSniaSetRaiseWindow(TwmWindow *tmp)
430bbfda8aSnia{
440bbfda8aSnia	enter_flag = true;
450bbfda8aSnia	enter_win = NULL;
460bbfda8aSnia	raise_win = tmp;
470bbfda8aSnia	leave_win = NULL;
480bbfda8aSnia	leave_flag = false;
490bbfda8aSnia	lower_win = NULL;
500bbfda8aSnia	XSync(dpy, 0);
510bbfda8aSnia}
520bbfda8aSnia
530bbfda8aSniavoid
540bbfda8aSniaAutoPopupMaybe(TwmWindow *tmp)
550bbfda8aSnia{
560bbfda8aSnia	if(LookInList(Scr->AutoPopupL, tmp->name, &tmp->class)
570bbfda8aSnia	                || Scr->AutoPopup) {
580bbfda8aSnia		if(OCCUPY(tmp, Scr->currentvs->wsw->currentwspc)) {
590bbfda8aSnia			if(!tmp->mapped) {
600bbfda8aSnia				DeIconify(tmp);
610bbfda8aSnia				SetRaiseWindow(tmp);
620bbfda8aSnia			}
630bbfda8aSnia		}
640bbfda8aSnia		else {
650bbfda8aSnia			tmp->mapped = true;
660bbfda8aSnia		}
670bbfda8aSnia	}
680bbfda8aSnia}
690bbfda8aSnia
700bbfda8aSniavoid
710bbfda8aSniaAutoLowerWindow(TwmWindow *tmp)
720bbfda8aSnia{
730bbfda8aSnia	OtpLower(tmp, WinWin);
740bbfda8aSnia
750bbfda8aSnia	if(ActiveMenu && ActiveMenu->w) {
760bbfda8aSnia		XRaiseWindow(dpy, ActiveMenu->w);
770bbfda8aSnia	}
780bbfda8aSnia	XSync(dpy, 0);
790bbfda8aSnia	enter_win = NULL;
800bbfda8aSnia	enter_flag = false;
810bbfda8aSnia	raise_win = NULL;
820bbfda8aSnia	leave_win = NULL;
830bbfda8aSnia	leave_flag = true;
840bbfda8aSnia	lower_win = tmp;
850bbfda8aSnia	WMapLower(tmp);
860bbfda8aSnia}
870bbfda8aSnia
880bbfda8aSnia
890bbfda8aSnia/*
900bbfda8aSnia * WindowOfEvent - return the window about which this event is concerned; this
910bbfda8aSnia * window may not be the same as XEvent.xany.window (the first window listed
920bbfda8aSnia * in the structure).
930bbfda8aSnia */
940bbfda8aSniaWindow
950bbfda8aSniaWindowOfEvent(XEvent *e)
960bbfda8aSnia{
970bbfda8aSnia	/*
980bbfda8aSnia	 * Each window subfield is marked with whether or not it is the same as
990bbfda8aSnia	 * XEvent.xany.window or is different (which is the case for some of the
1000bbfda8aSnia	 * notify events).
1010bbfda8aSnia	 */
1020bbfda8aSnia	switch(e->type) {
1030bbfda8aSnia		case KeyPress:
1040bbfda8aSnia		case KeyRelease:
1050bbfda8aSnia			return e->xkey.window;                       /* same */
1060bbfda8aSnia		case ButtonPress:
1070bbfda8aSnia		case ButtonRelease:
1080bbfda8aSnia			return e->xbutton.window;                 /* same */
1090bbfda8aSnia		case MotionNotify:
1100bbfda8aSnia			return e->xmotion.window;                  /* same */
1110bbfda8aSnia		case EnterNotify:
1120bbfda8aSnia		case LeaveNotify:
1130bbfda8aSnia			return e->xcrossing.window;                 /* same */
1140bbfda8aSnia		case FocusIn:
1150bbfda8aSnia		case FocusOut:
1160bbfda8aSnia			return e->xfocus.window;                       /* same */
1170bbfda8aSnia		case KeymapNotify:
1180bbfda8aSnia			return e->xkeymap.window;                  /* same */
1190bbfda8aSnia		case Expose:
1200bbfda8aSnia			return e->xexpose.window;                        /* same */
1210bbfda8aSnia		case GraphicsExpose:
1220bbfda8aSnia			return e->xgraphicsexpose.drawable;      /* same */
1230bbfda8aSnia		case NoExpose:
1240bbfda8aSnia			return e->xnoexpose.drawable;                  /* same */
1250bbfda8aSnia		case VisibilityNotify:
1260bbfda8aSnia			return e->xvisibility.window;          /* same */
1270bbfda8aSnia		case CreateNotify:
1280bbfda8aSnia			return e->xcreatewindow.window;            /* DIFF */
1290bbfda8aSnia		case DestroyNotify:
1300bbfda8aSnia			return e->xdestroywindow.window;          /* DIFF */
1310bbfda8aSnia		case UnmapNotify:
1320bbfda8aSnia			return e->xunmap.window;                    /* DIFF */
1330bbfda8aSnia		case MapNotify:
1340bbfda8aSnia			return e->xmap.window;                        /* DIFF */
1350bbfda8aSnia		case MapRequest:
1360bbfda8aSnia			return e->xmaprequest.window;                /* DIFF */
1370bbfda8aSnia		case ReparentNotify:
1380bbfda8aSnia			return e->xreparent.window;              /* DIFF */
1390bbfda8aSnia		case ConfigureNotify:
1400bbfda8aSnia			return e->xconfigure.window;            /* DIFF */
1410bbfda8aSnia		case ConfigureRequest:
1420bbfda8aSnia			return e->xconfigurerequest.window;    /* DIFF */
1430bbfda8aSnia		case GravityNotify:
1440bbfda8aSnia			return e->xgravity.window;                /* DIFF */
1450bbfda8aSnia		case ResizeRequest:
1460bbfda8aSnia			return e->xresizerequest.window;          /* same */
1470bbfda8aSnia		case CirculateNotify:
1480bbfda8aSnia			return e->xcirculate.window;            /* DIFF */
1490bbfda8aSnia		case CirculateRequest:
1500bbfda8aSnia			return e->xcirculaterequest.window;    /* DIFF */
1510bbfda8aSnia		case PropertyNotify:
1520bbfda8aSnia			return e->xproperty.window;              /* same */
1530bbfda8aSnia		case SelectionClear:
1540bbfda8aSnia			return e->xselectionclear.window;        /* same */
1550bbfda8aSnia		case SelectionRequest:
1560bbfda8aSnia			return e->xselectionrequest.requestor;  /* DIFF */
1570bbfda8aSnia		case SelectionNotify:
1580bbfda8aSnia			return e->xselection.requestor;         /* same */
1590bbfda8aSnia		case ColormapNotify:
1600bbfda8aSnia			return e->xcolormap.window;              /* same */
1610bbfda8aSnia		case ClientMessage:
1620bbfda8aSnia			return e->xclient.window;                 /* same */
1630bbfda8aSnia		case MappingNotify:
1640bbfda8aSnia			return None;
1650bbfda8aSnia	}
1660bbfda8aSnia	return None;
1670bbfda8aSnia}
1680bbfda8aSnia
1690bbfda8aSnia
1700bbfda8aSniavoid
1710bbfda8aSniaFixRootEvent(XEvent *e)
1720bbfda8aSnia{
1730bbfda8aSnia	if(Scr->Root == Scr->RealRoot) {
1740bbfda8aSnia		return;
1750bbfda8aSnia	}
1760bbfda8aSnia
1770bbfda8aSnia	switch(e->type) {
1780bbfda8aSnia		case KeyPress:
1790bbfda8aSnia		case KeyRelease:
1800bbfda8aSnia			e->xkey.x_root -= Scr->rootx;
1810bbfda8aSnia			e->xkey.y_root -= Scr->rooty;
1820bbfda8aSnia			e->xkey.root    = Scr->Root;
1830bbfda8aSnia			break;
1840bbfda8aSnia		case ButtonPress:
1850bbfda8aSnia		case ButtonRelease:
1860bbfda8aSnia			e->xbutton.x_root -= Scr->rootx;
1870bbfda8aSnia			e->xbutton.y_root -= Scr->rooty;
1880bbfda8aSnia			e->xbutton.root    = Scr->Root;
1890bbfda8aSnia			break;
1900bbfda8aSnia		case MotionNotify:
1910bbfda8aSnia			e->xmotion.x_root -= Scr->rootx;
1920bbfda8aSnia			e->xmotion.y_root -= Scr->rooty;
1930bbfda8aSnia			e->xmotion.root    = Scr->Root;
1940bbfda8aSnia			break;
1950bbfda8aSnia		case EnterNotify:
1960bbfda8aSnia		case LeaveNotify:
1970bbfda8aSnia			e->xcrossing.x_root -= Scr->rootx;
1980bbfda8aSnia			e->xcrossing.y_root -= Scr->rooty;
1990bbfda8aSnia			e->xcrossing.root    = Scr->Root;
2000bbfda8aSnia			break;
2010bbfda8aSnia		default:
2020bbfda8aSnia			break;
2030bbfda8aSnia	}
2040bbfda8aSnia}
2050bbfda8aSnia
2060bbfda8aSnia
2070bbfda8aSnia/* Move this next to GetTwmWindow()? */
2080bbfda8aSniaScreenInfo *
2090bbfda8aSniaGetTwmScreen(XEvent *event)
2100bbfda8aSnia{
2110bbfda8aSnia	ScreenInfo *scr;
2120bbfda8aSnia
2130bbfda8aSnia	if(XFindContext(dpy, event->xany.window, ScreenContext,
2140bbfda8aSnia	                (XPointer *)&scr) == XCNOENT) {
2150bbfda8aSnia		scr = FindScreenInfo(WindowOfEvent(event));
2160bbfda8aSnia	}
2170bbfda8aSnia
2180bbfda8aSnia	return scr;
2190bbfda8aSnia}
2200bbfda8aSnia
2210bbfda8aSnia
2220bbfda8aSnia/***********************************************************************
2230bbfda8aSnia *
2240bbfda8aSnia *  Procedure:
2250bbfda8aSnia *      FindScreenInfo - get ScreenInfo struct associated with a given window
2260bbfda8aSnia *
2270bbfda8aSnia *  Returned Value:
2280bbfda8aSnia *      ScreenInfo struct
2290bbfda8aSnia *
2300bbfda8aSnia *  Inputs:
2310bbfda8aSnia *      w       - the window
2320bbfda8aSnia *
2330bbfda8aSnia ***********************************************************************
2340bbfda8aSnia */
2350bbfda8aSniastatic ScreenInfo *
2360bbfda8aSniaFindScreenInfo(Window w)
2370bbfda8aSnia{
2380bbfda8aSnia	XWindowAttributes attr;
2390bbfda8aSnia	int scrnum;
2400bbfda8aSnia
2410bbfda8aSnia	attr.screen = NULL;
2420bbfda8aSnia	if(XGetWindowAttributes(dpy, w, &attr)) {
2430bbfda8aSnia		for(scrnum = 0; scrnum < NumScreens; scrnum++) {
2440bbfda8aSnia			if(ScreenList[scrnum] != NULL &&
2450bbfda8aSnia			                (ScreenOfDisplay(dpy, ScreenList[scrnum]->screen) ==
2460bbfda8aSnia			                 attr.screen)) {
2470bbfda8aSnia				return ScreenList[scrnum];
2480bbfda8aSnia			}
2490bbfda8aSnia		}
2500bbfda8aSnia	}
2510bbfda8aSnia
2520bbfda8aSnia	return NULL;
2530bbfda8aSnia}
2540bbfda8aSnia
2550bbfda8aSnia
2560bbfda8aSniavoid
2570bbfda8aSniaSynthesiseFocusOut(Window w)
2580bbfda8aSnia{
2590bbfda8aSnia	XEvent event;
2600bbfda8aSnia
2610bbfda8aSnia#ifdef TRACE_FOCUS
2620bbfda8aSnia	fprintf(stderr, "Synthesizing FocusOut on %x\n", w);
2630bbfda8aSnia#endif
2640bbfda8aSnia
2650bbfda8aSnia	event.type = FocusOut;
2660bbfda8aSnia	event.xfocus.window = w;
2670bbfda8aSnia	event.xfocus.mode = NotifyNormal;
2680bbfda8aSnia	event.xfocus.detail = NotifyPointer;
2690bbfda8aSnia
2700bbfda8aSnia	XPutBackEvent(dpy, &event);
2710bbfda8aSnia}
2720bbfda8aSnia
2730bbfda8aSnia
2740bbfda8aSniavoid
2750bbfda8aSniaSynthesiseFocusIn(Window w)
2760bbfda8aSnia{
2770bbfda8aSnia	XEvent event;
2780bbfda8aSnia
2790bbfda8aSnia#ifdef TRACE_FOCUS
2800bbfda8aSnia	fprintf(stderr, "Synthesizing FocusIn on %x\n", w);
2810bbfda8aSnia#endif
2820bbfda8aSnia
2830bbfda8aSnia	event.type = FocusIn;
2840bbfda8aSnia	event.xfocus.window = w;
2850bbfda8aSnia	event.xfocus.mode = NotifyNormal;
2860bbfda8aSnia	event.xfocus.detail = NotifyPointer;
2870bbfda8aSnia
2880bbfda8aSnia	XPutBackEvent(dpy, &event);
2890bbfda8aSnia
2900bbfda8aSnia}
2910bbfda8aSnia
2920bbfda8aSnia
2930bbfda8aSnia/*
2940bbfda8aSnia * This is actually never called anywhere in event code, but it digs into
2950bbfda8aSnia * the innards of events to do somewhat scary things.
2960bbfda8aSnia */
2970bbfda8aSniavoid
2980bbfda8aSniaSimulateMapRequest(Window w)
2990bbfda8aSnia{
3000bbfda8aSnia	Event.xmaprequest.window = w;
3010bbfda8aSnia	HandleMapRequest();
3020bbfda8aSnia}
303