Skip to content
Snippets Groups Projects
netwm.c 45.2 KiB
Newer Older
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    DisplayInfo *display_info;
    unsigned long old_flags, new_flags;
    int old_struts[STRUTS_SIZE];
Olivier Fourdan's avatar
Olivier Fourdan committed
    gulong *struts;
    g_return_val_if_fail (c != NULL, FALSE);
    TRACE ("entering clientGetNetStruts for \"%s\" (0x%lx)", c->name, c->window);

    screen_info = c->screen_info;
    display_info = screen_info->display_info;
Olivier Fourdan's avatar
Olivier Fourdan committed
    struts = NULL;
    /* Save old values */
    old_flags = c->flags & (CLIENT_FLAG_HAS_STRUT | CLIENT_FLAG_HAS_STRUT_PARTIAL);
    for (i = 0; i < STRUTS_SIZE; i++)
        old_struts[i] = c->struts[i];
        c->struts[i] = 0;
    }
    FLAG_UNSET (c->flags, CLIENT_FLAG_HAS_STRUT);
    FLAG_UNSET (c->flags, CLIENT_FLAG_HAS_STRUT_PARTIAL);

    if (getCardinalList (display_info, c->window, NET_WM_STRUT_PARTIAL, &struts, &nitems))
            if (struts)
            {
                XFree (struts);
            }
            /* Restore old values */
            if (old_flags)
            {
                FLAG_SET (c->flags, old_flags);
                for (i = 0; i < STRUTS_SIZE; i++)
                {
                    c->struts[i] = old_struts[i];
                }
            }
            return FALSE;
        }

        FLAG_SET (c->flags, CLIENT_FLAG_HAS_STRUT);
        FLAG_SET (c->flags, CLIENT_FLAG_HAS_STRUT_PARTIAL);
        for (i = 0; i < STRUTS_SIZE; i++)
    else if (getCardinalList (display_info, c->window, NET_WM_STRUT, &struts, &nitems))
            if (struts)
            {
                XFree (struts);
            }
            /* Restore old values */
            if (old_flags)
            {
                FLAG_SET (c->flags, old_flags);
                for (i = 0; i < STRUTS_SIZE; i++)
                {
                    c->struts[i] = old_struts[i];
                }
            }
            return FALSE;
        }

        FLAG_SET (c->flags, CLIENT_FLAG_HAS_STRUT);
        for (i = 0; i < 4; i++)
        {
            c->struts[i] = (int) struts[i];
        }
        for (i = 4; i < STRUTS_SIZE; i++)
        c->struts[STRUTS_TOP_START_X] = c->struts[STRUTS_BOTTOM_START_X] = 0;
        c->struts[STRUTS_TOP_END_X] = c->struts[STRUTS_BOTTOM_END_X] =
        c->struts[STRUTS_LEFT_START_Y] = c->struts[STRUTS_RIGHT_START_Y] = 0;
        c->struts[STRUTS_LEFT_END_Y] = c->struts[STRUTS_RIGHT_END_Y] =

    if (FLAG_TEST (c->flags, CLIENT_FLAG_HAS_STRUT))
    {
        clientValidateNetStrut (c);
    }

    /* check for a change in struts flags */
    new_flags = c->flags & (CLIENT_FLAG_HAS_STRUT | CLIENT_FLAG_HAS_STRUT_PARTIAL);
    if (old_flags != new_flags)
    {
        return TRUE;
    }

    /* Flags haven't changed, check values */
    if (new_flags)
    {
        for (i = 0; i < STRUTS_SIZE; i++)
        {
            if (old_struts[i] != c->struts[i])
            {
                return TRUE;
            }
        }
    }

    return FALSE;
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    DisplayInfo *display_info;
Olivier Fourdan's avatar
Olivier Fourdan committed
    int i;
    g_return_if_fail (c != NULL);
    TRACE ("entering clientSetNetActions");

    screen_info = c->screen_info;
    display_info = screen_info->display_info;
Olivier Fourdan's avatar
Olivier Fourdan committed
    i = 0;

    atoms[i++] = display_info->atoms[NET_WM_ACTION_CLOSE];
    atoms[i++] = display_info->atoms[NET_WM_ACTION_ABOVE];
    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_VISIBLE))
        atoms[i++] = display_info->atoms[NET_WM_ACTION_FULLSCREEN];
        if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE))
        {
            atoms[i++] = display_info->atoms[NET_WM_ACTION_MOVE];
        }
        if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_RESIZE) &&
            !((FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED)
               && (screen_info->params->borderless_maximize))))
        {
            atoms[i++] = display_info->atoms[NET_WM_ACTION_RESIZE];
        }
        if (CLIENT_CAN_MAXIMIZE_WINDOW (c))
        {
            atoms[i++] = display_info->atoms[NET_WM_ACTION_MAXIMIZE_HORZ];
            atoms[i++] = display_info->atoms[NET_WM_ACTION_MAXIMIZE_VERT];
        }
        if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_BORDER))
        {
            atoms[i++] = display_info->atoms[NET_WM_ACTION_SHADE];
        }
    if (CLIENT_CAN_HIDE_WINDOW (c))
    {
        atoms[i++] = display_info->atoms[NET_WM_ACTION_MINIMIZE];
    }
Olivier Fourdan's avatar
Olivier Fourdan committed
    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_STICK))
        atoms[i++] = display_info->atoms[NET_WM_ACTION_CHANGE_DESKTOP];
        atoms[i++] = display_info->atoms[NET_WM_ACTION_STICK];
    XChangeProperty (clientGetXDisplay (c), c->window, display_info->atoms[NET_WM_ALLOWED_ACTIONS],
                     XA_ATOM, 32, PropModeReplace, (unsigned char *) atoms, i);
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    DisplayInfo *display_info;
    netWindowType old_type;

    g_return_if_fail (c != NULL);
    TRACE ("entering clientWindowType");
    TRACE ("type for client \"%s\" (0x%lx)", c->name, c->window);

    screen_info = c->screen_info;
    display_info = screen_info->display_info;

    old_type = c->type;
    c->initial_layer = c->win_layer;
    if (c->type_atom != None)
    {
        if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_DESKTOP])
        {
            TRACE ("atom net_wm_window_type_desktop detected");
            c->type = WINDOW_DESKTOP;
            c->initial_layer = WIN_LAYER_DESKTOP;
            c->win_state |= WIN_STATE_STICKY;
            FLAG_SET (c->flags,
                CLIENT_FLAG_SKIP_PAGER | CLIENT_FLAG_STICKY |
                CLIENT_FLAG_SKIP_TASKBAR);
Olivier Fourdan's avatar
Olivier Fourdan committed
            FLAG_UNSET (c->xfwm_flags,
                XFWM_FLAG_HAS_RESIZE | XFWM_FLAG_HAS_MOVE |
                XFWM_FLAG_HAS_HIDE | XFWM_FLAG_HAS_MAXIMIZE |
Olivier Fourdan's avatar
Olivier Fourdan committed
                XFWM_FLAG_HAS_MENU | XFWM_FLAG_HAS_STICK |
                XFWM_FLAG_HAS_BORDER);
        else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_DOCK])
        {
            TRACE ("atom net_wm_window_type_dock detected");
            c->type = WINDOW_DOCK;
            c->initial_layer = WIN_LAYER_DOCK;
             FLAG_SET (c->flags,
                CLIENT_FLAG_SKIP_PAGER | CLIENT_FLAG_STICKY |
                CLIENT_FLAG_SKIP_TASKBAR);
Olivier Fourdan's avatar
Olivier Fourdan committed
            FLAG_UNSET (c->xfwm_flags,
                XFWM_FLAG_HAS_BORDER |  XFWM_FLAG_HAS_MOVE |
                XFWM_FLAG_HAS_HIDE | XFWM_FLAG_HAS_MAXIMIZE |
        else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_TOOLBAR])
        {
            TRACE ("atom net_wm_window_type_toolbar detected");
            c->type = WINDOW_TOOLBAR;
            c->initial_layer = WIN_LAYER_NORMAL;
            FLAG_SET (c->flags,
                CLIENT_FLAG_SKIP_PAGER | CLIENT_FLAG_SKIP_TASKBAR);
Olivier Fourdan's avatar
Olivier Fourdan committed
            FLAG_UNSET (c->xfwm_flags,
                XFWM_FLAG_HAS_HIDE | XFWM_FLAG_HAS_MAXIMIZE);
        else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_MENU])
        {
            TRACE ("atom net_wm_window_type_menu detected");
            c->type = WINDOW_MENU;
            c->initial_layer = WIN_LAYER_NORMAL;
            /* The policy here is unclear :
               http://mail.gnome.org/archives/wm-spec-list/2002-May/msg00001.html
               As it seems, GNOME and KDE don't treat menu the same way...
             */
            FLAG_SET (c->flags,
                CLIENT_FLAG_SKIP_PAGER | CLIENT_FLAG_SKIP_TASKBAR);
Olivier Fourdan's avatar
Olivier Fourdan committed
            FLAG_UNSET (c->xfwm_flags,
                XFWM_FLAG_HAS_HIDE | XFWM_FLAG_HAS_MAXIMIZE);
        else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_DIALOG])
        {
            TRACE ("atom net_wm_window_type_dialog detected");
            c->type = WINDOW_DIALOG;
            c->initial_layer = WIN_LAYER_NORMAL;
            /* Treat DIALOG without transient_for set as transient for group */
            if (c->transient_for == None)
            {
                c->transient_for = c->screen_info->xroot;
            }
        else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_NORMAL])
        {
            TRACE ("atom net_wm_window_type_normal detected");
            c->type = WINDOW_NORMAL;
            c->initial_layer = WIN_LAYER_NORMAL;
        }
        else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_UTILITY])
        {
            TRACE ("atom net_wm_window_type_utility detected");
            FLAG_SET (c->flags,
                CLIENT_FLAG_SKIP_PAGER | CLIENT_FLAG_SKIP_TASKBAR);
            c->type = WINDOW_UTILITY;
            c->initial_layer = WIN_LAYER_NORMAL;
            /* Treat UTILITY without transient_for set as transient for group */
            if (c->transient_for == None)
            {
                c->transient_for = c->screen_info->xroot;
            }
        else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_SPLASH])
            TRACE ("atom net_wm_window_type_splash detected");
            FLAG_SET (c->flags,
                CLIENT_FLAG_SKIP_PAGER | CLIENT_FLAG_SKIP_TASKBAR);
Olivier Fourdan's avatar
Olivier Fourdan committed
            FLAG_UNSET (c->xfwm_flags,
                XFWM_FLAG_HAS_BORDER | XFWM_FLAG_HAS_HIDE |
                XFWM_FLAG_HAS_MENU | XFWM_FLAG_HAS_MOVE |
        }
    }
    else
    {
        TRACE ("no \"net\" atom detected");
        c->type = UNSET;
        c->initial_layer = c->win_layer;
    }

    {
        Client *c2;

        TRACE ("Window \"%s\" is a transient or a modal", c->name);

        c2 = clientGetHighestTransientOrModalFor (c);
        if ((c2) && (c->initial_layer < c2->win_layer))
            c->initial_layer = c2->win_layer;
            TRACE ("Applied layer is %i", c->initial_layer);
        }
        FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_HAS_HIDE);
    }
    if ((old_type != c->type) || (c->initial_layer != c->win_layer))
    {
        TRACE ("setting layer %i", c->initial_layer);
        clientSetNetState (c);
        clientSetLayer (c, c->initial_layer);
    }
}

void
clientUpdateAboveState (Client * c)
{
    int layer;

    g_return_if_fail (c != NULL);
    TRACE ("entering clientUpdateAboveState");
    TRACE ("Update above state for client \"%s\" (0x%lx)", c->name, c->window);

    if (FLAG_TEST (c->flags, CLIENT_FLAG_ABOVE))
    {
        layer = WIN_LAYER_ABOVE_DOCK;
    }
    else
    {
        layer = c->initial_layer;
    }
    clientSetNetState (c);
    clientSetLayer (c, layer);
}

void
clientUpdateBelowState (Client * c)
{
    int layer;

    g_return_if_fail (c != NULL);
    TRACE ("entering clientUpdateBelowState");
    TRACE ("Update below state for client \"%s\" (0x%lx)", c->name, c->window);

    if (FLAG_TEST (c->flags, CLIENT_FLAG_BELOW))
    {
        layer = WIN_LAYER_BELOW;
    }
    else
    {
        layer = c->initial_layer;
    }
    clientSetNetState (c);
    clientSetLayer (c, layer);
}