From 981ee81f05f2c023e0af63209c34fe9356d77dae Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Mon, 12 Jan 2009 00:02:41 +0000 Subject: [PATCH] Added rendering via Cario for semi-transparent window when using compositing. Code is messy but works. --- cb-openbox-logout.py | 135 +++++++++++++++++++++++++++++++++---------- openbox-logout.conf | 3 +- 2 files changed, 105 insertions(+), 33 deletions(-) diff --git a/cb-openbox-logout.py b/cb-openbox-logout.py index 3e370a5..864dfc4 100755 --- a/cb-openbox-logout.py +++ b/cb-openbox-logout.py @@ -4,22 +4,37 @@ import gtk, os from PIL import Image, ImageFilter import ConfigParser import StringIO +import logging +import cairo class OpenboxLogout(): def __init__(self, config=None): self.load_config(config) - + self.window = gtk.Window() self.window.set_title("Log Out ..") + self.window.connect("destroy", self.quit) self.window.connect("key-press-event", self.on_keypress) + self.window.connect("window-state-event", self.on_window_state_change) + + if self.rendered_effects == False: + if not self.window.is_composited(): + logging.debug("No compositing, enabling rendered effects") + # Window isn't composited, enable rendered effects + self.rendered_effects = True + else: + # Link in Cairo rendering events + self.window.connect('expose-event', self.on_expose) + self.window.connect('screen-changed', self.on_screen_changed) + self.on_screen_changed(self.window) + self.window.set_size_request(620,200) self.window.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) - self.window.set_decorated(gtk.FALSE) + + self.window.set_decorated(False) self.window.set_position(gtk.WIN_POS_CENTER) - - self.window.connect("window-state-event", self.on_window_state_change) self.mainpanel = gtk.Fixed() self.window.add(self.mainpanel) @@ -50,42 +65,51 @@ class OpenboxLogout(): self.label_info.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("white")) self.mainpanel.put(self.label_info, x+490, y+170) - w = gtk.gdk.get_default_root_window() - sz = w.get_size() - pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1]) - pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1]) + if self.rendered_effects == True: + + logging.debug("Stepping though render path") + w = gtk.gdk.get_default_root_window() + sz = w.get_size() + pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1]) + pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1]) - if self.blur_background == True: - # Convert Pixbuf to PIL Image - width,height = pb.get_width(),pb.get_height() - pilimg = Image.fromstring("RGB",(width,height),pb.get_pixels() ) + logging.debug("Blur Enabled: %s" % self.blur_background) + if self.blur_background == True: + logging.debug("Rendering Blur") + # Convert Pixbuf to PIL Image + width,height = pb.get_width(),pb.get_height() + pilimg = Image.fromstring("RGB",(width,height),pb.get_pixels() ) - # Blur the image - pilimg = pilimg.filter(ImageFilter.BLUR) + # Blur the image + pilimg = pilimg.filter(ImageFilter.BLUR) - # "Convert" the PIL to Pixbuf via PixbufLoader - buf = StringIO.StringIO() - pilimg.save(buf, "ppm") - del pilimg - loader = gtk.gdk.PixbufLoader("pnm") - loader.write(buf.getvalue()) - pixbuf = loader.get_pixbuf() + # "Convert" the PIL to Pixbuf via PixbufLoader + buf = StringIO.StringIO() + pilimg.save(buf, "ppm") + del pilimg + loader = gtk.gdk.PixbufLoader("pnm") + loader.write(buf.getvalue()) + pixbuf = loader.get_pixbuf() - # Cleanup IO - buf.close() - loader.close() + # Cleanup IO + buf.close() + loader.close() + else: + pixbuf = pb + del pb + + pixmap, mask = pixbuf.render_pixmap_and_mask() + # width, height = pixmap.get_size() else: - pixbuf = pb - - pixmap, mask = pixbuf.render_pixmap_and_mask() - # width, height = pixmap.get_size() + pixmap = None + self.window.set_app_paintable(True) self.window.resize(screen_x, screen_y) self.window.realize() - self.window.window.set_back_pixmap(pixmap, False) + if pixmap: + self.window.window.set_back_pixmap(pixmap, False) self.window.move(0,0) - del pixbuf - del pixmap + def load_config(self, config): @@ -95,7 +119,52 @@ class OpenboxLogout(): parser = ConfigParser.SafeConfigParser() parser.read(config) - self.blur_background = parser.get("looks", "blurbackground") + self.blur_background = parser.getboolean("looks", "blur") + self.opacity = parser.getint("looks", "opacity") + + print self.blur_background + + if self.blur_background: + self.rendered_effects = True + else: + self.rendered_effects = False + + def on_expose(self, widget, event): + + cr = widget.window.cairo_create() + + if self.supports_alpha == True: + cr.set_source_rgba(1.0, 1.0, 1.0, 0.0) # Transparent + else: + cr.set_source_rgb(1.0, 1.0, 1.0) # Opaque white + + # Draw the background + cr.set_operator(cairo.OPERATOR_SOURCE) + cr.paint() + + (width, height) = widget.get_size() + cr.set_source_rgba(0, 0, 0, .5) + + cr.rectangle(0, 0, width, height) + cr.fill() + cr.stroke() + return False + + def on_screen_changed(self, widget, old_screen=None): + + # To check if the display supports alpha channels, get the colormap + screen = widget.get_screen() + colormap = screen.get_rgba_colormap() + if colormap == None: + logging.debug('Screen does not support alpha channels!') + colormap = screen.get_rgb_colormap() + self.supports_alpha = False + else: + logging.debug('Screen supports alpha channels!') + self.supports_alpha = True + + # Now we have a colormap appropriate for the screen, use it + widget.set_colormap(colormap) def on_window_state_change(self, widget, event, *args): if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: @@ -144,5 +213,7 @@ class OpenboxLogout(): gtk.main() if __name__ == "__main__": + + logging.basicConfig(level=logging.DEBUG) app = OpenboxLogout('openbox-logout.conf') app.run() diff --git a/openbox-logout.conf b/openbox-logout.conf index 90e547f..4db23e0 100644 --- a/openbox-logout.conf +++ b/openbox-logout.conf @@ -1,2 +1,3 @@ [looks] -blurbackground = False +blur = False +opacity = 50