Skip to content
Snippets Groups Projects
events.c 91 KiB
Newer Older
Olivier Fourdan's avatar
Olivier Fourdan committed
    else
    {
        /*
           The event did not occur in one of our known good clients...
           Get the screen structure from the root of the event.
         */
        screen_info = myDisplayGetScreenFromRoot (display_info, ev->root);
        if (screen_info)
        {
            if ((ev->window == screen_info->xroot) && (screen_info->params->scroll_workspaces)
                    && ((ev->button == Button4) || (ev->button == Button5)))
            {
                rootScrollButton (display_info, ev);
            }
            else
            {
                XUngrabPointer (display_info->dpy, ev->time);
                XSendEvent (display_info->dpy, screen_info->xfwm4_win, FALSE, SubstructureNotifyMask, (XEvent *) ev);
            }
        }
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
Olivier Fourdan's avatar
Olivier Fourdan committed
    /* Release pending events */
    XAllowEvents (display_info->dpy, replay ? ReplayPointer : SyncPointer, CurrentTime);
handleButtonRelease (DisplayInfo *display_info, XButtonEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;

    TRACE ("entering handleButtonRelease");
Olivier Fourdan's avatar
Olivier Fourdan committed

    /* Get the screen structure from the root of the event */
    screen_info = myDisplayGetScreenFromRoot (display_info, ev->root);
        XSendEvent (display_info->dpy, screen_info->xfwm4_win, FALSE, SubstructureNotifyMask, (XEvent *) ev);
    /* Release pending events */
    XAllowEvents (display_info->dpy, SyncPointer, CurrentTime);
handleDestroyNotify (DisplayInfo *display_info, XDestroyWindowEvent * ev)
#ifdef ENABLE_KDE_SYSTRAY_PROXY
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    TRACE ("entering handleDestroyNotify");
    TRACE ("DestroyNotify on window (0x%lx)", ev->window);
    screen_info = myDisplayGetScreenFromSystray (display_info, ev->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
    if (screen_info)
        /* systray window is gone */
        screen_info->systray = None;
    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_WINDOW);
        TRACE ("DestroyNotify for \"%s\" (0x%lx)", c->name, c->window);
        list_of_windows = clientListTransientOrModal (c);
        clientPassFocus (c->screen_info, c, list_of_windows);
        clientUnframe (c, FALSE);
        status = EVENT_FILTER_REMOVE;
handleMapRequest (DisplayInfo *display_info, XMapRequestEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;
Olivier Fourdan's avatar
Olivier Fourdan committed

    TRACE ("entering handleMapRequest");
    TRACE ("MapRequest on window (0x%lx)", ev->window);
Olivier Fourdan's avatar
Olivier Fourdan committed

Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        TRACE ("Mapping None ???");
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_WINDOW);
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        ScreenInfo *screen_info = c->screen_info;

Olivier Fourdan's avatar
Olivier Fourdan committed
        TRACE ("handleMapRequest: clientShow");
Olivier Fourdan's avatar
Olivier Fourdan committed
        if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MAP_PENDING))
        {
            TRACE ("Ignoring MapRequest on window (0x%lx)", ev->window);
            status = EVENT_FILTER_REMOVE;
        if (FLAG_TEST (c->flags, CLIENT_FLAG_STICKY) ||
            (c->win_workspace == screen_info->current_ws))
        status = EVENT_FILTER_REMOVE;
Olivier Fourdan's avatar
Olivier Fourdan committed
        TRACE ("handleMapRequest: clientFrame");
        clientFrame (display_info, ev->window, FALSE);
        status = EVENT_FILTER_REMOVE;
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
handleMapNotify (DisplayInfo *display_info, XMapEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;
Olivier Fourdan's avatar
Olivier Fourdan committed

    TRACE ("entering handleMapNotify");
    TRACE ("MapNotify on window (0x%lx)", ev->window);
    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_WINDOW);
Olivier Fourdan's avatar
Olivier Fourdan committed
    if (c)
    {
        TRACE ("MapNotify for \"%s\" (0x%lx)", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
        if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MAP_PENDING))
Olivier Fourdan's avatar
Olivier Fourdan committed
            FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_MAP_PENDING);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
handleUnmapNotify (DisplayInfo *display_info, XUnmapEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;

    TRACE ("entering handleUnmapNotify");
    TRACE ("UnmapNotify on window (0x%lx)", ev->window);
        TRACE ("Ignoring UnmapNotify caused by parent's resize");
    screen_info = myDisplayGetScreenFromWindow (display_info, ev->window);
    if (screen_info && (ev->event != ev->window) && (ev->event != screen_info->xroot || !ev->send_event))
        TRACE ("handleUnmapNotify (): Event ignored");
    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_WINDOW);
    if (c)
    {
        TRACE ("UnmapNotify for \"%s\" (0x%lx)", c->name, c->window);
        TRACE ("ignore_unmap for \"%s\" is %i", c->name, c->ignore_unmap);
        status = EVENT_FILTER_REMOVE;
Olivier Fourdan's avatar
Olivier Fourdan committed
        if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MAP_PENDING))
             * This UnmapNotify event is caused by reparenting
             * so we just ignore it, so the window won't return
             * to withdrawn state by mistake.
             */
            TRACE ("Client \"%s\" is not mapped, event ignored", c->name);
Olivier Fourdan's avatar
Olivier Fourdan committed
        screen_info = c->screen_info;
        /*
         * ICCCM spec states that a client wishing to switch
         * to WithdrawnState should send a synthetic UnmapNotify
         * with the event field set to root if the client window
         * is already unmapped.
         * Therefore, bypass the ignore_unmap counter and
         * unframe the client.
         */
        if ((ev->event == screen_info->xroot) && (ev->send_event))
        {
            TRACE ("ICCCM UnmapNotify for \"%s\"", c->name);
            list_of_windows = clientListTransientOrModal (c);
            clientPassFocus (screen_info, c, list_of_windows);
            clientUnframe (c, FALSE);
        if (c->ignore_unmap)
        {
            c->ignore_unmap--;
            TRACE ("ignore_unmap for \"%s\" is now %i",
            TRACE ("unmapping \"%s\" as ignore_unmap is %i", c->name, c->ignore_unmap);
            list_of_windows = clientListTransientOrModal (c);
            clientPassFocus (screen_info, c, list_of_windows);
            clientUnframe (c, FALSE);
handleConfigureNotify (DisplayInfo *display_info, XConfigureEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    TRACE ("entering handleConfigureNotify");
handleConfigureRequest (DisplayInfo *display_info, XConfigureRequestEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    XWindowChanges wc;

    TRACE ("entering handleConfigureRequest");
    TRACE ("ConfigureRequest on window (0x%lx)", ev->window);
Olivier Fourdan's avatar
Olivier Fourdan committed

    wc.x = ev->x;
    wc.y = ev->y;
    wc.width = ev->width;
    wc.height = ev->height;
    wc.sibling = ev->above;
    wc.stack_mode = ev->detail;
    wc.border_width = ev->border_width;

    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_WINDOW);
        /* Some app tend or try to manipulate the wm frame to achieve fullscreen mode */
        c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_FRAME);
            TRACE ("client %s (0x%lx) is attempting to manipulate its frame!", c->name, c->window);
            if (ev->value_mask & CWX)
            {
                wc.x += frameLeft (c);
            }
            if (ev->value_mask & CWY)
            {
                wc.y += frameTop (c);
            }
            if (ev->value_mask & CWWidth)
            {
                wc.width -= frameLeft (c) + frameRight (c);
            }
            if (ev->value_mask & CWHeight)
            {
                wc.height -= frameTop (c) + frameBottom (c);
            }
            /* We don't allow changing stacking order by accessing the frame
               window because that would break the layer management in xfwm4
             */
            ev->value_mask &= ~(CWSibling | CWStackMode);
        }
        gboolean constrained = FALSE;
        ScreenInfo *screen_info = c->screen_info;
        TRACE ("handleConfigureRequest managed window \"%s\" (0x%lx)", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
        if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING))
        {
            /* Sorry, but it's not the right time for configure request */
        }
        if (c->type == WINDOW_DESKTOP)
        {
            /* Ignore stacking request for DESKTOP windows */
            ev->value_mask &= ~(CWSibling | CWStackMode);
        }
        if (FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
Jasper Huijsmans's avatar
 
Jasper Huijsmans committed
        {
Jasper Huijsmans's avatar
 
Jasper Huijsmans committed
            int cx, cy;

            /* size request from fullscreen windows get fullscreen */
Jasper Huijsmans's avatar
 
Jasper Huijsmans committed
            cx = frameX (c) + (frameWidth (c) / 2);
            cy = frameY (c) + (frameHeight (c) / 2);

            monitor_nbr = find_monitor_at_point (screen_info->gscr, cx, cy);
            gdk_screen_get_monitor_geometry (screen_info->gscr, monitor_nbr, &rect);

            wc.x = rect.x;
            wc.y = rect.y;
            wc.width = rect.width;
            wc.height = rect.height;
Jasper Huijsmans's avatar
 
Jasper Huijsmans committed

            ev->value_mask |= (CWX | CWY | CWWidth | CWHeight);
        }
        else if (FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED)
                 && (screen_info->params->borderless_maximize))
        {
            wc.x = c->x;
            wc.y = c->y;
            wc.width = c->width;
            wc.height = c->height;
        }
        /* Clean up buggy requests that set all flags */
        if ((ev->value_mask & CWX) && (wc.x == c->x))
        {
            ev->value_mask &= ~CWX;
        }
        if ((ev->value_mask & CWY) && (wc.y == c->y))
        {
            ev->value_mask &= ~CWY;
        }
        if ((ev->value_mask & CWWidth) && (wc.width == c->width))
        {
            ev->value_mask &= ~CWWidth;
        }
        if ((ev->value_mask & CWHeight) && (wc.height == c->height))
        {
            ev->value_mask &= ~CWHeight;
        }
        /* Still a move/resize after cleanup? */
        if (ev->value_mask & (CWX | CWY | CWWidth | CWHeight))
        {
            if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
            {
                clientRemoveMaximizeFlag (c);
            }
            constrained = TRUE;
        }
        /*
           Let's say that if the client performs a XRaiseWindow, we show the window if focus
           stealing prevention is not activated, otherwise we just set the "demands attention"
           flag...
         */
        if ((ev->value_mask & CWStackMode) && (wc.stack_mode == Above) && (wc.sibling == None) && !(c->type & WINDOW_TYPE_DONT_FOCUS))
            last_raised = clientGetLastRaise (screen_info);
            if (last_raised && (c != last_raised))
                if ((screen_info->params->prevent_focus_stealing) && (screen_info->params->activate_action == ACTIVATE_ACTION_NONE))
                    ev->value_mask &= ~(CWSibling | CWStackMode);
                    TRACE ("Setting WM_STATE_DEMANDS_ATTENTION flag on \"%s\" (0x%lx)", c->name, c->window);
                    FLAG_SET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
                    clientSetNetState (c);
                }
                else
                {
                    clientActivate (c, getXServerTime (display_info));
        clientConfigure (c, &wc, ev->value_mask, (constrained ? CFG_CONSTRAINED : 0) | CFG_REQUEST);
        TRACE ("unmanaged configure request for win 0x%lx", ev->window);
        XConfigureWindow (display_info->dpy, ev->window, ev->value_mask, &wc);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
handleEnterNotify (DisplayInfo *display_info, XCrossingEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    static Time lastresist = (Time) CurrentTime;
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    Client *c;
    gboolean warp_pointer, need_redraw;
Olivier Fourdan's avatar
Olivier Fourdan committed

    /* See http://rfc-ref.org/RFC-TEXTS/1013/chapter12.html for details */

    TRACE ("entering handleEnterNotify");
Olivier Fourdan's avatar
Olivier Fourdan committed

    if ((ev->mode == NotifyGrab) || (ev->mode == NotifyUngrab)
        || (ev->detail > NotifyNonlinearVirtual))
        /* We're not interested in such notifications */
Olivier Fourdan's avatar
Olivier Fourdan committed

    TRACE ("EnterNotify on window (0x%lx)", ev->window);
Olivier Fourdan's avatar
Olivier Fourdan committed

Olivier Fourdan's avatar
Olivier Fourdan committed
    warp_pointer = FALSE;
    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_FRAME | SEARCH_BUTTON);
    if (c)
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        screen_info = c->screen_info;
Olivier Fourdan's avatar
Olivier Fourdan committed

        TRACE ("EnterNotify window is \"%s\"", c->name);
        if (c == clientGetFocus ())
        {
            for (b = 0; b < BUTTON_COUNT; b++)
            {
                if (MYWINDOW_XWINDOW(c->buttons[b]) == ev->window)
                {
                    if (!xfwmPixmapNone(clientGetButtonPixmap(c, b, PRELIGHT)))
                    {
                        c->button_status[b] = BUTTON_STATE_PRELIGHT;
                        need_redraw = TRUE;
                    }
                frameQueueDraw (c, FALSE);
Olivier Fourdan's avatar
Olivier Fourdan committed
        else if (!(screen_info->params->click_to_focus) && clientAcceptFocus (c))
        {
            if (!(c->type & (WINDOW_DOCK | WINDOW_DESKTOP)))
            {
                if(screen_info->params->focus_delay)
                {
                    clientClearDelayedFocus ();
                    clientAddDelayedFocus (c);
                }
                else
                {
                    clientSetFocus (c->screen_info, c, ev->time, NO_FOCUS_FLAG);
                }
            }
            else
            {
                clientClearDelayedFocus ();
            }
        }

    if (display_info->nb_screens > 1)
    {
        /* Wrap workspace/wrap windows is disabled with multiscreen */
    /* Get the screen structure from the root of the event */
    screen_info = myDisplayGetScreenFromRoot (display_info, ev->root);

    if (!screen_info)
    {
    if (screen_info->workspace_count && screen_info->params->wrap_workspaces
        && screen_info->params->wrap_resistance)
    {
        int msx, msy, maxx, maxy;
        int rx, ry;

        maxx = screen_info->width - 1;
        maxy = screen_info->height - 1;
            if ((ev->time - lastresist) > 250)  /* ms */
            {
                edge_scroll_x = 0;
            }
            else
            {
                edge_scroll_x++;
            }
            warp_pointer = TRUE;
            lastresist = ev->time;
        }
        if ((msy == 0) || (msy == maxy))
        {
            if ((ev->time - lastresist) > 250)  /* ms */
            {
                edge_scroll_y = 0;
            }
            else
            {
                edge_scroll_y++;
            }
            warp_pointer = TRUE;
        if (edge_scroll_x > screen_info->params->wrap_resistance)
        {
                if (workspaceMove (screen_info, 0, -1, NULL, ev->time))
                    rx = 4 * maxx / 5;
                if (workspaceMove (screen_info, 0, 1, NULL, ev->time))
                    rx = -4 * maxx / 5;
        }
        if (edge_scroll_y > screen_info->params->wrap_resistance)
        {
            edge_scroll_y = 0;
                if (workspaceMove (screen_info, -1, 0, NULL, ev->time))
                    ry = 4 * maxy / 5;
                if (workspaceMove (screen_info, 1, 0, NULL, ev->time))
                    ry = -4 * maxy / 5;
            warp_pointer = TRUE;
        }
        if (warp_pointer)
        {
            XWarpPointer (display_info->dpy, None, None, 0, 0, 0, 0, rx, ry);
            XFlush (display_info->dpy);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
handleLeaveNotify (DisplayInfo *display_info, XCrossingEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
    gboolean need_redraw;
    TRACE ("entering handleLeaveNotify");
    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_FRAME | SEARCH_BUTTON);
    if (c)
    {
        for (b = 0; b < BUTTON_COUNT; b++)
        {
            if ((c->button_status[b] == BUTTON_STATE_PRELIGHT) || (c->button_status[b] == BUTTON_STATE_PRESSED))
            {
                if (MYWINDOW_XWINDOW(c->buttons[b]) == ev->window)
                {
                    c->button_status[b] = BUTTON_STATE_NORMAL;
            frameQueueDraw (c, FALSE);
        }

        /* No need to process the event any further */
        return EVENT_FILTER_REMOVE;
    }


handleFocusIn (DisplayInfo *display_info, XFocusChangeEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    Client *c, *user_focus, *current_focus;
    /* See http://rfc-ref.org/RFC-TEXTS/1013/chapter12.html for details */
Olivier Fourdan's avatar
Olivier Fourdan committed

    TRACE ("entering handleFocusIn");
    TRACE ("handleFocusIn (0x%lx) mode = %s",
Olivier Fourdan's avatar
Olivier Fourdan committed
                ev->window,
                (ev->mode == NotifyNormal) ?
                "NotifyNormal" :
                (ev->mode == NotifyWhileGrabbed) ?
                "NotifyWhileGrabbed" :
                (ev->mode == NotifyGrab) ?
                "NotifyGrab" :
                (ev->mode == NotifyUngrab) ?
                "NotifyUngrab" :
Olivier Fourdan's avatar
Olivier Fourdan committed
                "(unknown)");
    TRACE ("handleFocusIn (0x%lx) detail = %s",
Olivier Fourdan's avatar
Olivier Fourdan committed
                ev->window,
                (ev->detail == NotifyAncestor) ?
                "NotifyAncestor" :
                (ev->detail == NotifyVirtual) ?
                "NotifyVirtual" :
                (ev->detail == NotifyInferior) ?
                "NotifyInferior" :
                (ev->detail == NotifyNonlinear) ?
                "NotifyNonlinear" :
                (ev->detail == NotifyNonlinearVirtual) ?
                "NotifyNonlinearVirtual" :
                (ev->detail == NotifyPointer) ?
                "NotifyPointer" :
                (ev->detail == NotifyPointerRoot) ?
                "NotifyPointerRoot" :
                (ev->detail == NotifyDetailNone) ?
                "NotifyDetailNone" :
                "(unknown)");
    screen_info = myDisplayGetScreenFromWindow (display_info, ev->window);
    if (!screen_info)
    {
        /* Not for us */
Olivier Fourdan's avatar
Olivier Fourdan committed

    if ((ev->window == screen_info->xroot)
        && ((ev->detail == NotifyDetailNone)
            || ((ev->mode == NotifyNormal) && (ev->detail == NotifyInferior))))
           Handle unexpected focus transition to root (means that an unknown
           window has vanished and the focus is returned to the root).
        clientSetFocus (screen_info, c, getXServerTime (display_info), FOCUS_FORCE);
    if ((ev->mode == NotifyGrab) || (ev->mode == NotifyUngrab))
        /* We're not interested in such notifications */
    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_FRAME | SEARCH_WINDOW);
    user_focus = clientGetUserFocus ();
    TRACE ("FocusIn on window (0x%lx)", ev->window);
    if ((c) && (c != current_focus) && (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_VISIBLE)))
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        TRACE ("Focus transfered to \"%s\" (0x%lx)", c->name, c->window);
        screen_info = c->screen_info;
        clientUpdateFocus (screen_info, c, FOCUS_SORT);
        if ((user_focus != c) && (user_focus != NULL))
               Focus stealing prevention:
               Some apps tend to focus the window directly. If focus stealing prevention is enabled,
               we revert the user set focus to the window that we think has focus and then set the

               Note that focus stealing prevention is ignored between windows of the same group or
               between windows that have a transient relationship, as some apps tend to play with
               focus with their "own" windows.

            if (screen_info->params->prevent_focus_stealing &&
                !clientSameGroup (c, user_focus) &&
                !clientIsTransientOrModalFor (c, user_focus))
                TRACE ("Setting focus back to \"%s\" (0x%lx)", user_focus->name, user_focus->window);
                clientSetFocus (user_focus->screen_info, user_focus, getXServerTime (display_info), NO_FOCUS_FLAG);
                    TRACE ("Setting WM_STATE_DEMANDS_ATTENTION flag on \"%s\" (0x%lx)", c->name, c->window);
                    FLAG_SET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
                    clientSetNetState (c);
                }
        if (screen_info->params->raise_on_focus)
Olivier Fourdan's avatar
Olivier Fourdan committed
            clientResetDelayedRaise (screen_info);
handleFocusOut (DisplayInfo *display_info, XFocusChangeEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;
    /* See http://rfc-ref.org/RFC-TEXTS/1013/chapter12.html for details */

    TRACE ("entering handleFocusOut");
Olivier Fourdan's avatar
Olivier Fourdan committed
    TRACE ("handleFocusOut (0x%lx) mode = %s",
                ev->window,
                (ev->mode == NotifyNormal) ?
                "NotifyNormal" :
                (ev->mode == NotifyWhileGrabbed) ?
                "NotifyWhileGrabbed" :
                "(unknown)");
    TRACE ("handleFocusOut (0x%lx) detail = %s",
                ev->window,
                (ev->detail == NotifyAncestor) ?
                "NotifyAncestor" :
                (ev->detail == NotifyVirtual) ?
                "NotifyVirtual" :
                (ev->detail == NotifyInferior) ?
                "NotifyInferior" :
                (ev->detail == NotifyNonlinear) ?
                "NotifyNonlinear" :
                (ev->detail == NotifyNonlinearVirtual) ?
                "NotifyNonlinearVirtual" :
                (ev->detail == NotifyPointer) ?
                "NotifyPointer" :
                (ev->detail == NotifyPointerRoot) ?
                "NotifyPointerRoot" :
                (ev->detail == NotifyDetailNone) ?
                "NotifyDetailNone" :
                "(unknown)");
    if ((ev->mode == NotifyGrab) || (ev->mode == NotifyUngrab) ||
        (ev->detail == NotifyInferior) || (ev->detail > NotifyNonlinearVirtual))
    {
        /* We're not interested in such notifications */
    if ((ev->mode == NotifyNormal)
        && ((ev->detail == NotifyNonlinear)
            || (ev->detail == NotifyNonlinearVirtual)))
        c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_FRAME | SEARCH_WINDOW);
        TRACE ("FocusOut on window (0x%lx)", ev->window);
        {
            TRACE ("focus lost from \"%s\" (0x%lx)", c->name, c->window);
            clientUpdateFocus (c->screen_info, NULL, NO_FOCUS_FLAG);
Olivier Fourdan's avatar
Olivier Fourdan committed
            clientClearDelayedRaise ();
handlePropertyNotify (DisplayInfo *display_info, XPropertyEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    Client *c;
Olivier Fourdan's avatar
Olivier Fourdan committed

    TRACE ("entering handlePropertyNotify");

    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_WINDOW);
        status = EVENT_FILTER_REMOVE;
        screen_info = c->screen_info;
        if (ev->atom == XA_WM_NORMAL_HINTS)
        {
            TRACE ("client \"%s\" (0x%lx) has received a XA_WM_NORMAL_HINTS notify", c->name, c->window);
            clientGetWMNormalHints (c, TRUE);
        else if ((ev->atom == XA_WM_NAME) ||
                 (ev->atom == display_info->atoms[NET_WM_NAME]) ||
                 (ev->atom == display_info->atoms[WM_CLIENT_MACHINE]))
            TRACE ("client \"%s\" (0x%lx) has received a XA_WM_NAME/NET_WM_NAME/WM_CLIENT_MACHINE notify", c->name, c->window);
        else if (ev->atom == display_info->atoms[MOTIF_WM_HINTS])
            TRACE ("client \"%s\" (0x%lx) has received a MOTIF_WM_HINTS notify", c->name, c->window);
            clientGetMWMHints (c, TRUE);
        }
        else if (ev->atom == XA_WM_HINTS)
        {
            TRACE ("client \"%s\" (0x%lx) has received a XA_WM_HINTS notify", c->name, c->window);
            c->wmhints = XGetWMHints (display_info->dpy, c->window);
                if (c->wmhints->flags & WindowGroupHint)
                {
                    c->group_leader = c->wmhints->window_group;
                }
                if ((c->wmhints->flags & IconPixmapHint) && (screen_info->params->show_app_icon))
                {
                    clientUpdateIcon (c);
                }
                if (HINTS_ACCEPT_INPUT (c->wmhints))
                {
                    FLAG_SET (c->wm_flags, WM_FLAG_INPUT);
                }
                else
                {
                    FLAG_UNSET (c->wm_flags, WM_FLAG_INPUT);
                }
            clientUpdateUrgency (c);
        else if (ev->atom == display_info->atoms[WM_PROTOCOLS])
            TRACE ("client \"%s\" (0x%lx) has received a WM_PROTOCOLS notify", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
            clientGetWMProtocols (c);
        }
        else if (ev->atom == display_info->atoms[WM_TRANSIENT_FOR])
            TRACE ("client \"%s\" (0x%lx) has received a WM_TRANSIENT_FOR notify", c->name, c->window);
            getTransientFor (display_info, c->screen_info->xroot, c->window, &w);
            if (clientCheckTransientWindow (c, w))
            {
                c->transient_for = w;
                /*
                  Java 1.6 updates the WM_TRANSIENT_FOR properties "on-the-fly"
                  of its windows to maintain the z-order.

                  If we raise the transient then, we clearly have a race
                  condition between the WM and Java... And that breaks
                  I still think that raising here makes sense, to ensure
                  that the newly promoted transient window is placed above
                  its parent.
                  Chances are that Java 1.6 won't change any time soon (heh,
                  it's not even released yet), so let's adjust the WM to
                  work with Java 1.6...
                 */
        else if (ev->atom == display_info->atoms[WIN_HINTS])
            TRACE ("client \"%s\" (0x%lx) has received a WIN_HINTS notify", c->name, c->window);
            getHint (display_info, c->window, WIN_HINTS, (long *) &c->win_hints);
        else if (ev->atom == display_info->atoms[NET_WM_WINDOW_TYPE])
            TRACE ("client \"%s\" (0x%lx) has received a NET_WM_WINDOW_TYPE notify", c->name, c->window);
            clientGetNetWmType (c);
            frameQueueDraw (c, TRUE);
        else if ((ev->atom == display_info->atoms[NET_WM_STRUT]) ||
                 (ev->atom == display_info->atoms[NET_WM_STRUT_PARTIAL]))
            TRACE ("client \"%s\" (0x%lx) has received a NET_WM_STRUT notify", c->name, c->window);
            if (clientGetNetStruts (c) && FLAG_TEST (c->xfwm_flags, XFWM_FLAG_VISIBLE))
            {
                workspaceUpdateArea (c->screen_info);
            }
        else if (ev->atom == display_info->atoms[WM_COLORMAP_WINDOWS])
            TRACE ("client \"%s\" (0x%lx) has received a WM_COLORMAP_WINDOWS notify", c->name, c->window);
            clientUpdateColormaps (c);
            if (c == clientGetFocus ())
            {
                clientInstallColormaps (c);
            }
        }
        else if (ev->atom == display_info->atoms[NET_WM_USER_TIME])
            TRACE ("client \"%s\" (0x%lx) has received a NET_WM_USER_TIME notify", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
            if (getNetWMUserTime (display_info, c->window, &c->user_time) && (c->user_time != 0))
                myDisplaySetLastUserTime (display_info, c->user_time);
                FLAG_SET (c->flags, CLIENT_FLAG_HAS_USER_TIME);
        else if (ev->atom == display_info->atoms[NET_WM_WINDOW_OPACITY])
            TRACE ("client \"%s\" (0x%lx) has received a NET_WM_OPACITY notify", c->name, c->window);
            if (!getOpacity (display_info, c->window, &c->opacity))
                c->opacity =  NET_WM_OPAQUE;
            compositorWindowSetOpacity (display_info, c->frame, c->opacity);
        else if (ev->atom == display_info->atoms[NET_WM_WINDOW_OPACITY_LOCKED])
        {
            TRACE ("client \"%s\" (0x%lx) has received a NET_WM_OPACITY_LOCKED notify", c->name, c->window);
            if (getOpacityLock (display_info, c->window))
            {
                FLAG_SET (c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED);
            }
            else
            {
                FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_OPACITY_LOCKED);
            }
        else if ((screen_info->params->show_app_icon) &&
                 ((ev->atom == display_info->atoms[NET_WM_ICON]) ||
                  (ev->atom == display_info->atoms[KWM_WIN_ICON])))
        {
            clientUpdateIcon (c);
        }
#ifdef HAVE_STARTUP_NOTIFICATION
        else if (ev->atom == display_info->atoms[NET_STARTUP_ID])
            getWindowStartupId (display_info, c->window, &c->startup_id);
#endif /* HAVE_STARTUP_NOTIFICATION */
#ifdef HAVE_XSYNC
        else if (ev->atom == display_info->atoms[NET_WM_SYNC_REQUEST_COUNTER])
        {
            getXSyncCounter (display_info, c->window, &c->xsync_counter);
            TRACE ("Window 0x%lx has NET_WM_SYNC_REQUEST_COUNTER set to 0x%lx", c->window, c->xsync_counter);
        }
#endif /* HAVE_XSYNC */

    screen_info = myDisplayGetScreenFromWindow (display_info, ev->window);
    if (!screen_info)
    {
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
    if (ev->atom == display_info->atoms[NET_DESKTOP_NAMES])