Transparent GtkWindow

前回 GtkWindow の枠を消した、これで Google Chrome みたいなウインドウ…
とか書いたけどウインドウ自体を透過させなきゃ四角いウインドウしか作れない。
透明にできれば角を丸くなんかは DrawingArea でなんとかなるはず。

python – Making Gtk.Window Transparent? – Ask Ubuntu

アッサリ見つかった。
ついでに自分のストックから PyGtk 版も出てきた。

せっかくなので PyGtk との違いを見るため両方で書いてみる。

透明なだけでは面白くないので透過付き画像を表示させる処理も。
私は絵心が壊滅的なので Text という文字を Gimp で書いただけですが…
アーカイブも置いておきますので自作して試してくださると嬉しい。
visual.tar.gz

PyGtk

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import gtk, cairo

class ColormapWin(gtk.Window):
    """
        PyGtk(GTK2) Version
    """
    def __init__(self):
        """
            gtk.main_quit is Double Click
        """
        gtk.Window.__init__(self)
        self.connect("delete-event", gtk.main_quit)
        self.connect("expose-event", self.on_expose)
        # GdkColormap
        screen = self.get_screen()
        colormap = screen.get_rgba_colormap()
        if colormap != None and screen.is_composited():
            self.set_colormap(colormap)
        else:
            print "no Composited..."
        self.set_app_paintable(True)
        # Transparent background image
        self.pixbuf = gtk.gdk.pixbuf_new_from_file("test.xpm")
        # Mouse Click
        self.set_events(gtk.gdk.BUTTON_PRESS_MASK)
        self.connect("button-press-event", self.on_button_press_event)
        #
        self.set_decorated(False)
        self.resize(320, 240)
        self.show_all()

    def on_expose(self, widget, event=None):
        """
            cr is gtk.gdk.CairoContext
        """
        cr = widget.window.cairo_create()
        cr.set_source_rgba(1.0, 1.0, 1.0, 0.0)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.set_source_pixbuf(self.pixbuf, 0, 0)
        cr.paint()

    def on_button_press_event(self, widget, event=None):
        """
            Mouse Drag and Quit
        """
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time)
        elif event.type == gtk.gdk._2BUTTON_PRESS:
            gtk.main_quit()

ColormapWin()
gtk.main()

pygi

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from gi.repository import Gtk, Gdk, GdkPixbuf
import cairo

class VisualWin(Gtk.Window):
    """
        PyGI(GTK3) Version
    """
    def __init__(self):
        """
            Gtk.main_quit is Double Click
        """
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        # 'expose-event' to 'draw'
        self.connect("draw", self.on_draw)
        # GdkColormap to GdkVisual
        screen = self.get_screen()
        visual = screen.get_rgba_visual()
        if visual != None and screen.is_composited():
            self.set_visual(visual)
        else:
            print "no Composited..."
        self.set_app_paintable(True)
        # Transparent background image
        self.pixbuf = GdkPixbuf.Pixbuf.new_from_file("test.xpm")
        # Mouse Click
        self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK)
        self.connect("button-press-event", self.on_button_press_event)
        #
        self.set_decorated(False)
        self.resize(320, 240)
        self.show_all()

    def on_draw(self, widget, cr):
        """
            cr is cairo.Context
        """
        cr.set_source_rgba(1.0, 1.0, 1.0, 0.0)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        Gdk.cairo_set_source_pixbuf(cr, self.pixbuf, 0, 0)
        cr.paint()

    def on_button_press_event(self, widget, event, data=None):
        """
            Mouse Drag and Quit
        """
        if event.type == Gdk.EventType.BUTTON_PRESS:
            self.begin_move_drag(event.button, event.x_root, event.y_root, event.time)
        elif event.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
            Gtk.main_quit()

VisualWin()
Gtk.main()

Gnome Shell 3D
gnome3_3d

Unity 3D
ubuntu_unity

Fedora でも Ubuntu でも問題ない。
枠も無くウインドウは透過しているけど画像は綺麗に表示できている。

PyGtk と PyGI もあまり違いは無いようだ。
GdkColormap が GdkVisual に変わったくらいで後はもうお馴染みの違いだけ。
デスクトップアクセサリを作る程度ならこれで簡単に作れるかな。

と思ったけど。
GNOME 3 を強制フォールバックにしたら真っ黒に、2D では合成できないようだ。

gnome_2d

Lubuntu でもダメだった。

lubuntu

これじゃ「透過するアプリですヨン」って配れないじゃん。
デスクトップ Linux は仮想マシンな人がほとんどという現実だもの。

つまり Google Chrome みたいなウインドウはこの方法では作れないよ。
うーん、まだまだ勉強しなければ。