Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wevent.c
dissimilarity index 89%
index 87a6b9f..6865838 100644 (file)
-
-
-/*
- * This event handling stuff was inspired on Tk.
- */
-
-#include "WINGsP.h"
-
-
-/* table to map event types to event masks */
-static unsigned long eventMasks[] = {
-    0,
-    0,
-    KeyPressMask,                       /* KeyPress */
-    KeyReleaseMask,                     /* KeyRelease */
-    ButtonPressMask,                    /* ButtonPress */
-    ButtonReleaseMask,                  /* ButtonRelease */
-    PointerMotionMask|PointerMotionHintMask|ButtonMotionMask
-    |Button1MotionMask|Button2MotionMask|Button3MotionMask
-    |Button4MotionMask|Button5MotionMask,
-    /* MotionNotify */
-    EnterWindowMask,                    /* EnterNotify */
-    LeaveWindowMask,                    /* LeaveNotify */
-    FocusChangeMask,                    /* FocusIn */
-    FocusChangeMask,                    /* FocusOut */
-    KeymapStateMask,                    /* KeymapNotify */
-    ExposureMask,                       /* Expose */
-    ExposureMask,                       /* GraphicsExpose */
-    ExposureMask,                       /* NoExpose */
-    VisibilityChangeMask,               /* VisibilityNotify */
-    SubstructureNotifyMask,             /* CreateNotify */
-    StructureNotifyMask,                /* DestroyNotify */
-    StructureNotifyMask,                /* UnmapNotify */
-    StructureNotifyMask,                /* MapNotify */
-    SubstructureRedirectMask,           /* MapRequest */
-    StructureNotifyMask,                /* ReparentNotify */
-    StructureNotifyMask,                /* ConfigureNotify */
-    SubstructureRedirectMask,           /* ConfigureRequest */
-    StructureNotifyMask,                /* GravityNotify */
-    ResizeRedirectMask,                 /* ResizeRequest */
-    StructureNotifyMask,                /* CirculateNotify */
-    SubstructureRedirectMask,           /* CirculateRequest */
-    PropertyChangeMask,                 /* PropertyNotify */
-    0,                                  /* SelectionClear */
-    0,                                  /* SelectionRequest */
-    0,                                  /* SelectionNotify */
-    ColormapChangeMask,                 /* ColormapNotify */
-    ClientMessageMask,                 /* ClientMessage */
-    0,                                 /* Mapping Notify */
-};
-
-
-
-/* hook for other toolkits or wmaker process their events */
-static WMEventHook *extraEventHandler=NULL;
-
-
-
-
-
-/*
- * WMCreateEventHandler--
- *     Create an event handler and put it in the event handler list for the
- * view. If the same callback and clientdata are already used in another
- * handler, the masks are OR'ed.
- *
- */
-void
-WMCreateEventHandler(WMView *view, unsigned long mask, WMEventProc *eventProc,
-                     void *clientData)
-{
-    W_EventHandler *hPtr;
-    WMArrayIterator iter;
-
-    WM_ITERATE_ARRAY(view->eventHandlers, hPtr, iter) {
-        if (hPtr->clientData==clientData && hPtr->proc==eventProc) {
-            hPtr->eventMask |= mask;
-            return;
-        }
-    }
-
-    hPtr = wmalloc(sizeof(W_EventHandler));
-
-    /* select events for window */
-    hPtr->eventMask = mask;
-    hPtr->proc = eventProc;
-    hPtr->clientData = clientData;
-
-    WMAddToArray(view->eventHandlers, hPtr);
-}
-
-
-static int
-matchHandler(void *item, void *cdata)
-{
-#define H1 ((W_EventHandler*)item)
-#define H2 ((W_EventHandler*)cdata)
-
-    return (H1->eventMask==H2->eventMask && H1->proc==H2->proc &&
-            H1->clientData==H2->clientData);
-}
-
-
-/*
- * WMDeleteEventHandler--
- *     Delete event handler matching arguments from windows
- * event handler list.
- *
- */
-void
-WMDeleteEventHandler(WMView *view, unsigned long mask, WMEventProc *eventProc,
-                     void *clientData)
-{
-    W_EventHandler tmp;
-
-    tmp.eventMask = mask;
-    tmp.proc = eventProc;
-    tmp.clientData = clientData;
-    WMRemoveFromArrayMatching(view->eventHandlers, matchHandler, (void*)&tmp);
-}
-
-
-static Time
-getEventTime(WMScreen *screen, XEvent *event)
-{
-    switch (event->type) {
-    case ButtonPress:
-    case ButtonRelease:
-        return event->xbutton.time;
-    case KeyPress:
-    case KeyRelease:
-        return event->xkey.time;
-    case MotionNotify:
-        return event->xmotion.time;
-    case EnterNotify:
-    case LeaveNotify:
-        return event->xcrossing.time;
-    case PropertyNotify:
-        return event->xproperty.time;
-    case SelectionClear:
-        return event->xselectionclear.time;
-    case SelectionRequest:
-        return event->xselectionrequest.time;
-    case SelectionNotify:
-        return event->xselection.time;
-    default:
-        return screen->lastEventTime;
-    }
-}
-
-
-void
-W_CallDestroyHandlers(W_View *view)
-{
-    XEvent event;
-    WMArrayIterator iter;
-    W_EventHandler *hPtr;
-
-
-    event.type = DestroyNotify;
-    event.xdestroywindow.window = view->window;
-    event.xdestroywindow.event = view->window;
-
-    WM_ITERATE_ARRAY(view->eventHandlers, hPtr, iter) {
-        if (hPtr->eventMask & StructureNotifyMask) {
-            (*hPtr->proc)(&event, hPtr->clientData);
-        }
-    }
-}
-
-
-
-void
-WMSetViewNextResponder(WMView *view, WMView *responder)
-{
-    /* set the widget to receive keyboard events that aren't handled
-     * by this widget */
-
-    view->nextResponder = responder;
-}
-
-
-void
-WMRelayToNextResponder(WMView *view, XEvent *event)
-{
-    unsigned long mask = eventMasks[event->xany.type];
-
-    if (view->nextResponder) {
-        WMView *next = view->nextResponder;
-        W_EventHandler *hPtr;
-        WMArrayIterator iter;
-
-        WM_ITERATE_ARRAY(next->eventHandlers, hPtr, iter) {
-            if ((hPtr->eventMask & mask)) {
-                (*hPtr->proc)(event, hPtr->clientData);
-            }
-        }
-    }
-}
-
-
-int
-WMHandleEvent(XEvent *event)
-{
-    W_EventHandler *hPtr;
-    W_View *view, *toplevel;
-    unsigned long mask;
-    Window window;
-    WMArrayIterator iter;
-
-    if (event->type == MappingNotify) {
-        XRefreshKeyboardMapping(&event->xmapping);
-        return True;
-    }
-
-    if (XFilterEvent(event, None) == True) {
-        return False;
-    }
-
-    mask = eventMasks[event->xany.type];
-
-    window = event->xany.window;
-
-    /* diferentiate SubstructureNotify with StructureNotify */
-    if (mask == StructureNotifyMask) {
-        if (event->xmap.event != event->xmap.window) {
-            mask = SubstructureNotifyMask;
-            window = event->xmap.event;
-        }
-    }
-    view = W_GetViewForXWindow(event->xany.display, window);
-
-    if (!view) {
-        if (extraEventHandler)
-            (extraEventHandler)(event);
-
-        return False;
-    }
-
-    view->screen->lastEventTime = getEventTime(view->screen, event);
-
-    toplevel = W_TopLevelOfView(view);
-
-    if (event->type == SelectionNotify || event->type == SelectionClear
-        || event->type == SelectionRequest) {
-        /* handle selection related events */
-        W_HandleSelectionEvent(event);
-
-    }
-
-    /* if it's a key event, redispatch it to the focused control */
-    if (mask & (KeyPressMask|KeyReleaseMask)) {
-        W_View *focused = W_FocusedViewOfToplevel(toplevel);
-
-        if (focused) {
-            view = focused;
-        }
-    }
-
-    /* compress Motion events */
-    if (event->type == MotionNotify && !view->flags.dontCompressMotion) {
-        while (XPending(event->xmotion.display)) {
-            XEvent ev;
-            XPeekEvent(event->xmotion.display, &ev);
-            if (ev.type == MotionNotify
-                && event->xmotion.window == ev.xmotion.window
-                && event->xmotion.subwindow == ev.xmotion.subwindow) {
-                /* replace events */
-                XNextEvent(event->xmotion.display, event);
-            } else break;
-        }
-    }
-
-    /* compress expose events */
-    if (event->type == Expose && !view->flags.dontCompressExpose) {
-        while (XCheckTypedWindowEvent(event->xexpose.display, view->window,
-                                      Expose, event));
-    }
-
-
-    if (view->screen->modalLoop && toplevel!=view->screen->modalView
-        && !toplevel->flags.worksWhenModal) {
-        if (event->type == KeyPress || event->type == KeyRelease
-            || event->type == MotionNotify || event->type == ButtonPress
-            || event->type == ButtonRelease
-            || event->type == FocusIn || event->type == FocusOut) {
-            return True;
-        }
-    }
-
-    /* do balloon stuffs */
-    if (event->type == EnterNotify)
-        W_BalloonHandleEnterView(view);
-    else if (event->type == LeaveNotify)
-        W_BalloonHandleLeaveView(view);
-
-    /* This is a hack. It will make the panel be secure while
-     * the event handlers are handled, as some event handler
-     * might destroy the widget. */
-    W_RetainView(toplevel);
-
-    WM_ITERATE_ARRAY(view->eventHandlers, hPtr, iter) {
-        if ((hPtr->eventMask & mask)) {
-            (*hPtr->proc)(event, hPtr->clientData);
-        }
-    }
-#if 0
-    /* pass the event to the top level window of the widget */
-    /* TODO: change this to a responder chain */
-    if (view->parent != NULL) {
-        vPtr = view;
-        while (vPtr->parent != NULL)
-            vPtr = vPtr->parent;
-
-        WM_ITERATE_ARRAY(vPtr->eventHandlers, hPtr, iter) {
-            if (hPtr->eventMask & mask) {
-                (*hPtr->proc)(event, hPtr->clientData);
-            }
-        }
-    }
-#endif
-    /* save button click info to track double-clicks */
-    if (view->screen->ignoreNextDoubleClick) {
-        view->screen->ignoreNextDoubleClick = 0;
-    } else {
-        if (event->type == ButtonPress) {
-            view->screen->lastClickWindow = event->xbutton.window;
-            view->screen->lastClickTime = event->xbutton.time;
-        }
-    }
-
-    if (event->type == ClientMessage) {
-        /* must be handled at the end, for such message can destroy the view */
-        W_HandleDNDClientMessage(toplevel, &event->xclient);
-    }
-
-    W_ReleaseView(toplevel);
-
-    return True;
-}
-
-
-int
-WMIsDoubleClick(XEvent *event)
-{
-    W_View *view;
-
-    if (event->type != ButtonPress)
-        return False;
-
-    view = W_GetViewForXWindow(event->xany.display, event->xbutton.window);
-
-    if (!view)
-        return False;
-
-    if (view->screen->lastClickWindow != event->xbutton.window)
-        return False;
-
-    if (event->xbutton.time - view->screen->lastClickTime
-        < WINGsConfiguration.doubleClickDelay) {
-        view->screen->lastClickTime = 0;
-        view->screen->lastClickWindow = None;
-        view->screen->ignoreNextDoubleClick = 1;
-        return True;
-    } else
-        return False;
-}
-
-
-/*
- * Check for X and input events. If X events are present input events will
- * not be checked.
- *
- * Return value: True if a X event is available or any input event was
- *               processed, false otherwise (including return because of
- *               some timer handler expired).
- *
- *  If waitForInput is False, it will just peek for available input and return
- * without processing. Return vaue will be True if input is available.
- *
- *  If waitForInput is True, it will wait until an input event arrives on the
- * registered input handlers and ConnectionNumber(dpy), or will return when
- * a timer handler expires if no input event arrived until then.
- */
-static Bool
-waitForEvent(Display *dpy, unsigned long xeventmask, Bool waitForInput)
-{
-    XSync(dpy, False);
-    if (xeventmask==0) {
-        if (XPending(dpy))
-            return True;
-    } else {
-        XEvent ev;
-        if (XCheckMaskEvent(dpy, xeventmask, &ev)) {
-            XPutBackEvent(dpy, &ev);
-            return True;
-        }
-    }
-
-    return W_HandleInputEvents(waitForInput, ConnectionNumber(dpy));
-}
-
-
-void
-WMNextEvent(Display *dpy, XEvent *event)
-{
-    /* Check any expired timers */
-    W_CheckTimerHandlers();
-
-    while (XPending(dpy) == 0) {
-        /* Do idle and timer stuff while there are no input or X events */
-        while (!waitForEvent(dpy, 0, False) && W_CheckIdleHandlers()) {
-            /* dispatch timer events */
-            W_CheckTimerHandlers();
-        }
-
-        /*
-         * Make sure that new events did not arrive while we were doing
-         * timer/idle stuff. Or we might block forever waiting for
-         * an event that already arrived.
-         */
-        /* wait for something to happen or a timer to expire */
-        waitForEvent(dpy, 0, True);
-
-        /* Check any expired timers */
-        W_CheckTimerHandlers();
-    }
-
-    XNextEvent(dpy, event);
-}
-
-
-void
-WMMaskEvent(Display *dpy, long mask, XEvent *event)
-{
-    /* Check any expired timers */
-    W_CheckTimerHandlers();
-
-    while (!XCheckMaskEvent(dpy, mask, event)) {
-        /* Do idle and timer stuff while there are no input or X events */
-        while (!waitForEvent(dpy, mask, False) && W_CheckIdleHandlers()) {
-            W_CheckTimerHandlers();
-        }
-
-        if (XCheckMaskEvent(dpy, mask, event))
-            return;
-
-        /* Wait for input on the X connection socket or another input handler */
-        waitForEvent(dpy, mask, True);
-
-        /* Check any expired timers */
-        W_CheckTimerHandlers();
-    }
-}
-
-
-Bool
-WMScreenPending(WMScreen *scr)
-{
-    if (XPending(scr->display))
-        return True;
-    else
-        return False;
-}
-
-
-WMEventHook*
-WMHookEventHandler(WMEventHook *handler)
-{
-    WMEventHook *oldHandler = extraEventHandler;
-
-    extraEventHandler = handler;
-
-    return oldHandler;
-}
-
-
+
+/*
+ * This event handling stuff was inspired on Tk.
+ */
+
+#include "WINGsP.h"
+
+/* table to map event types to event masks */
+static unsigned long eventMasks[] = {
+       0,
+       0,
+       KeyPressMask,           /* KeyPress */
+       KeyReleaseMask,         /* KeyRelease */
+       ButtonPressMask,        /* ButtonPress */
+       ButtonReleaseMask,      /* ButtonRelease */
+       PointerMotionMask | PointerMotionHintMask | ButtonMotionMask
+           | Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask,
+       /* MotionNotify */
+       EnterWindowMask,        /* EnterNotify */
+       LeaveWindowMask,        /* LeaveNotify */
+       FocusChangeMask,        /* FocusIn */
+       FocusChangeMask,        /* FocusOut */
+       KeymapStateMask,        /* KeymapNotify */
+       ExposureMask,           /* Expose */
+       ExposureMask,           /* GraphicsExpose */
+       ExposureMask,           /* NoExpose */
+       VisibilityChangeMask,   /* VisibilityNotify */
+       SubstructureNotifyMask, /* CreateNotify */
+       StructureNotifyMask,    /* DestroyNotify */
+       StructureNotifyMask,    /* UnmapNotify */
+       StructureNotifyMask,    /* MapNotify */
+       SubstructureRedirectMask,       /* MapRequest */
+       StructureNotifyMask,    /* ReparentNotify */
+       StructureNotifyMask,    /* ConfigureNotify */
+       SubstructureRedirectMask,       /* ConfigureRequest */
+       StructureNotifyMask,    /* GravityNotify */
+       ResizeRedirectMask,     /* ResizeRequest */
+       StructureNotifyMask,    /* CirculateNotify */
+       SubstructureRedirectMask,       /* CirculateRequest */
+       PropertyChangeMask,     /* PropertyNotify */
+       0,                      /* SelectionClear */
+       0,                      /* SelectionRequest */
+       0,                      /* SelectionNotify */
+       ColormapChangeMask,     /* ColormapNotify */
+       ClientMessageMask,      /* ClientMessage */
+       0,                      /* Mapping Notify */
+};
+
+/* hook for other toolkits or wmaker process their events */
+static WMEventHook *extraEventHandler = NULL;
+
+/*
+ * WMCreateEventHandler--
+ *     Create an event handler and put it in the event handler list for the
+ * view. If the same callback and clientdata are already used in another
+ * handler, the masks are OR'ed.
+ *
+ */
+void WMCreateEventHandler(WMView * view, unsigned long mask, WMEventProc * eventProc, void *clientData)
+{
+       W_EventHandler *hPtr;
+       WMArrayIterator iter;
+
+       WM_ITERATE_ARRAY(view->eventHandlers, hPtr, iter) {
+               if (hPtr->clientData == clientData && hPtr->proc == eventProc) {
+                       hPtr->eventMask |= mask;
+                       return;
+               }
+       }
+
+       hPtr = wmalloc(sizeof(W_EventHandler));
+
+       /* select events for window */
+       hPtr->eventMask = mask;
+       hPtr->proc = eventProc;
+       hPtr->clientData = clientData;
+
+       WMAddToArray(view->eventHandlers, hPtr);
+}
+
+static int matchHandler(void *item, void *cdata)
+{
+#define H1 ((W_EventHandler*)item)
+#define H2 ((W_EventHandler*)cdata)
+
+       return (H1->eventMask == H2->eventMask && H1->proc == H2->proc && H1->clientData == H2->clientData);
+}
+
+/*
+ * WMDeleteEventHandler--
+ *     Delete event handler matching arguments from windows
+ * event handler list.
+ *
+ */
+void WMDeleteEventHandler(WMView * view, unsigned long mask, WMEventProc * eventProc, void *clientData)
+{
+       W_EventHandler tmp;
+
+       tmp.eventMask = mask;
+       tmp.proc = eventProc;
+       tmp.clientData = clientData;
+       WMRemoveFromArrayMatching(view->eventHandlers, matchHandler, (void *)&tmp);
+}
+
+static Time getEventTime(WMScreen * screen, XEvent * event)
+{
+       switch (event->type) {
+       case ButtonPress:
+       case ButtonRelease:
+               return event->xbutton.time;
+       case KeyPress:
+       case KeyRelease:
+               return event->xkey.time;
+       case MotionNotify:
+               return event->xmotion.time;
+       case EnterNotify:
+       case LeaveNotify:
+               return event->xcrossing.time;
+       case PropertyNotify:
+               return event->xproperty.time;
+       case SelectionClear:
+               return event->xselectionclear.time;
+       case SelectionRequest:
+               return event->xselectionrequest.time;
+       case SelectionNotify:
+               return event->xselection.time;
+       default:
+               return screen->lastEventTime;
+       }
+}
+
+void W_CallDestroyHandlers(W_View * view)
+{
+       XEvent event;
+       WMArrayIterator iter;
+       W_EventHandler *hPtr;
+
+       event.type = DestroyNotify;
+       event.xdestroywindow.window = view->window;
+       event.xdestroywindow.event = view->window;
+
+       WM_ITERATE_ARRAY(view->eventHandlers, hPtr, iter) {
+               if (hPtr->eventMask & StructureNotifyMask) {
+                       (*hPtr->proc) (&event, hPtr->clientData);
+               }
+       }
+}
+
+void WMSetViewNextResponder(WMView * view, WMView * responder)
+{
+       /* set the widget to receive keyboard events that aren't handled
+        * by this widget */
+
+       view->nextResponder = responder;
+}
+
+void WMRelayToNextResponder(WMView * view, XEvent * event)
+{
+       unsigned long mask = eventMasks[event->xany.type];
+
+       if (view->nextResponder) {
+               WMView *next = view->nextResponder;
+               W_EventHandler *hPtr;
+               WMArrayIterator iter;
+
+               WM_ITERATE_ARRAY(next->eventHandlers, hPtr, iter) {
+                       if ((hPtr->eventMask & mask)) {
+                               (*hPtr->proc) (event, hPtr->clientData);
+                       }
+               }
+       }
+}
+
+int WMHandleEvent(XEvent * event)
+{
+       W_EventHandler *hPtr;
+       W_View *view, *toplevel;
+       unsigned long mask;
+       Window window;
+       WMArrayIterator iter;
+
+       if (event->type == MappingNotify) {
+               XRefreshKeyboardMapping(&event->xmapping);
+               return True;
+       }
+
+       if (XFilterEvent(event, None) == True) {
+               return False;
+       }
+
+       mask = eventMasks[event->xany.type];
+
+       window = event->xany.window;
+
+       /* diferentiate SubstructureNotify with StructureNotify */
+       if (mask == StructureNotifyMask) {
+               if (event->xmap.event != event->xmap.window) {
+                       mask = SubstructureNotifyMask;
+                       window = event->xmap.event;
+               }
+       }
+       view = W_GetViewForXWindow(event->xany.display, window);
+
+       if (!view) {
+               if (extraEventHandler)
+                       (extraEventHandler) (event);
+
+               return False;
+       }
+
+       view->screen->lastEventTime = getEventTime(view->screen, event);
+
+       toplevel = W_TopLevelOfView(view);
+
+       if (event->type == SelectionNotify || event->type == SelectionClear || event->type == SelectionRequest) {
+               /* handle selection related events */
+               W_HandleSelectionEvent(event);
+
+       }
+
+       /* if it's a key event, redispatch it to the focused control */
+       if (mask & (KeyPressMask | KeyReleaseMask)) {
+               W_View *focused = W_FocusedViewOfToplevel(toplevel);
+
+               if (focused) {
+                       view = focused;
+               }
+       }
+
+       /* compress Motion events */
+       if (event->type == MotionNotify && !view->flags.dontCompressMotion) {
+               while (XPending(event->xmotion.display)) {
+                       XEvent ev;
+                       XPeekEvent(event->xmotion.display, &ev);
+                       if (ev.type == MotionNotify
+                           && event->xmotion.window == ev.xmotion.window
+                           && event->xmotion.subwindow == ev.xmotion.subwindow) {
+                               /* replace events */
+                               XNextEvent(event->xmotion.display, event);
+                       } else
+                               break;
+               }
+       }
+
+       /* compress expose events */
+       if (event->type == Expose && !view->flags.dontCompressExpose) {
+               while (XCheckTypedWindowEvent(event->xexpose.display, view->window, Expose, event)) ;
+       }
+
+       if (view->screen->modalLoop && toplevel != view->screen->modalView && !toplevel->flags.worksWhenModal) {
+               if (event->type == KeyPress || event->type == KeyRelease
+                   || event->type == MotionNotify || event->type == ButtonPress
+                   || event->type == ButtonRelease || event->type == FocusIn || event->type == FocusOut) {
+                       return True;
+               }
+       }
+
+       /* do balloon stuffs */
+       if (event->type == EnterNotify)
+               W_BalloonHandleEnterView(view);
+       else if (event->type == LeaveNotify)
+               W_BalloonHandleLeaveView(view);
+
+       /* This is a hack. It will make the panel be secure while
+        * the event handlers are handled, as some event handler
+        * might destroy the widget. */
+       W_RetainView(toplevel);
+
+       WM_ITERATE_ARRAY(view->eventHandlers, hPtr, iter) {
+               if ((hPtr->eventMask & mask)) {
+                       (*hPtr->proc) (event, hPtr->clientData);
+               }
+       }
+#if 0
+       /* pass the event to the top level window of the widget */
+       /* TODO: change this to a responder chain */
+       if (view->parent != NULL) {
+               vPtr = view;
+               while (vPtr->parent != NULL)
+                       vPtr = vPtr->parent;
+
+               WM_ITERATE_ARRAY(vPtr->eventHandlers, hPtr, iter) {
+                       if (hPtr->eventMask & mask) {
+                               (*hPtr->proc) (event, hPtr->clientData);
+                       }
+               }
+       }
+#endif
+       /* save button click info to track double-clicks */
+       if (view->screen->ignoreNextDoubleClick) {
+               view->screen->ignoreNextDoubleClick = 0;
+       } else {
+               if (event->type == ButtonPress) {
+                       view->screen->lastClickWindow = event->xbutton.window;
+                       view->screen->lastClickTime = event->xbutton.time;
+               }
+       }
+
+       if (event->type == ClientMessage) {
+               /* must be handled at the end, for such message can destroy the view */
+               W_HandleDNDClientMessage(toplevel, &event->xclient);
+       }
+
+       W_ReleaseView(toplevel);
+
+       return True;
+}
+
+int WMIsDoubleClick(XEvent * event)
+{
+       W_View *view;
+
+       if (event->type != ButtonPress)
+               return False;
+
+       view = W_GetViewForXWindow(event->xany.display, event->xbutton.window);
+
+       if (!view)
+               return False;
+
+       if (view->screen->lastClickWindow != event->xbutton.window)
+               return False;
+
+       if (event->xbutton.time - view->screen->lastClickTime < WINGsConfiguration.doubleClickDelay) {
+               view->screen->lastClickTime = 0;
+               view->screen->lastClickWindow = None;
+               view->screen->ignoreNextDoubleClick = 1;
+               return True;
+       } else
+               return False;
+}
+
+/*
+ * Check for X and input events. If X events are present input events will
+ * not be checked.
+ *
+ * Return value: True if a X event is available or any input event was
+ *               processed, false otherwise (including return because of
+ *               some timer handler expired).
+ *
+ *  If waitForInput is False, it will just peek for available input and return
+ * without processing. Return vaue will be True if input is available.
+ *
+ *  If waitForInput is True, it will wait until an input event arrives on the
+ * registered input handlers and ConnectionNumber(dpy), or will return when
+ * a timer handler expires if no input event arrived until then.
+ */
+static Bool waitForEvent(Display * dpy, unsigned long xeventmask, Bool waitForInput)
+{
+       XSync(dpy, False);
+       if (xeventmask == 0) {
+               if (XPending(dpy))
+                       return True;
+       } else {
+               XEvent ev;
+               if (XCheckMaskEvent(dpy, xeventmask, &ev)) {
+                       XPutBackEvent(dpy, &ev);
+                       return True;
+               }
+       }
+
+       return W_HandleInputEvents(waitForInput, ConnectionNumber(dpy));
+}
+
+void WMNextEvent(Display * dpy, XEvent * event)
+{
+       /* Check any expired timers */
+       W_CheckTimerHandlers();
+
+       while (XPending(dpy) == 0) {
+               /* Do idle and timer stuff while there are no input or X events */
+               while (!waitForEvent(dpy, 0, False) && W_CheckIdleHandlers()) {
+                       /* dispatch timer events */
+                       W_CheckTimerHandlers();
+               }
+
+               /*
+                * Make sure that new events did not arrive while we were doing
+                * timer/idle stuff. Or we might block forever waiting for
+                * an event that already arrived.
+                */
+               /* wait for something to happen or a timer to expire */
+               waitForEvent(dpy, 0, True);
+
+               /* Check any expired timers */
+               W_CheckTimerHandlers();
+       }
+
+       XNextEvent(dpy, event);
+}
+
+void WMMaskEvent(Display * dpy, long mask, XEvent * event)
+{
+       /* Check any expired timers */
+       W_CheckTimerHandlers();
+
+       while (!XCheckMaskEvent(dpy, mask, event)) {
+               /* Do idle and timer stuff while there are no input or X events */
+               while (!waitForEvent(dpy, mask, False) && W_CheckIdleHandlers()) {
+                       W_CheckTimerHandlers();
+               }
+
+               if (XCheckMaskEvent(dpy, mask, event))
+                       return;
+
+               /* Wait for input on the X connection socket or another input handler */
+               waitForEvent(dpy, mask, True);
+
+               /* Check any expired timers */
+               W_CheckTimerHandlers();
+       }
+}
+
+Bool WMScreenPending(WMScreen * scr)
+{
+       if (XPending(scr->display))
+               return True;
+       else
+               return False;
+}
+
+WMEventHook *WMHookEventHandler(WMEventHook * handler)
+{
+       WMEventHook *oldHandler = extraEventHandler;
+
+       extraEventHandler = handler;
+
+       return oldHandler;
+}