pygtkで遊ぼう(14) 四角くないWindow編

まだ完全に理解したわけではないですが、Windowをちょっと変わった形にする方法を実験してました。
今回やりたかったのは、

ウインドウの形をPNGの画像を使って、マスクする。

です。

今回使用した背景は、先日紹介したPluggerアイコン用の画像です。

今回作ったPythonスクリプトを実行すると、こんな感じになります。


いやはや、透けてますね〜。(笑


今回は初めてcairoを使いました。
cairoは強力なのかもしれませんが、理解するのに苦労しそうです。
ドキュメントも少なめだし。


ソースコードはこんな感じです。
とりあえず、XFCEの場合には、Ctrl+Shift+矢印キーまたは、Superキー+左マウスドラッグでウインドウを動かせるようにしました。

参考にしたサイト:http://faq.pygtk.org/index.py?req=show&file=faq10.024.htp

#-*- coding: utf-8 -*-

import math

import cairo
import gtk
from gtk import gdk

class ShapedWindow(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)
        
        self.set_position(gtk.WIN_POS_CENTER)
        self.set_decorated(False)
        self.connect('size-allocate', self.on_size_allocate)
        self.connect('delete-event', self.on_delete_event)

        img = gtk.Image()
        img.set_from_file('logo.png')
        self.add(img)
        self.set_resizable(False)

    def on_size_allocate(self, win, allocation):
        # オフスクリーンのPixmapを作成する。
        # マスクに使いたいだけなので、色深度は1(白黒)に。
        bitmap = gtk.gdk.Pixmap(None,
                                allocation.width,
                                allocation.height,
                                1)

        #cairoオブジェクト生成
        ca = bitmap.cairo_create()

        # まず、真っ黒に塗りつぶす
        ca.set_source_rgb(0, 0, 0)
        ca.set_operator(cairo.OPERATOR_DEST_OUT)
        ca.paint()

        # logo.pngを読み込んでImageSurfaceオブジェクトを作る。
        img = cairo.ImageSurface.create_from_png('logo.png')
        ca.set_source_surface(img)
        ca.set_operator(cairo.OPERATOR_OVER)
        ca.paint()

        # ↑で作成したマスク用ピクセルマップを使ってWindowをマスク。
        win.shape_combine_mask(bitmap,
                               allocation.x,
                               allocation.y)
        return True
    
    def on_delete_event(self, widget, event=None):
        print '-- quit --'
        gtk.main_quit()
#
#
if __name__ == '__main__':
    win = ShapedWindow()
    win.show_all()

    gtk.main()