[pygtk] cairo + transparent png + XShape
Sebastian Bartos
seth.kriticos at googlemail.com
Sat Jan 3 23:45:10 WST 2009
Hello there,
well, just to help the people who come after me, here is the solution I
did. It's a bit dirty, sorry for that. Anyways, it loads the file
base.png in the same folder and puts it on a 800x650 window with
transparency and XShape clipping:
import sys
import gobject
import pango
import pygtk
import gtk
from gtk import gdk
import cairo
# import Images
import gobject
class pngtranswin:
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_decorated(0)
self.window.set_default_size(800, 650)
self.window.set_events(gtk.gdk.ALL_EVENTS_MASK)
# Initialize colors, alpha transparency
self.window.set_app_paintable(1)
self.gtk_screen = self.window.get_screen()
colormap = self.gtk_screen.get_rgba_colormap()
if colormap == None:
colormap = self.gtk_screen.get_rgb_colormap()
gtk.widget_set_default_colormap(colormap)
if not self.window.is_composited():
self.supports_alpha = False
else:
self.supports_alpha = True
self.w,self.h = self.window.get_size()
self.window.connect("expose_event", self.expose)
self.window.connect("destroy", gtk.main_quit)
def expose (self, widget, event):
self.ctx = self.window.window.cairo_create()
# set a clip region for the expose event, XShape stuff
self.ctx.save()
if self.supports_alpha == False:
self.ctx.set_source_rgb(1, 1, 1)
else:
self.ctx.set_source_rgba(1, 1, 1,0)
self.ctx.set_operator (cairo.OPERATOR_SOURCE)
self.ctx.paint()
self.ctx.restore()
self.ctx.rectangle(event.area.x, event.area.y,
event.area.width, event.area.height)
self.ctx.clip()
self.draw_image(self.ctx,0,0,'base.png')
def setup(self):
# Set menu background image
self.background = gtk.Image()
self.frame = gtk.Fixed()
self.window.add (self.frame)
# Set window shape from alpha mask of background image
w,h = self.window.get_size()
if w==0: w = 800
if h==0: h = 650
self.w = w
self.h = h
self.pixmap = gtk.gdk.Pixmap (None, w, h, 1)
ctx = self.pixmap.cairo_create()
# todo: modify picture source
#self.bgpb = gtk.gdk.pixbuf_new_from_file('base.png')
ctx.save()
ctx.set_source_rgba(1, 1, 1,0)
ctx.set_operator (cairo.OPERATOR_SOURCE)
ctx.paint()
ctx.restore()
self.draw_image(ctx,0,0,'base.png')
if self.window.is_composited():
ctx.rectangle(0,0,w,h)
ctx.fill()
self.window.input_shape_combine_mask(self.pixmap,0,0)
else:
self.window.shape_combine_mask(self.pixmap, 0, 0)
def draw_image(self,ctx,x,y, pix):
"""Draws a picture from specified path with a certain width and
height"""
ctx.save()
ctx.translate(x, y)
pixbuf = gtk.gdk.pixbuf_new_from_file(pix)
format = cairo.FORMAT_RGB24
if pixbuf.get_has_alpha():
format = cairo.FORMAT_ARGB32
#if Images.flip != None:
# pixbuf = pixbuf.flip(Images.flip)
iw = pixbuf.get_width()
ih = pixbuf.get_height()
image = cairo.ImageSurface(format, iw, ih)
image = ctx.set_source_pixbuf(pixbuf, 0, 0)
ctx.paint()
puxbuf = None
image = None
ctx.restore()
ctx.clip()
def show_window(self):
self.window.show_all()
while gtk.events_pending():
gtk.main_iteration()
self.window.present()
self.window.grab_focus()
self.p = 1
if __name__ == "__main__":
m = pngtranswin()
m.setup()
m.show_window()
gtk.main()
Ok, you can see that it is a bit prototype state, but works. Any
functional comments?
~ Seth
On Sat, 2009-01-03 at 11:48 +0100, Pietro Battiston wrote:
> Il giorno mer, 31/12/2008 alle 01.22 +0100, Sebastian Bartos ha scritto:
> > Hello there,
> >
> > I'm working on a little app here that uses cairo and a transparent png
> > for nifty window design (kind of like widgets/screenlets, no border,
> > transparency, etc.)
> >
> > Now I try to figure out how to tell the XShape extension to take the
> > fully transparent parts of the window and cut them away (really
> > irregular borders).
> >
> > Any ideas?
> >
> > Thanks
> > Seth Kriticos
>
>
> I once tried it, please look if this does what you want (and eventually
> do it in some less chaotic way! It was really just a proof of concept):
>
> -----------------------------------------------------------------------
>
>
> import gtk, gobject
>
>
> N,M=200,200
>
> drag_icon_xpm = [
> str(N)+" "+str(M)+" 1 1",
> " c None"]+[' '*N]*M
>
>
> w = gtk.Window()
>
>
> def apply_mask():
> p = gtk.gdk.pixmap_create_from_xpm_d(w.window , None,
> drag_icon_xpm)[1]
> r=p.cairo_create()
> r.arc(N/2, M/2, min(N,M)/2, .0001, 0)
> r.fill()
> w.shape_combine_mask(p, 0, 0)
> w.set_decorated(False)
> return
>
>
> b=gtk.Button("Click me,\n stupid")
> w.add(b)
> b.connect('released', gtk.main_quit)
> w.set_size_request(200,200)
> w.show_all()
>
> gobject.timeout_add(1, apply_mask)
>
> gtk.main()
>
--
Sebastian Bartos, <seth.kriticos at googlemail.com>
keyserevr: pgp.mit.edu
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
Url : http://www.daa.com.au/pipermail/pygtk/attachments/20090103/c09ff96c/attachment.pgp
More information about the pygtk
mailing list