Logo Search packages:      
Sourcecode: afterstep version File versions

pager.c

/*
 * Copyright (c) 2003 Sasha Vasko <sasha@ aftercode.net>
 * Copyright (c) 1999 Ethan Fischer <allanon@crystaltokyo.com>
 * Copyright (C) 1993 Robert Nation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/***********************************************************************
 *
 * afterstep pager handling code
 *
 ***********************************************************************/

#define LOCAL_DEBUG
#include "../../configure.h"

#include "asinternals.h"

#include "../../libAfterStep/wmprops.h"
#include "../../libAfterStep/session.h"
#include "../../libAfterStep/moveresize.h"


/***************************************************************************
 *
 * Check to see if the pointer is on the edge of the screen, and scroll/page
 * if needed
 ***************************************************************************/
void
HandlePaging (int HorWarpSize, int VertWarpSize, int *xl, int *yt,
              int *delta_x, int *delta_y, Bool Grab, ASEvent *event)
{
#ifndef NO_VIRTUAL
      int           x, y, total;
#endif
    Window wdumm;
    int    dumm;
    unsigned int udumm;

      *delta_x = 0;
      *delta_y = 0;

#ifndef NO_VIRTUAL
      if (DoHandlePageing)
      {
        if ((Scr.Feel.EdgeResistanceScroll >= 10000) || ((HorWarpSize == 0) && (VertWarpSize == 0)))
                  return;

            /* need to move the viewport */
            if ((*xl >= SCROLL_REGION) && (*xl < Scr.MyDisplayWidth - SCROLL_REGION) &&
                  (*yt >= SCROLL_REGION) && (*yt < Scr.MyDisplayHeight - SCROLL_REGION))
                  return;

            total = 0;
        while (total < (int)Scr.Feel.EdgeResistanceScroll)
            {
            register int i ;
                  sleep_a_millisec(10);
                  total += 10;
            for( i = 0 ; i < PAN_FRAME_SIDES ; i++ )
                if( Scr.PanFrame[i].isMapped )
                    if (ASCheckWindowEvent (Scr.PanFrame[i].win, LeaveWindowMask, &(event->x)))
                        return;
        }

        XQueryPointer (dpy, Scr.Root, &wdumm, &wdumm, &x, &y, &dumm, &dumm, &udumm);

            /* fprintf (stderr, "-------- MoveOutline () called from pager.c\ntmp_win == 0xlX\n", (long int) tmp_win); */
            /* Turn off the rubberband if its on */
            /*        MoveOutline ( Scr.Root,  tmp_win, 0, 0, 0, 0); */

            /* Move the viewport */
            /* and/or move the cursor back to the approximate correct location */
            /* that is, the same place on the virtual desktop that it */
            /* started at */
            if (x < SCROLL_REGION)
                  *delta_x = -HorWarpSize;
            else if (x >= Scr.MyDisplayWidth - SCROLL_REGION)
                  *delta_x = HorWarpSize;
            else
                  *delta_x = 0;
            if (y < SCROLL_REGION)
                  *delta_y = -VertWarpSize;
            else if (y >= Scr.MyDisplayHeight - SCROLL_REGION)
                  *delta_y = VertWarpSize;
            else
                  *delta_y = 0;

            /* Ouch! lots of bounds checking */
            if (Scr.Vx + *delta_x < 0)
            {
            if (!get_flags(Scr.Feel.flags, EdgeWrapX))
                  {
                        *delta_x = -Scr.Vx;
                        *xl = x - *delta_x;
                  } else
                  {
                        *delta_x += Scr.VxMax + Scr.MyDisplayWidth;
                        *xl = x + *delta_x % Scr.MyDisplayWidth + HorWarpSize;
                  }
            } else if (Scr.Vx + *delta_x > Scr.VxMax)
            {
            if (!get_flags(Scr.Feel.flags, EdgeWrapX))
                  {
                        *delta_x = Scr.VxMax - Scr.Vx;
                        *xl = x - *delta_x;
                  } else
                  {
                        *delta_x -= Scr.VxMax + Scr.MyDisplayWidth;
                        *xl = x + *delta_x % Scr.MyDisplayWidth - HorWarpSize;
                  }
            } else
                  *xl = x - *delta_x;

            if (Scr.Vy + *delta_y < 0)
            {
            if (!get_flags(Scr.Feel.flags, EdgeWrapY))
                  {
                        *delta_y = -Scr.Vy;
                        *yt = y - *delta_y;
                  } else
                  {
                        *delta_y += Scr.VyMax + Scr.MyDisplayHeight;
                        *yt = y + *delta_y % Scr.MyDisplayHeight + VertWarpSize;
                  }
            } else if (Scr.Vy + *delta_y > Scr.VyMax)
            {
            if (!get_flags(Scr.Feel.flags, EdgeWrapY))
                  {
                        *delta_y = Scr.VyMax - Scr.Vy;
                        *yt = y - *delta_y;
                  } else
                  {
                        *delta_y -= Scr.VyMax + Scr.MyDisplayHeight;
                        *yt = y + *delta_y % Scr.MyDisplayHeight - VertWarpSize;
                  }
            } else
                  *yt = y - *delta_y;

            if (*xl <= SCROLL_REGION)
                  *xl = SCROLL_REGION + 1;
            if (*yt <= SCROLL_REGION)
                  *yt = SCROLL_REGION + 1;
            if (*xl >= Scr.MyDisplayWidth - SCROLL_REGION)
                  *xl = Scr.MyDisplayWidth - SCROLL_REGION - 1;
            if (*yt >= Scr.MyDisplayHeight - SCROLL_REGION)
                  *yt = Scr.MyDisplayHeight - SCROLL_REGION - 1;

            if ((*delta_x != 0) || (*delta_y != 0))
            {
                  if (Grab)
                        grab_server();
                  XWarpPointer (dpy, None, Scr.Root, 0, 0, 0, 0, *xl, *yt);
                  MoveViewport (Scr.Vx + *delta_x, Scr.Vy + *delta_y, False);
            XQueryPointer (dpy, Scr.Root, &wdumm, &wdumm, xl, yt, &dumm, &dumm, &udumm);
                  if (Grab)
                        ungrab_server();
            }
      }
#endif
}

/***************************************************************************
 *
 *  Moves the viewport within the virtual desktop
 *
 ***************************************************************************/

Bool
viewport_aswindow_iter_func( void *data, void *aux_data )
{
    ASWindow *asw = (ASWindow*)data ;
    if( asw )
    {
        asw->status->viewport_x = Scr.Vx ;
        asw->status->viewport_y = Scr.Vy ;
        if( !ASWIN_GET_FLAGS(asw,AS_Sticky) )
            on_window_status_changed( asw, True, True );

        if( ASWIN_GET_FLAGS(asw,AS_Iconic) && get_flags(Scr.Feel.flags, StickyIcons))
        {   /* we must update let all the modules know that icon viewport has changed
             * we dont have to do that for Sticky non-iconified windows, since its assumed
             * that those follow viewport, while Icons only do that when StckiIcons is set. */
            broadcast_config (M_CONFIGURE_WINDOW, asw);
        }
    }
    return True;
}


void
MoveViewport (int newx, int newy, Bool grab)
{

      ChangeDeskAndViewport ( Scr.CurrentDesk, newx, newy, grab);

#if 0
#ifndef NO_VIRTUAL
      int           deltax, deltay;

LOCAL_DEBUG_CALLER_OUT( "new(%+d%+d), old(%+d%+d), max(%+d,%+d)", newx, newy, Scr.Vx, Scr.Vy, Scr.VxMax, Scr.VyMax );

    if (newx > Scr.VxMax)
            newx = Scr.VxMax;
      if (newy > Scr.VyMax)
            newy = Scr.VyMax;
      if (newx < 0)
            newx = 0;
      if (newy < 0)
            newy = 0;

      deltay = Scr.Vy - newy;
      deltax = Scr.Vx - newx;

      Scr.Vx = newx;
      Scr.Vy = newy;
    SendPacket( -1, M_NEW_PAGE, 3, Scr.Vx, Scr.Vy, Scr.CurrentDesk);
    set_current_viewport_prop (Scr.wmprops, Scr.Vx, Scr.Vy, get_flags( AfterStepState, ASS_NormalOperation));

      if (deltax || deltay)
      {
            if (grab)
                  grab_server();
        /* traverse window list and redo the titlebar/buttons if necessary */
        iterate_asbidirlist( Scr.Windows->clients, viewport_aswindow_iter_func, NULL, NULL, False );
        /* TODO: autoplace sticky icons so they don't wind up over a stationary icon */
          check_screen_panframes(ASDefaultScr);
            if (grab)
                  ungrab_server();
    }
#endif
#endif
}

/**************************************************************************
 * Move to a new desktop
 *************************************************************************/
Bool
deskviewport_aswindow_iter_func(void *data, void *aux_data)
{
    ASWindow *asw = (ASWindow *)data ;
    int new_desk = (int)Scr.CurrentDesk ;
      int dvx = asw->status->viewport_x - Scr.Vx ;
      int dvy = asw->status->viewport_y - Scr.Vy ;
      union {
            void *ptr ;
            int id ;
      }old_desk ;
      old_desk.ptr = aux_data;

    asw->status->viewport_x = Scr.Vx ;
    asw->status->viewport_y = Scr.Vy ;

      if( ASWIN_GET_FLAGS(asw, AS_Sticky) ||
        (ASWIN_GET_FLAGS(asw, AS_Iconic) && get_flags( Scr.Feel.flags, StickyIcons)) )
    {  /* Window is sticky */
            if( ASWIN_DESK(asw) != new_desk && IsValidDesk(new_desk))
        {
            ASWIN_DESK(asw) = new_desk ;
            if( !ASWIN_GET_FLAGS(asw, AS_Dead) )
                set_client_desktop( asw->w, new_desk );
            broadcast_config (M_CONFIGURE_WINDOW, asw);
        }else if( ASWIN_GET_FLAGS(asw,AS_Iconic) && get_flags(Scr.Feel.flags, StickyIcons))
        {   /* we must update let all the modules know that icon viewport has changed
             * we dont have to do that for Sticky non-iconified windows, since its assumed
             * that those follow viewport, while Icons only do that when StckiIcons is set. */
            broadcast_config (M_CONFIGURE_WINDOW, asw);
        }
    }else
    {
            if( old_desk.id != new_desk )
            {     
                  Window dest = (ASWIN_DESK(asw)==new_desk)?Scr.Root:Scr.ServiceWin;
            quietly_reparent_aswindow( asw, dest, True );
            }
            if( dvx != 0 || dvy != 0 )
                  on_window_status_changed( asw, True, True );
    }
      display_progress( False, ".");
    return True;
}

Bool
count_desk_client_iter_func(void *data, void *aux_data)
{
    int *pcount = (int*)aux_data ;
    ASWindow *asw = (ASWindow *)data ;

    if( !ASWIN_GET_FLAGS(asw, AS_Sticky) &&
        (!ASWIN_GET_FLAGS(asw, AS_Iconic) || !get_flags( Scr.Feel.flags, StickyIcons)) )
    {
        if(ASWIN_DESK(asw)==Scr.CurrentDesk)
            ++(*pcount);
    }
    return True;
}

void
ChangeDeskAndViewport ( int new_desk, int new_vx, int new_vy, Bool force_grab)
{
      int dvx, dvy;
    int old_desk = Scr.CurrentDesk ;
      Bool desk_covered = False ;

LOCAL_DEBUG_CALLER_OUT( "new(%d%+d%+d), old(%d%+d%+d), max(%+d,%+d)", new_desk, new_vx, new_vy, Scr.CurrentDesk, Scr.Vx, Scr.Vy, Scr.VxMax, Scr.VyMax );

    if (new_vx > Scr.VxMax)
            new_vx = Scr.VxMax;
      else if (new_vx < 0)
            new_vx = 0;
      if (new_vy > Scr.VyMax)
            new_vy = Scr.VyMax;
      else if (new_vy < 0)
            new_vy = 0;

      dvx = Scr.Vx - new_vx;
      dvy = Scr.Vy - new_vy;

    if( IsValidDesk( old_desk ) )
            Scr.LastValidDesk = old_desk ;

    /* we have to handle all the pending ConfigureNotifys here : */
    ConfigureNotifyLoop();

    if( old_desk != new_desk && IsValidDesk( old_desk ) )
    {
        int client_count = 0 ;
          if( get_flags( AfterStepState, ASS_NormalOperation) && get_flags( Scr.Feel.flags, AnimateDeskChange))
            {     
                  cover_desktop();
                  desk_covered = True ;
            }

        iterate_asbidirlist( Scr.Windows->clients, count_desk_client_iter_func, (void*)&client_count, NULL, False );
        if( client_count != 0 )
            old_desk = INVALID_DESK ;
            force_grab = True ;
      }

      if( Scr.CurrentDesk != new_desk )
      {
            Scr.CurrentDesk = new_desk;

            if( as_desk2ext_desk (Scr.wmprops, new_desk) == INVALID_DESKTOP_PROP )
                  set_desktop_num_prop( Scr.wmprops, new_desk, Scr.Root, True );
      set_current_desk_prop ( Scr.wmprops, new_desk);
      }

      Scr.Vx = new_vx;
      Scr.Vy = new_vy;

    if( Scr.CurrentDesk != new_desk || dvx != 0 || dvy != 0 )        
            set_current_viewport_prop (Scr.wmprops, Scr.Vx, Scr.Vy, get_flags( AfterStepState, ASS_NormalOperation));
      
      display_progress( True, "Notifying modules of desk/viewport change ...");

      SendPacket( -1, M_NEW_DESKVIEWPORT, 3, Scr.Vx, Scr.Vy, Scr.CurrentDesk);

      if (dvx != 0 || dvy != 0 || old_desk != new_desk )
      {
            union
            {
                  void *ptr ;
                  int id ;
            }desk_id;

            display_progress( True, "Moving off-desktop windows back to desktop #%d ...", new_desk);
            if ( force_grab )
                  grab_server();
            if( Scr.moveresize_in_progress && !Scr.moveresize_in_progress->move_only )
            {
                  ASWindow *asw = window2ASWindow( AS_WIDGET_WINDOW(Scr.moveresize_in_progress->mr));
                  if( !get_flags (asw->status->flags, AS_Sticky) )
                  {
                        Scr.moveresize_in_progress->last_x += dvx ;
                        Scr.moveresize_in_progress->last_y += dvy ;
                        Scr.moveresize_in_progress->curr.x += dvx ;
                        Scr.moveresize_in_progress->curr.y += dvy ;
      //                Scr.moveresize_in_progress->start.x += dvx ;
      //                Scr.moveresize_in_progress->start.y += dvy ;
                        
//                      if( Scr.moveresize_in_progress->pointer_func == resize_func ) 
                        {     
   //                         Scr.moveresize_in_progress->curr.width += dvx ;
   //                         Scr.moveresize_in_progress->curr.height += dvy ;
  //                          Scr.moveresize_in_progress->start.width  -= dvx ;
  //                          Scr.moveresize_in_progress->start.height -= dvy ;
                        }
                  }
            }
            desk_id.id = old_desk ;
        /* traverse window list and redo the titlebar/buttons if necessary */
        iterate_asbidirlist( Scr.Windows->clients, deskviewport_aswindow_iter_func, desk_id.ptr, NULL, False );
        /* TODO: autoplace sticky icons so they don't wind up over a stationary icon */
          check_screen_panframes(ASDefaultScr);
            if ( force_grab)
                  ungrab_server();
    }
      /* yield to let modules handle desktop/viewport change */
      FlushAllQueues();

      if( old_desk != new_desk )
      {
      if (get_flags(Scr.Feel.flags, ClickToFocus))
            {
            int i ;
            int circ_count = VECTOR_USED(*(Scr.Windows->circulate_list));
            if( !get_flags( Scr.Feel.flags, DontRestoreFocus ) )
            {
                  ASWindow **circ_list = VECTOR_HEAD(ASWindow*,*(Scr.Windows->circulate_list));
                  for( i =0 ; i < circ_count ; ++i )
                  if( circ_list[i] != NULL && circ_list[i]->magic == MAGIC_ASWINDOW )
                        if( ASWIN_DESK(circ_list[i]) == new_desk )
                        {
                              focus_aswindow( circ_list[i] );
                              break;
                        }
            }else
                  i = circ_count ;

            if( i >= circ_count )
                  hide_focus();
      }

      if( IsValidDesk(new_desk) )
            {
            restack_window_list( new_desk, False );
                  FlushAllQueues();              /* yield to modules */
            }
      /* Change the look to this desktop's one if it really changed */
#ifdef DIFFERENTLOOKNFEELFOREACHDESKTOP
            if( get_flags( AfterStepState, ASS_NormalOperation) )
                  QuickRestart ("look&feel");
#endif

      /* we need to set the desktop background : */
            if( !get_flags( AfterStepState, ASS_SuppressDeskBack ) )
            {     
                  if( (IsValidDesk( new_desk ) && IsValidDesk( old_desk )) ||
                        Scr.LastValidDesk != new_desk )
                  {
                  
                        display_progress( True, "Changing desktop background ...");
                  change_desktop_background(new_desk);
                  }
            }
      }
    
      if( desk_covered )
            remove_desktop_cover();
}


void
ChangeDesks (int new_desk)
{
      ChangeDeskAndViewport ( new_desk, Scr.Vx, Scr.Vy, False);

}

/*************************************************************************
 *  Root Background handling :
 * - Each root background is described by MyBackground object.
 * - MyBackground could produce ASImage or it could run an external command
 * - If ASImage is produced - it will be stored either under its filename,
 *   if there were no transformation performed, or under MyBackground's name
 * - When there are no windows on the desk and it gets switched and its
 *   background size is over the threshold - it will be destroyed/released
 *   from hash.
 * - if destroyed ASImage is same as Scr.RootImage - Scr.RootImage will be
 *   set to NULL.
 * - ASImage also produces pixmap that goes into Root window background
 * - pixmap gets published using _X_ROOTPMAP property
 * - when PropertyNotify event comes and property is set to current pixmap -
 *   its ASImage will be assigned to Scr.RootImage
 * - If pixmap is unknown - then Scr.RootImage will be set to NULL and it
 *   will be generated as required by mystyle functions.
 * - If Scr.RootImage has no name - it will be destroyed when PropertyNotify
 *   event arrives
 **************************************************************************/

MyBackground *get_desk_back_or_default( int desk, Bool old_desk )
{
      MyBackground *myback = mylook_get_desk_back( &(Scr.Look), desk );
      if( myback == NULL && !old_desk && !get_flags( Scr.Look.flags, DontDrawBackground ))
      {
            const char *const_configfile = get_session_file (Session, desk, F_CHANGE_BACKGROUND, True);
            if( const_configfile != NULL )
            {  /* there is a preconfigured background file - so creating MyBack,
                  * even thou look does not have one. */
                  MyDesktopConfig *dc ;
                  char * buf = safemalloc( strlen(DEFAULT_BACK_NAME)+15+1 );

                  sprintf( buf, DEFAULT_BACK_NAME, desk );
                  dc = mylook_get_desk_config( &(Scr.Look), desk );
                  if( dc == NULL )
                  {
                  dc = create_mydeskconfig( desk, buf );
                        free( buf );
                        dc = add_deskconfig( &(Scr.Look), dc );
                  }
                  if( dc != NULL )
                  {
                        myback = mylook_get_back( &(Scr.Look), dc->back_name);
                  if( myback == NULL  )
                  {
                        myback = create_myback( dc->back_name );
                        myback->type = MB_BackImage ;
                        add_myback( &(Scr.Look), myback );
                        }
                  }
            }
      }
      return myback;
}


ASImage *
load_myback_image( int desk, MyBackground *back )
{
    ASImage *im = NULL ;
    if( back->data && back->data[0] )
      {
            LOCAL_DEBUG_OUT( "Attempting to load background image from \"%s\"", back->data?back->data:"NULL" );
        im = get_asimage( Scr.image_manager, back->data, 0xFFFFFFFF, 100 );
      }

    if( im == NULL )
    {
        const char *const_configfile = get_session_file (Session, desk, F_CHANGE_BACKGROUND, False);
        if( const_configfile != NULL )
        {
            im = get_asimage( Scr.image_manager, const_configfile, 0xFFFFFFFF, 100 );
            show_progress("BACKGROUND for desktop %d loaded from \"%s\" ...", desk, const_configfile);
        }else
            show_progress("BACKGROUND file cannot be found for desktop %d", desk );
    }
    if( im != NULL )
    {
        ASImage *scaled_im = NULL ;
        ASImage *tiled_im = NULL ;
        /* crop and or tint */
        if( back->cut.flags != 0 || (back->tint != TINT_NONE && back->tint != TINT_LEAVE_SAME))
        {

        }
        /* scale */
            LOCAL_DEBUG_OUT( "scale.flags = 0x%X", back->scale.flags );
            LOCAL_DEBUG_OUT( "scale.width = %d", back->scale.width );
            LOCAL_DEBUG_OUT( "scale.height = %d", back->scale.height );
            if( get_flags(back->scale.flags, (WidthValue|HeightValue)) )
        {
            int width = im->width ;
            int height = im->height ;
            if( get_flags(back->scale.flags, WidthValue) )
                width = back->scale.width;
            if( get_flags(back->scale.flags, HeightValue) )
                height = back->scale.height;
            if( width != im->width || height != im->height )
            {
                scaled_im = scale_asimage( Scr.asv, im, width, height, ASA_ASImage, 100, ASIMAGE_QUALITY_DEFAULT );
                LOCAL_DEBUG_OUT( "image scaled to %dx%d. tmp_im = %p", width, height, scaled_im );
                if( scaled_im != im )
                {
                    safe_asimage_destroy( im );
                    im = scaled_im ;
                }
            }
        }
        /* pad */
        if( back->align_flags != NO_ALIGN && (im->width != Scr.MyDisplayWidth || im->height != Scr.MyDisplayHeight))
        {
            int x = 0, y = 0;
            x = Scr.MyDisplayWidth - im->width ;
            if( get_flags( back->align_flags, ALIGN_LEFT ) )
                x = 0 ;
            else if( get_flags( back->align_flags, ALIGN_HCENTER ) )
                x /= 2;

            y = Scr.MyDisplayHeight - im->height;
            if( get_flags( back->align_flags, ALIGN_TOP ) )
                y = 0 ;
            else if( get_flags( back->align_flags, ALIGN_VCENTER ) )
                y /= 2;

            tiled_im = pad_asimage( Scr.asv, im, x, y, Scr.MyDisplayWidth, Scr.MyDisplayHeight, back->pad_color,
                                           ASA_ASImage, 100, ASIMAGE_QUALITY_DEFAULT );
            if( tiled_im != im )
            {
                safe_asimage_destroy( im );
                im = tiled_im ;
            }
        }
        if( im->width > Scr.MyDisplayWidth || im->height > Scr.MyDisplayHeight )
        {
            int width = ( im->width > Scr.MyDisplayWidth )?Scr.MyDisplayWidth:im->width ;
            int height = ( im->height > Scr.MyDisplayHeight )?Scr.MyDisplayHeight:im->height ;

            tiled_im = tile_asimage( Scr.asv, im, 0, 0, width, height, TINT_LEAVE_SAME, ASA_ASImage, 100, ASIMAGE_QUALITY_DEFAULT );
            LOCAL_DEBUG_OUT( "image croped to %dx%d. tmp_im = %p", width, height, tiled_im );
            if( tiled_im != im )
            {
                safe_asimage_destroy( im );
                im = tiled_im ;
            }
        }
    }
#ifdef LOCAL_DEBUG
    LOCAL_DEBUG_OUT( "syncing %s","");
    ASSync(False);
      print_asimage_manager(Scr.image_manager);
#endif

    return im;
}

void
release_old_background( int desk, Bool forget )
{
    MyBackground *back = get_desk_back_or_default( desk, True );
    ASImage *im = NULL ;
    char *imname ;

      LOCAL_DEBUG_CALLER_OUT("%d,%d", desk, forget);
    if( back == NULL || back->type == MB_BackCmd )
        return ;
      
      imname = make_myback_image_name( &(Scr.Look), back->name );

    if( back->loaded_im_name )
    {
        im = query_asimage( Scr.image_manager, back->data );
        LOCAL_DEBUG_OUT( "query_asimage \"%s\" - returned %p", back->data?back->data:"NULL", im );
    }
      
      if( im == NULL ) 
      {
            im = query_asimage( Scr.image_manager, imname );
          LOCAL_DEBUG_OUT( "query_asimage \"%s\" - returned %p", imname?imname:"NULL", im );
      }

    if( im == NULL && back->type == MB_BackImage )
    {
        if( im == NULL )
        {
            const char *const_configfile = get_session_file (Session, desk, F_CHANGE_BACKGROUND, False);
            if( const_configfile != NULL )
            {
                im = query_asimage( Scr.image_manager, const_configfile );
                LOCAL_DEBUG_OUT( "query_asimage \"%s\" - returned %p", const_configfile, im );
            }
        }
    }
#ifdef LOCAL_DEBUG
    LOCAL_DEBUG_OUT( "syncing %s","");
    ASSync(False);
#endif
    if( im != NULL )
    {
        if( Scr.RootImage == im )
        {                                      /* always do that ! */
            safe_asimage_destroy( im );
            Scr.RootImage = NULL ;
                  im = NULL ;
        }else if( forget || im->width*im->height >= Scr.Look.KillBackgroundThreshold )
        {
            LOCAL_DEBUG_OUT( "im = %p, ref_count = %d", im, im->ref_count );
            safe_asimage_destroy( im );
                  im = NULL ;
        }else if( strcmp( im->name, imname) != 0 )     /* we need to store it for future use ! */
            {                                                /* for future references we store image under imname */
                  if( im->ref_count > 1 )
                  {              /* then something else is using this image, and we need to duplicate it  */               
                        release_asimage( im );
                        im = clone_asimage( im, 0xFFFFFFFF );
                  }else
                        forget_asimage( im );
                  store_asimage( Scr.image_manager, im, imname );
            }      
            if( back->loaded_im_name )
            {
                  free( back->loaded_im_name );
                  back->loaded_im_name = NULL ; 
            }

            if( im )
            {     
                  back->loaded_im_name = mystrdup(im->name); 
                  LOCAL_DEBUG_OUT( "loaded_im_name = \"%s\"", back->loaded_im_name );
            }
    }
      free( imname );

#ifdef LOCAL_DEBUG
    LOCAL_DEBUG_OUT( "syncing, loaded_pixmap = %lX", back->loaded_pixmap );
    ASSync(False);
#endif
      if( back->loaded_pixmap && (forget || Scr.Feel.conserve_memory > 0) ) 
      {
            LOCAL_DEBUG_OUT( "ROOT_PIXMAP = %lX at %d", Scr.RootBackground->pmap, __LINE__ );
            if( Scr.RootBackground->pmap == back->loaded_pixmap ) 
                  Scr.RootBackground->pmap = None ;
            LOCAL_DEBUG_OUT( "destroying pixmap %lX", back->loaded_pixmap );
            destroy_visual_pixmap( Scr.asv, &(back->loaded_pixmap));                
      }      
}

ASImage*
make_desktop_image( int desk, MyBackground *new_back )
{
    ASImage *new_im = NULL;
    char *new_imname = NULL ; 

    if( new_back->loaded_im_name )
            new_im = fetch_asimage( Scr.image_manager, new_back->loaded_im_name );
      
      if( new_im == NULL ) 
      {     
            new_imname = make_myback_image_name( &(Scr.Look), new_back->name );
      if( new_back->type == MB_BackImage )
            {     
                  if( (new_im = fetch_asimage( Scr.image_manager, new_imname )) == NULL )
                  {     
                        LOCAL_DEBUG_OUT( "fetch_asimage could not find the back \"%s\" - loading ", new_imname );
                  }
            }
            if( new_im == NULL && new_back->loaded_pixmap != None )
            {
                  unsigned int width, height ;
                  get_drawable_size( new_back->loaded_pixmap, &width, &height );
                  new_im = pixmap2asimage(Scr.asv, new_back->loaded_pixmap, 0, 0, width, height, 0xFFFFFFFF, False, 100);
                  store_asimage( Scr.image_manager, new_im, new_imname );
            }
      }                 
      if( new_im != NULL ) 
            return new_im ;
      
      if( new_back->type == MB_BackImage )
    {
        if( (new_im = load_myback_image( desk, new_back )) != NULL )
            {
                if( new_im->name == NULL )
                      store_asimage( Scr.image_manager, new_im, new_imname );
            }
    }else if( new_back->type == MB_BackMyStyle )
    {
        MyStyle *style = mystyle_find_or_default( new_back->data );
        int root_width = Scr.MyDisplayWidth;
        int root_height = Scr.MyDisplayHeight ;
        ASImage *old_root = Scr.RootImage;

        if( style->texture_type == TEXTURE_SOLID || 
                  style->texture_type == TEXTURE_TRANSPARENT ||
            style->texture_type == TEXTURE_TRANSPARENT_TWOWAY )
            root_width = root_height = 1 ;
        else if( style->texture_type == TEXTURE_PIXMAP || style->texture_type == TEXTURE_SHAPED_PIXMAP ||
                 (style->texture_type >= TEXTURE_TRANSPIXMAP && style->texture_type < TEXTURE_SCALED_TRANSPIXMAP ))
        {
            if( root_width > style->back_icon.width )
                root_width = style->back_icon.width ;
            if( root_height > style->back_icon.height )
                root_height = style->back_icon.height ;
        }
        if( style->texture_type >= TEXTURE_TRANSPARENT )
        {
            Scr.RootImage = create_asimage( root_width, 1, 100 );
            Scr.RootImage->back_color = style->colors.back ;
        }
        LOCAL_DEBUG_OUT( "drawing root background using mystyle \"%s\" size %dx%d", style->name, root_width, root_height );
        new_im = mystyle_make_image( style, 0, 0, root_width, root_height, 0 );

        if( style->texture_type >= TEXTURE_TRANSPARENT )
        {
            destroy_asimage( &(Scr.RootImage) );
            Scr.RootImage = old_root;
        }
            if( new_im )
              store_asimage( Scr.image_manager, new_im, new_imname );
    }

      if( new_im != NULL ) 
      {
            set_string_value( &(new_back->loaded_im_name), mystrdup(new_im->name), NULL, 0 );
            LOCAL_DEBUG_OUT( "produced image %p", new_im );
      }
      
#ifdef LOCAL_DEBUG
    LOCAL_DEBUG_OUT( "syncing %s","");
    ASSync(False);
    if( new_im )
        LOCAL_DEBUG_OUT( "im(%p)->ref_count(%d)->name(\"%s\")", new_im, new_im->ref_count, new_im->name?new_im->name:"NULL" );
#endif
    if( new_imname )
        free( new_imname );
    
    return new_im;
}

typedef struct ASBackgroundXferData
{
      char        *im_name ;
      ASImage     *im_ptr ;
      Pixmap       target_pmap ;
      int          lines_per_iteration, lines_done, total_lines ;
      XImage            *shm_ximage ;
      int step ;
      unsigned long shmseg ;

      struct ASBackgroundXferData *next, *prev ;
}ASBackgroundXferData;

static ASBackgroundXferData* back_xfer_list = NULL ;

Bool
is_background_xfer_ximage( unsigned long id ) 
{
      ASBackgroundXferData *curr = back_xfer_list ;
      while( curr ) 
      {
            if( curr->shmseg == id ) 
                  return True;
            curr = curr->next ;     
      }      
      return False;
}       

ASBackgroundXferData *
pmap2background_xfer( Pixmap pmap )
{     
      ASBackgroundXferData *curr = back_xfer_list ;
      while( curr ) 
      {
            if( curr->target_pmap == pmap ) 
                  return curr;
            curr = curr->next ;     
      }      
      return NULL ;
}

void do_background_xfer_iter( void *vdata );

static void
stop_background_xfer( ASBackgroundXferData *data )
{
      ASBackgroundXferData *curr = back_xfer_list ;
      
      /* finding us in the list, to avoid stale pointers : */
      while( curr ) 
      {
            if( curr == data ) 
                  break;
            curr = curr->next ;     
      }      
      if( curr == NULL ) 
            return ;
      
      /* removing us from the list : */
      if( curr->prev ) 
            curr->prev->next = curr->next ;
      else
            back_xfer_list = curr->next ;
      if( curr->next ) 
            curr->next->prev = curr->prev ;

      /* freeing members : */
      timer_remove_by_data( data );  /* just in case */ 

      release_asimage_by_name( Scr.image_manager, data->im_name ); 
      if( data->shm_ximage ) 
            XDestroyImage( data->shm_ximage );

      data->shmseg = 0 ;
      free( data->im_name );
      free( data );
}

void 
stop_all_background_xfer()
{     
      while( back_xfer_list ) 
            stop_background_xfer( back_xfer_list );
}
      

static ASBackgroundXferData *
start_background_xfer( ASImage *new_im )
{
      ASBackgroundXferData *data = safecalloc( 1, sizeof(ASBackgroundXferData));

      /* inserting us into the list : */
      data->next = back_xfer_list ; 
      if( back_xfer_list ) 
            back_xfer_list->prev = data ;
      back_xfer_list = data ;
      
      /* initializing members : */     
      data->im_name = mystrdup(new_im->name); 
      
      fetch_asimage( Scr.image_manager, data->im_name );  /* have to increment ref count */ 

      data->im_ptr = new_im ; 
      data->target_pmap = Scr.RootBackground->pmap ; 
      if( new_im->width < Scr.MyDisplayWidth || new_im->height < Scr.MyDisplayHeight )
            data->lines_per_iteration = ASSHM_SAVED_MAX / (new_im->width * 4) ;
      else
      {     
#ifdef __CYGWIN__       
            /* under Windows XImage must not exceed 32K , or performance drops sagnificantly */
            data->lines_per_iteration = 7800/new_im->width ;
#else       
            data->lines_per_iteration = Scr.MyDisplayHeight/90;
#endif
      }
      if( data->lines_per_iteration == 0 ) 
            data->lines_per_iteration = 1 ;
      data->lines_done = 0 ;
      data->total_lines = new_im->height ;
      data->shm_ximage = NULL ; 
#ifdef XSHMIMAGE        
      if(check_shmem_images_enabled())
      {     
            data->shm_ximage = create_visual_ximage( Scr.asv, new_im->width, data->lines_per_iteration, 0 );
            data->shmseg = ximage2shmseg(data->shm_ximage) ;
      }
#endif         

      do_background_xfer_iter( data );
      return data;
}



void
do_background_xfer_iter( void *vdata )
{
      ASBackgroundXferData *data = (ASBackgroundXferData *)vdata ;
      ASImage *im ;
      Bool success = False ; 
LOCAL_DEBUG_CALLER_OUT( "%p:\"%s\", pmap %lX ", vdata, data->im_name, data->target_pmap );      
      if( data == NULL )
            return ; 
      LOCAL_DEBUG_OUT( "target_pmap = %lX", data->target_pmap );
      if( (im = query_asimage( Scr.image_manager, data->im_name )) != NULL )
      {
            LOCAL_DEBUG_OUT( "found image %p, named as it should. Original was %p", im, data->im_ptr );
            if( im == data->im_ptr ) 
            {
                  XImage *xim = data->shm_ximage ;
                  int lines = data->lines_per_iteration ;
                  int y = data->lines_done/2;

                  if( lines > data->total_lines - data->lines_done )
                        lines = data->total_lines - data->lines_done ;
                  if( data->step & 0x000001 )
                        y = (data->total_lines - (data->lines_done-data->lines_per_iteration)/2) - lines ;
                                                                           
                  if( xim == NULL ) 
                        xim = create_visual_scratch_ximage( Scr.asv, im->width, lines, 0 );
                  LOCAL_DEBUG_OUT( "making ximage %p, starting at %d, and including %d lines", xim, data->lines_done, lines );
                  if( subimage2ximage (Scr.asv, im, 0, y, xim)    )
                  {     
                        LOCAL_DEBUG_OUT( "done, copying to pixmap at %d, (bytes_per_line = %d)", data->lines_done, xim->bytes_per_line );
                        success = put_ximage( Scr.asv, xim, data->target_pmap, 
                                                      Scr.DrawGC,  0, 0, 0, y, im->width, lines );    
                        LOCAL_DEBUG_OUT( "%s", success?"Success":"Failure" );
                        data->lines_done += lines ;
                        ++(data->step);

                        if( im->width >= Scr.MyDisplayWidth && im->height >= Scr.MyDisplayHeight )
                              XClearWindow( dpy, Scr.Root );/* only if not tiled ! */
                        ASSync(False);
                  }else
                        success = True ;
                  if( xim != data->shm_ximage )
                        XDestroyImage( xim );                        
                              
            }      
      }else
      {
            LOCAL_DEBUG_OUT( "not found image \"%s\"", data->im_name );
      }      
      
      if( success && data->lines_done >= data->total_lines )
      {
            if( data->target_pmap == Scr.RootBackground->pmap )
            {     
            XSetWindowBackgroundPixmap( dpy, Scr.Root, Scr.RootBackground->pmap );
            XClearWindow( dpy, Scr.Root );
            set_xrootpmap_id (Scr.wmprops, Scr.RootBackground->pmap );
                  set_as_background(Scr.wmprops, Scr.RootBackground->pmap );
                  ASSync(False);
            }
      }      

      if( !success || data->lines_done >= data->total_lines )
      {
            LOCAL_DEBUG_OUT( "Discontinuing - done = %d, total = %d", data->lines_done, data->total_lines );
            stop_background_xfer( data );
      }else
      {
            timer_new (10, do_background_xfer_iter, vdata); 
      }            
}      



void
change_desktop_background( int desk )
{
    MyBackground *new_back = get_desk_back_or_default( desk, False );
      static int old_desk = 0 ;
    MyBackground *old_back = get_desk_back_or_default( old_desk, True );
    ASImage *new_im = NULL ;

LOCAL_DEBUG_CALLER_OUT( "desk(%d)->old_desk(%d)->new_back(%p)->old_back(%p)", desk, old_desk, new_back, old_back );
    if( new_back == NULL )
        return ;

    if( new_back->loaded_im_name != NULL  && Scr.RootBackground )
      {
            if( Scr.RootBackground->im != NULL && Scr.RootBackground->im->name != NULL )
                  if( strcmp( new_back->loaded_im_name, Scr.RootBackground->im->name ) == 0 ) 
                        return ; /* same background as what we already have - do nothing */
      }
      
    if( new_back == old_back &&
        desk != old_desk ) /* if desks are the same then we are reloading current background !!! */
        return;
    
    if( Scr.RootBackground != NULL )
      {     
            LOCAL_DEBUG_OUT( "ROOT_PIXMAP = %lX at %d", Scr.RootBackground->pmap, __LINE__ );
      }

#ifdef LOCAL_DEBUG
    LOCAL_DEBUG_OUT( "syncing %s","");
    ASSync(False);
#endif
      if( old_back ) 
      {LOCAL_DEBUG_OUT( "old_back>>> desk = %d, ptr = %p, loaded_im_name = \"%s\", pixmap = %lX", old_desk, old_back, old_back->loaded_im_name?old_back->loaded_im_name:"NULL", old_back->loaded_pixmap );}
      if( new_back ) 
      {LOCAL_DEBUG_OUT( "new_back>>> desk = %d, ptr = %p, loaded_im_name = \"%s\", pixmap = %lX", desk, new_back, new_back->loaded_im_name?new_back->loaded_im_name:"NULL", new_back->loaded_pixmap );}
    if( Scr.RootBackground == NULL )
        Scr.RootBackground = safecalloc( 1, sizeof(ASBackgroundHandler));
    else
    {                                          /* do cleanup - kill command maybe */
        if( Scr.RootBackground->cmd_pid )
            check_singleton_child (BACKGROUND_SINGLETON_ID, True);
        Scr.RootBackground->cmd_pid = 0;
        Scr.RootBackground->im = NULL ;
    }
      display_progress( True, "Releasing old background ..."); 
    release_old_background( old_desk, (desk==old_desk) );
      if( new_back->loaded_pixmap ) 
      {
            ASBackgroundHandler *bh = Scr.RootBackground ;              
            unsigned int width, height ;       
            if( !get_drawable_size(new_back->loaded_pixmap, &width, &height ) )
                  new_back->loaded_pixmap = None ;
            else
            {
            ASBackgroundXferData *pending_back_xfer = pmap2background_xfer( new_back->loaded_pixmap );
                  /* cancel last background xfer is there was any  */
                  if( pending_back_xfer != NULL )
                  {     /* have to increment ref count, to compensate for release_background() */ 
                        bh->im = fetch_asimage( Scr.image_manager, pending_back_xfer->im_name );
                  }else
                        bh->im = NULL;

                  bh->pmap_width = width ;
            bh->pmap_height = height ;
            
                  bh->pmap = new_back->loaded_pixmap ;
                  display_progress( True, "Setting background to previously generated pixmap ..."); 
                  XSetWindowBackgroundPixmap( dpy, Scr.Root, new_back->loaded_pixmap );
                  XClearWindow( dpy, Scr.Root );
                  set_xrootpmap_id (Scr.wmprops, new_back->loaded_pixmap );
                  set_as_background(Scr.wmprops, new_back->loaded_pixmap );
                  display_progress( True, "Done with background change. It may take a moment for X server to display it."); 
                  ASSync(False);
                  old_desk = desk ;
                  return ;   
            }
      }             

      display_progress( True, "Changing background for desktop #%d ...", desk);
      

    if( new_back->type == MB_BackCmd )
    {                                          /* run command */
        Scr.RootBackground->cmd_pid = spawn_child( XIMAGELOADER, BACKGROUND_SINGLETON_ID, Scr.screen, None, C_NO_CONTEXT, True, False, new_back->data, NULL );
    }else
        new_im = make_desktop_image( desk, new_back );

      display_progress( True, "Background image generated."); 
    LOCAL_DEBUG_OUT( "im(%p)", new_im );
    if( new_im )
    {
        ASBackgroundHandler *bh = Scr.RootBackground ;
            Pixmap old_pmap ;
            Bool already_transferring = False ;
        /* Scr.RootImage = new_im ; */         /* will be done in event handler !!! */
        if( new_im->name == NULL )
        {
            char *new_imname = make_myback_image_name( &(Scr.Look), new_back->name );
            store_asimage( Scr.image_manager, new_im, new_imname );
        }
            LOCAL_DEBUG_OUT( "ROOT_PIXMAP = %lX at %d", Scr.RootBackground->pmap, __LINE__ );
            if( old_back && bh->pmap == old_back->loaded_pixmap)
            {
                  if( Scr.Feel.conserve_memory == 0 )
                        bh->pmap = None ;                   
                  else
                        old_back->loaded_pixmap = None ;
            }
            LOCAL_DEBUG_OUT( "ROOT_PIXMAP = %lX at %d", Scr.RootBackground->pmap, __LINE__ );
            old_pmap = bh->pmap ;
        if( bh->pmap && (new_im->width != bh->pmap_width ||
            new_im->height != bh->pmap_height) )
        {
                  if( Scr.wmprops->root_pixmap == bh->pmap )
                  {     
                        set_xrootpmap_id (Scr.wmprops, None );
                        set_as_background(Scr.wmprops, None );
                  }
            XFreePixmap( dpy, bh->pmap );
            ASSync(False);
            LOCAL_DEBUG_OUT( "root pixmap with id %lX destroyed", bh->pmap );
            bh->pmap = None ;
        }
        LOCAL_DEBUG_OUT( "ROOT_PIXMAP = %lX at %d", Scr.RootBackground->pmap, __LINE__ );
            if( !validate_drawable( bh->pmap, NULL, NULL ) )
                  bh->pmap = None ;
            if( bh->pmap == None )
            {
            bh->pmap = create_visual_pixmap( Scr.asv, Scr.Root, new_im->width, new_im->height, 0 );
            LOCAL_DEBUG_OUT( "new root pixmap created with id %lX and size %dx%d", bh->pmap, new_im->width, new_im->height );
            }else
            {     
            ASBackgroundXferData *last_back_xfer = pmap2background_xfer( bh->pmap );
                  LOCAL_DEBUG_OUT( "using root pixmap created with id %lX", bh->pmap );
                  /* cancel last background xfer is there was any  */
                  if( last_back_xfer != NULL )
                  {     
                        if( last_back_xfer->im_ptr != new_im )
                        {     
                              LOCAL_DEBUG_OUT( "Discontinuing - done = %d, total = %d", last_back_xfer->lines_done, last_back_xfer->total_lines );                         
                              stop_background_xfer( last_back_xfer );
                        }else
                        {
                              fetch_asimage( Scr.image_manager, last_back_xfer->im_name );  
                              /* have to increment ref count, to compensate for release_background() */ 
                              LOCAL_DEBUG_OUT( "Not Dsicontinuing - already transferring %s", "" );                        
                              already_transferring = True ;
                        }
                  }
            }

        bh->pmap_width = new_im->width ;
        bh->pmap_height = new_im->height ;
        bh->im = new_im;

            new_back->loaded_pixmap = bh->pmap ;
            /*print_asimage( new_im, 0xFFFFFFFF, __FUNCTION__, __LINE__ );*/
        ASSync(False);
        LOCAL_DEBUG_OUT( "width(%d)->height(%d)->pixmap(%lX/%lu)", new_im->width, new_im->height, bh->pmap, bh->pmap );
            if( old_back ) 
            {LOCAL_DEBUG_OUT( "old_back>>>#2 desk = %d, ptr = %p, loaded_im_name = \"%s\", pixmap = %lX", old_desk, old_back, old_back->loaded_im_name, old_back->loaded_pixmap );}
            if( new_back ) 
            {LOCAL_DEBUG_OUT( "new_back>>>#2 desk = %d, ptr = %p, loaded_im_name = \"%s\", pixmap = %lX", desk, new_back, new_back->loaded_im_name, new_back->loaded_pixmap );}
            
            old_desk = desk ;
            
            if( new_im->width * new_im->height * 4 >= ASSHM_SAVED_MAX/2 &&
                  /* can't animate if pixmap is tiled - X is slow then */
                  !get_flags( Scr.Feel.flags, DontAnimateBackground) && 
                  /* when we do this for the first time  - we better do it all at once */
                  Scr.wmprops->root_pixmap != None )
            {     
                  Bool tiled = ( new_im->width < Scr.MyDisplayWidth || new_im->height < Scr.MyDisplayHeight );
                  if( old_pmap != bh->pmap )
                  {     
                        if( !tiled ) 
                              XSetWindowBackgroundPixmap( dpy, Scr.Root, bh->pmap );
                  }else if( tiled ) 
                  {
                        /* animation of tiled backgrounds causes X to be very slow */
                        XSetWindowBackgroundPixmap( dpy, Scr.Root, None );
                  }
                  if( !already_transferring )
                  {     
                        display_progress( True, "Animating background change for better responsiveness ...");
                        start_background_xfer( new_im );  /* we need to do it in small steps! */
                  }
            }else
            {     
                  if( !already_transferring )
                  {     
                  if( !asimage2drawable( Scr.asv, bh->pmap, new_im, Scr.DrawGC, 0, 0, 0, 0, new_im->width, new_im->height, True) )
                              show_warning( "failed to draw root background onto pixmap");
                  flush_asimage_cache(new_im);
                  }
            XSetWindowBackgroundPixmap( dpy, Scr.Root, bh->pmap );
            XClearWindow( dpy, Scr.Root );
            set_xrootpmap_id (Scr.wmprops, bh->pmap );
                  set_as_background(Scr.wmprops, bh->pmap );
            }  
            if( Scr.RootImage == NULL )
                  Scr.RootImage = dup_asimage(Scr.RootBackground->im) ;
    }else
      {     
        set_xrootpmap_id (Scr.wmprops, None );
            set_as_background(Scr.wmprops, None );
      }
    ASSync(False);
#ifdef DEBUG_ALLOCS     
    print_asimage_registry();
      spool_unfreed_mem (__FUNCTION__, "");
#endif      
    LOCAL_DEBUG_OUT("done%s","" );
    remove_desktop_cover();
}

/*************************************************************************
 * Client access to the root background for different desktops :
 *
 * Client should send the ClientMessage to the Root window
 *      window        = client's window
 *      message_type  = _AS_BACKGROUND
 *      format        = 16
 *          data.s[0]   = desktop number
 *          data.s[1]   = clip_x
 *          data.s[2]   = clip_y
 *          data.s[3]   = clip_width
 *          data.s[4]   = clip_height
 *          data.s[5]   = flags
 *          data.s[6]   = red tint
 *          data.s[7]   = green tint
 *          data.s[8]   = blue tint
 * When target Pixmap has been populated with required background
 * AfterStep will send the ClientMessage event back to client's window.
 * Contents of the message should be as follows :
 *      window        = root window
 *      message_type  = _AS_BACKGROUND
 *      format        = 32
 *          data.l[0]   = desktop number
 *          data.l[1]   = result pixmap
 *
 * In case AfterStep fails to generate required image it will still send the
 * ClientMessage with all the data set to 0
 *
 * It is the responcibility of the client to create and destroy the
 * target Pixmap.
 *************************************************************************/
void
SendBackgroundReplay( ASEvent *src, Pixmap pmap )
{
    XClientMessageEvent *xcli = &(src->x.xclient) ;
    Window w = xcli->window;
    int desk = xcli->data.s[0];

    xcli->data.l[0] = desk ;
    xcli->data.l[1] = pmap ;
    xcli->data.l[2] = 0 ;
    xcli->data.l[3] = 0 ;
    xcli->data.l[4] = 0 ;
    xcli->window = Scr.Root ;
    xcli->format = 32 ;
    XSendEvent( dpy, w, False, 0, &(src->x) );
}

void
HandleBackgroundRequest( ASEvent *event )
{
    XClientMessageEvent *xcli = &(event->x.xclient) ;
    Pixmap  p           = None ;
    int     desk        = xcli->data.s[0] ;
    int     clip_x      = xcli->data.s[1] ;
    int     clip_y      = xcli->data.s[2] ;
    int     clip_width  = xcli->data.s[3] ;
    int     clip_height = xcli->data.s[4] ;
    Bool    flags       = xcli->data.s[5] ;
    ARGB32  tint        = MAKE_ARGB32(0,xcli->data.s[6],xcli->data.s[7],xcli->data.s[8]) ;
    ASImage *im ;
    MyBackground *back = get_desk_back_or_default( desk, False );
    Bool res = False;
    Bool do_tint = True ;

    if( xcli->data.s[6] == xcli->data.s[7] == xcli->data.s[8] )
        do_tint = !(xcli->data.s[6] == 0 || xcli->data.s[6] == 0x7F );

    LOCAL_DEBUG_OUT("pmap(%lX/%lu)->clip_pos(%+d%+d)->clip_size(%dx%d)->scale(%d)->tint(%lX)->window(%lX)", p, p, clip_x, clip_y, clip_width, clip_height, flags, tint, event->x.xclient.window );

    if( clip_width > 0 && clip_height > 0 && back != NULL && back->type != MB_BackCmd )
    {
        if( (im = make_desktop_image( desk, back )) != NULL )
        {
            p = create_visual_pixmap( Scr.asv, Scr.Root, clip_width, clip_height, 0 );
            if( p )
            {
                ASImage *tmp_im ;
                int tmp_w = clip_width ;
                int tmp_h = clip_height ;
                if( get_flags(flags, 0x01) )
                {
                    if( clip_width < im->width )
                        tmp_w = im->width ;
                    if( clip_height < im->height )
                        tmp_h = im->height ;
                }
                if( get_flags(flags, 0x02) )
                {
                    if( clip_width > im->width )
                        tmp_w = im->width ;
                    if( clip_height > im->height )
                        tmp_h = im->height ;
                }

                if( clip_x != 0 || clip_y != 0 || tmp_w != im->width || tmp_h != im->height || do_tint )
                {
                    tmp_im = tile_asimage( Scr.asv, im, clip_x, clip_y, tmp_w, tmp_h, tint, (tmp_w != im->width || tmp_h != im->height)?ASA_ASImage:ASA_XImage, ASIMAGE_QUALITY_DEFAULT, 0 );
                    if( tmp_im != NULL )
                    {
                        safe_asimage_destroy( im );
                        im = tmp_im ;
                    }
                }
                if( im->width != clip_width || im->height != clip_height )
                {
                    tmp_im = scale_asimage( Scr.asv, im, clip_width, clip_height, ASA_XImage, ASIMAGE_QUALITY_DEFAULT, 0 );
                    if( tmp_im != NULL )
                    {
                        safe_asimage_destroy( im );
                        im = tmp_im ;
                    }
                }
                if( asimage2drawable( Scr.asv, p, im, Scr.DrawGC, 0, 0, 0, 0, clip_width, clip_height, True) )
                    res = True ;
                else
                {
                    XFreePixmap( dpy, p );
                    p = None ;
                }
            }
            safe_asimage_destroy( im );
        }
    }
    SendBackgroundReplay( event, p );
}


Generated by  Doxygen 1.6.0   Back to index