Skip to content
Snippets Groups Projects
mypixmap.c 7.16 KiB
Newer Older
        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, 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.
        xfwm4    - (c) 2002-2004 Olivier Fourdan
Olivier Fourdan's avatar
Olivier Fourdan committed
 */

#ifdef HAVE_CONFIG_H
Olivier Fourdan's avatar
Olivier Fourdan committed
#endif

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <glib.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <libxfce4util/libxfce4util.h> 
Olivier Fourdan's avatar
Olivier Fourdan committed
#include <stdlib.h>
#include <stdio.h>
Olivier Fourdan's avatar
Olivier Fourdan committed

xfwmPixmapCompose (xfwmPixmap * pm, gchar * dir, gchar * file)
{
    gchar *filepng;
    gchar *filename;
    GdkPixbuf *alpha;
    GdkPixbuf *src;
    GdkPixmap *destw;
    GdkColormap *cmap;
    gint width, height;

    filepng = g_strdup_printf ("%s.%s", file, "png");
    filename = g_build_filename (dir, filepng, NULL);
    g_free (filepng);
    
    if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
    {
    }
    alpha = gdk_pixbuf_new_from_file (filename, &error);
    g_free (filename);
    if (error)
    {
        g_warning ("%s", error->message);
        g_error_free (error);
        return FALSE;
    }
    if (!gdk_pixbuf_get_has_alpha (alpha))
    {
    destw = gdk_xid_table_lookup (pm->pixmap);
    if (destw)
    {
        g_object_ref (G_OBJECT (destw));
    }
    else
    {
         destw = gdk_pixmap_foreign_new (pm->pixmap);
    }
    
        DBG ("Cannot get pixmap");
        g_object_unref (alpha);
        return FALSE;

    cmap = gdk_drawable_get_colormap (destw);
    if (cmap)
    {
        g_object_ref (G_OBJECT (cmap));
    }
    else
    {
        if (gdk_drawable_get_depth (destw) == 1)
        {
            cmap = NULL;
        }
        else
        {
            cmap = gdk_screen_get_rgb_colormap (pm->screen_info->gscr);
            g_object_ref (G_OBJECT (cmap));
        }
    }

    if (cmap && (gdk_colormap_get_visual (cmap)->depth != gdk_drawable_get_depth (destw)))
    {
        g_object_unref (G_OBJECT (cmap));
        cmap = NULL;
    }

    width = MIN (gdk_pixbuf_get_width (alpha), pm->width);
    height = MIN (gdk_pixbuf_get_height (alpha), pm->height);
    
    src = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE (destw), cmap, 
    gdk_pixbuf_composite (alpha, src, 0, 0, width, height,
                          0, 0, 1.0, 1.0, GDK_INTERP_NEAREST, 255);
    gdk_draw_pixbuf (GDK_DRAWABLE (destw), NULL, src, 0, 0, 0, 0,
                     pm->width, pm->height, GDK_RGB_DITHER_NONE, 0, 0);

    if (cmap)
    {
        g_object_unref (G_OBJECT (cmap));
    }
    g_object_unref (alpha);
    g_object_unref (src);
    g_object_unref (destw);

    return TRUE;
}

xfwmPixmapLoad (ScreenInfo * screen_info, xfwmPixmap * pm, gchar * dir, gchar * file, XpmColorSymbol * cs, gint n)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    XpmAttributes attr;

    TRACE ("entering xfwmPixmapLoad");
    g_return_val_if_fail (dir != NULL, FALSE);
    g_return_val_if_fail (file != NULL, FALSE);
Olivier Fourdan's avatar
Olivier Fourdan committed

    pm->screen_info = screen_info;
Olivier Fourdan's avatar
Olivier Fourdan committed
    pm->pixmap = None;
Olivier Fourdan's avatar
Olivier Fourdan committed
    pm->height = 1;
    filexpm = g_strdup_printf ("%s.%s", file, "xpm");
    filename = g_build_filename (dir, filexpm, NULL);
    g_free (filexpm);
Olivier Fourdan's avatar
Olivier Fourdan committed
    attr.colorsymbols = cs;
    attr.colormap = pm->screen_info->cmap;
    attr.closeness = 65535;
    attr.valuemask = XpmCloseness | XpmColormap | XpmSize;
        attr.valuemask = attr.valuemask | XpmColorSymbols;
    if (XpmReadFileToPixmap (myScreenGetXDisplay (screen_info), screen_info->xroot, filename, &pm->pixmap, &pm->mask, &attr))
        TRACE ("%s not found", filename);
        g_free (filename);
        return FALSE;
Olivier Fourdan's avatar
Olivier Fourdan committed
    pm->width = attr.width;
    pm->height = attr.height;
    XpmFreeAttributes (&attr);
    g_free (filename);
Olivier Fourdan's avatar
Olivier Fourdan committed

    /* Apply the alpha channel if available */
    xfwmPixmapCompose (pm, dir, file);
Olivier Fourdan's avatar
Olivier Fourdan committed
    return TRUE;
}

xfwmPixmapCreate (ScreenInfo * screen_info, xfwmPixmap * pm, gint width, gint height)
    TRACE ("entering xfwmPixmapCreate, width=%i, height=%i", width, height);
    if ((width < 1) || (height < 1) || (!screen_info))
        xfwmPixmapInit (screen_info, pm);
        pm->screen_info = screen_info;
        pm->pixmap = XCreatePixmap (myScreenGetXDisplay (screen_info), screen_info->xroot, width, height, screen_info->depth);
        pm->mask = XCreatePixmap (myScreenGetXDisplay (screen_info), pm->pixmap, width, height, 1);
xfwmPixmapInit (ScreenInfo * screen_info, xfwmPixmap * pm)
    pm->screen_info = screen_info;
    pm->pixmap = None;
    pm->mask = None;
    pm->width = 0;
    pm->height = 0;
}

xfwmPixmapFree (xfwmPixmap * pm)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    
    TRACE ("entering xfwmPixmapFree");
    
        XFreePixmap (myScreenGetXDisplay(pm->screen_info), pm->pixmap);
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        XFreePixmap (myScreenGetXDisplay(pm->screen_info), pm->mask);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
}
static void
xfwmPixmapFillRectangle (Display *dpy, int screen, Pixmap pm, Drawable d, int x, int y, int width, int height)
{
    XGCValues gv;
    GC gc;
    unsigned long mask;
    TRACE ("entering fillRectangle");

    if ((width < 1) || (height < 1))
    {
        return;
    }
    gv.fill_style = FillTiled;
    gv.ts_x_origin = x;
    gv.ts_y_origin = y;
    gv.foreground = WhitePixel (dpy, screen);
    if (gv.tile != None)
    {
        mask = GCTile | GCFillStyle | GCTileStipXOrigin;
    }
    else
    {
        mask = GCForeground;
    }
    gc = XCreateGC (dpy, d, mask, &gv);
    XFillRectangle (dpy, d, gc, x, y, width, height);
    XFreeGC (dpy, gc);
}

void
xfwmPixmapFill (xfwmPixmap * src, xfwmPixmap * dst, gint x, gint y, gint width, gint height)
{
    XGCValues gv;
    GC gc;
    unsigned long mask;
    TRACE ("entering xfwmWindowFill");

    if ((width < 1) || (height < 1))
    {
        return;
    }
    xfwmPixmapFillRectangle (myScreenGetXDisplay (src->screen_info), 
                             src->screen_info->screen,  
                             src->pixmap, dst->pixmap, x, y, width, height);
    xfwmPixmapFillRectangle (myScreenGetXDisplay (src->screen_info), 
                             src->screen_info->screen,  
                             src->mask, dst->mask, x, y, width, height);