Exemplo n.º 1
0
class GlassWindow(gtk.Window):

    #
    # Constructor.
    #
    def __init__(self, wintype = gtk.WINDOW_TOPLEVEL):

        # handler for transparency updates
        self.__update_handler = None

        # remember the current window position to detect movements
        self.__position = (0, 0)
        self.__size = (0, 0)

        # window manager
        self.__wm = self.__get_window_manager()

        gtk.Window.__init__(self, wintype)

        self.__layout = gtk.Fixed()
        self.__layout.show()
        gtk.Window.add(self, self.__layout)

        self.__background = Tiling()
        self.__layout.put(self.__background, 0, 0)
        
        self.__on_screen_changed (self, None)
        # Workaround for Ubuntu >= 11.04
        # Thanks screenlets
        # (http://bazaar.launchpad.net/~screenlets-dev/screenlets/trunk/revision/646)
        try:
            self.set_property('has-resize-grip', False)
        except TypeError:
            pass
        self.set_app_paintable (True)
        
        self.__bg_watcher = BGWatcher()

        self.connect("configure-event", self.__on_configure)
        self.connect("screen-changed", self.__on_screen_changed)
        self.connect("expose-event", self.__on_expose_event)
        self.connect("composited-changed", self.__on_composited_changed)
        
        self.__is_composited = True
        self.__on_composited_changed (self)



    #
    # Override add method.
    #
    def add(self, widget):

        self.__layout.put(widget, 0, 0)



    #
    # Override resize method.
    #
    def resize(self, width, height):

        self.__layout.set_size_request(width, height)
        gobject.idle_add(gtk.Window.resize, self, width, height)



    #
    # Observer method for the background.
    # Connect this method to the BG watcher.
    #
    def __bg_observer(self, src, cmd):

        self.__update_bg()



    #
    # Updates the background for transparency.
    #
    def __update_bg(self):

        if (self.__update_handler):
            gobject.source_remove(self.__update_handler)
            self.__update_handler = gobject.timeout_add(100, self.__updater)
        else: self.__updater()



    def __updater(self):

        if (not self.window): return

        x, y = self.window.get_origin()
        width, height = self.window.get_size()
        if (width > 1 and height > 1):
            self.__capture_bg(x, y, width, height)



    #
    # Captures the background to create transparency.
    #
    def __capture_bg(self, x, y, width, height):

        wallpaper.get_wallpaper(self.__background, x, y, width, height)
        self.queue_draw()

    #
    # Reacts on expose event
    #
    def __on_expose_event (self, widget, event = None, user_data = None):

        cr = widget.window.cairo_create ()
        # Fill with fully transparent white
        cr.set_source_rgba (1.0, 1.0, 1.0, 0.0)
        cr.set_operator (cairo.OPERATOR_SOURCE)
        cr.paint ()

    #
    # Reacts on composited changed
    #
    def __on_composited_changed (self, widget):
        
        screen = self.get_screen ()
        is_composited = gtk.ver[1] >= 10 and screen.is_composited ()
        
        if self.__is_composited == is_composited:
            return
        
        if is_composited:
            self.__is_composited = True
            self.__background.hide ()
            try:
                self.__bg_watcher.remove_observer(self.__bg_observer)
            except: pass
        else:
            self.__is_composited = False
            self.__bg_watcher.add_observer(self.__bg_observer)
            self.__background.show ()

    #
    # Reacts on screen changed
    #
    def __on_screen_changed (self, src, old_screen):
        
        screen = self.get_screen ()
        colormap = screen.get_rgba_colormap ()
        
        if colormap == None:
            colormap = screen.get_rgb_colormap ()

        self.set_colormap (colormap)


    #
    # Reacts on moving the window.
    #
    def __on_configure(self, src, event):

        pos = self.window.get_origin()
        size = self.window.get_size()
        if (pos != self.__position or size != self.__size):
            self.__position = pos
            self.__size = size
            if not self.__is_composited: 
                self.__update_bg()


    #
    # Sets the BELOW window flag.
    #
    def _set_flag_below(self, value, tries = 0):

        if (not self.__wm == "Enlightenment" and
            not self.get_property("visible") and
            not tries >= 10):
            gobject.timeout_add(500, self._set_flag_below, value, tries + 1)

        if (self.window):
            x11.set_above(self.window, not value)
            x11.set_below(self.window, value)



    #
    # Sets the ABOVE window flag.
    #
    def _set_flag_above(self, value, tries = 0):

        if (not self.__wm == "Enlightenment" and
            not self.__wm.startswith("Xfwm4") and
            not self.get_property("visible") and
            not tries >= 11):
            gobject.timeout_add(500, self._set_flag_above, value, tries + 1)

        if (self.window):
            x11.set_below(self.window, not value)
            x11.set_above(self.window, value)



    #
    # Sets the STICKY window flag.
    #
    def _set_flag_sticky(self, value):

        if (value): self.stick()
        else: self.unstick()



    def _set_type_hint_dock(self, window, value):

        x11.set_type_dock(window, value)



    #
    # Sets the MANAGED window flag.
    #
    def _set_flag_managed(self, value):

        if (value):
            self.set_property("skip-taskbar-hint", 0)
            self.set_property("skip-pager-hint", 0)
            self._set_type_hint_dock(self.window, False)
        else:
            self.set_property("skip-taskbar-hint", 1)
            self.set_property("skip-pager-hint", 1)

            if (self.__wm == "Metacity"):
                self._set_type_hint_dock(self.window, True)



    #
    # Sets the DECORATED window flag.
    #
    def _set_flag_decorated(self, value):

        if (value): self.set_decorated(True)
        else: self.set_decorated(False)



    #
    # Returns the name of the running EWMH compliant window manager or "".
    #
    def __get_window_manager(self):

        name = ""
        win = ""
        # get the window where the EMWH compliant window manager tells its name
        root = gtk.gdk.get_default_root_window()
        try:
            ident = root.property_get("_NET_SUPPORTING_WM_CHECK", "WINDOW")[2]
            win = gtk.gdk.window_foreign_new(long(ident[0]))
        except TypeError, exc:
            log("Your window manager doesn't support "
                "_NET_SUPPORTING_WM_CHECK! Switch to a compliant WM!"
                "The following error occurred:\n%s" % (exc,))
        if (win != None and win != ""):
            try:
                name = win.property_get("_NET_WM_NAME")[2]
            except TypeError, exc:
                log("Your window manager doesn't support _NET_WM_NAME!\n"
                    "Switch to a EWMH compliant WM.\n"
                    "The following error occurred:\n%s" % (exc,))
                return name
Exemplo n.º 2
0
class TargetLabel(DisplayTarget):

    # regular expression for parsing font description strings
    __RE_FONT = re.compile("(?P<name>.+?)"
                           "(?P<size>[0-9\.]+)"
                           "(?P<unit>[a-z%]+)?$")


    def utf8_to_utf8(value):

        if (isinstance(value, unicode)):
            try:
                value = value.encode("UTF-8", "replace")
            except ValueError:
                log("Unicode -> UTF-8 convertion failed !!!")
                raise

        elif (not isinstance(value, str)):
            # int, float, long, list, tuple, instance
            value = str(value)

        return value


    def charmap_to_utf8(value):

        if (isinstance(value, str)):
            try:
                value = unicode(value, CHARMAP, "ignore")
            except LookupError:
                # may be it's already UTF-8 ?
                value = unicode(value, "UTF-8", "replace")

        if (isinstance(value, unicode)):
            try:
                value = value.encode("UTF-8", "replace")
            except ValueError:
                log("Unicode -> UTF-8 convertion failed !!!")
                raise

        else:
            # int, float, long, list, tuple, instance
            value = str(value)

        return value


    #
    # Converts the given string to UTF-8 format.
    #
    if (CHARMAP == 'UTF-8'):
        __utf8ify = staticmethod(utf8_to_utf8)
    else:
        __utf8ify = staticmethod(charmap_to_utf8)



    def __init__(self, name, parent):

        self.__old_value = ""
        self.__font_description = None
        self.__wrap_at = -1
        self.__alignment = pango.ALIGN_LEFT
        self.__justify = True

        self.__size = (0, 0)

        DisplayTarget.__init__(self, name, parent)

        self.__widget = Tiling()
        self.__pango_context = self.__widget.get_pango_context()
        self.__pango_context.set_base_dir(pango.DIRECTION_LTR)
        self.__pango_layout = pango.Layout(self.__pango_context)
        self.__color = (0, 0, 0, 255)
        self.__font_description = self.__pango_context.get_font_description()
        self.__widget.show()

        # i guess a label has to accept everything printable for its value
        # these days
        self._register_property("value", TYPE_ANY,
                                self._setp_value, self._getp)
        self._register_property("color", TYPE_STRING,
                                self._setp_color, self._getp)
        self._register_property("font", TYPE_STRING,
                                self._setp_font, self._getp)
        self._register_property("wrap-at", TYPE_UNIT,
                                self._setp_wrap_at, self._getp)
        self._register_property("alignment", TYPE_STRING,
                                self._setp_alignment, self._getp)
        self._register_property("justify", TYPE_BOOL,
                                self._setp_justify, self._getp)

        self._setp("value", "")
        self._setp("color", "black")
        self.set_prop("font", "Sans 8")
        self.set_prop("wrap-at", Unit.Unit(0, Unit.UNIT_PX))
        self.set_prop("alignment", "left")
        self.set_prop("justify", True)

        # watch the widget for geometry changes; we need this for percentual
        # font sizes
        self.add_observer(self.__on_observe_size)


    def get_widget(self): return self.__widget


    def __on_observe_size(self, src, cmd, *args):

        x, y, w, h = src.get_geometry()
        if (cmd == src.OBS_GEOMETRY):
            self.__size = (w.as_px(), h.as_px())
            self.__set_justify(self.get_prop("justify"))
            self.__set_alignment(self.get_prop("alignment"))
            self.__set_wrap(self.get_prop("wrap-at"))
            self.__set_font(self.get_prop("font"))
            self.__set_value(self.get_prop("value"))


    #
    # Renders the given text.
    #
    def __render_text(self, layout):

        width, height = layout.get_pixel_size()

        # render font
        pmap = gtk.gdk.Pixmap(gtk.gdk.get_default_root_window(),
                              width, height * 2)
        gc = pmap.new_gc()
        gc.set_foreground(self.__widget.get_colormap().alloc_color("black"))
        pmap.draw_rectangle(gc, True, 0, 0, width, height)
        gc.set_foreground(self.__widget.get_colormap().alloc_color("white"))
        pmap.draw_rectangle(gc, True, 0, height, width, height)

        r, g, b, a = self.__color
        col = "#" + ("0" + hex(r)[2:])[-2:] + \
                    ("0" + hex(g)[2:])[-2:] + \
                    ("0" + hex(b)[2:])[-2:]
        gc.set_foreground(
            gtk.gdk.get_default_root_window().get_colormap().alloc_color(col))
        if (self.__alignment == pango.ALIGN_RIGHT):
            pmap.draw_layout(gc, width, 0, layout)
            pmap.draw_layout(gc, width, height, layout)
        elif (self.__alignment == pango.ALIGN_CENTER):
            pmap.draw_layout(gc, int(width / 2.0), 0, layout)
            pmap.draw_layout(gc, int(width / 2.0), height, layout)
        else:
            pmap.draw_layout(gc, 0, 0, layout)
            pmap.draw_layout(gc, 0, height, layout)
#        pmap.draw_layout(gc, 0, 0, layout)
#        pmap.draw_layout(gc, 0, height, layout)

        #  then copy to image
        self.__widget.set_from_drawable(pmap, True)
        width, height = self.__size
        if (width and height):
            self.__widget.render(width, height, a / 255.0, 1)


    def __make_label(self):

        value = self.__old_value

        self.__pango_layout.set_markup(value)
        self.__pango_layout.set_font_description(self.__font_description)
        self.__pango_layout.set_alignment(self.__alignment)
        self.__pango_layout.set_justify(self.__justify)
        self.__pango_layout.set_width(self.__wrap_at * pango.SCALE)
        width, height = self.__pango_layout.get_pixel_size()

        if (width and height):
            self.__render_text(self.__pango_layout)
            self.__widget.show()
        else:
            self.__widget.hide()

        self.set_size(Unit.Unit(width, Unit.UNIT_PX),
                      Unit.Unit(height, Unit.UNIT_PX))



    def __set_value(self, value):

        value = self.__utf8ify(value)
        self.__old_value = value
        self.__make_label()



    def __set_font(self, font):

        m = TargetLabel.__RE_FONT.match(font)
        if (m):
            name = m.group("name")
            unit = m.group("unit") or Unit.UNIT_PT  # pt is default for fonts
            size = m.group("size")
            if (size):
                size = float(size)
                if (unit == Unit.UNIT_PERCENT):
                    height = self._get_parent().get_geometry()[3]
                    # don't allow 0 pixels height
                    size = max(1, height.as_pt() * (size / 100.0))
                    unit = Unit.UNIT_PT
                u = Unit.Unit(size, unit)
                size = u.as_pt()
                font = "%s %f" % (name, size)

        self.__font_description = pango.FontDescription(font)
        self.__pango_context.set_font_description(self.__font_description)
        #self.__widget.set_size_request(-1, -1)


    def __set_color(self, color):

        self.__color = utils.parse_color(color)


    def __set_wrap(self, value):

        width = self._get_parent().get_geometry()[2]
        if (width > Unit.ZERO): value.set_100_percent(width.as_px())
        size = value.as_px()

        if (size == 0):
            self.__wrap_at = -1
        else:
            self.__wrap_at = size


    def __set_alignment(self, value):

        if (value == "right"): self.__alignment = pango.ALIGN_RIGHT
        elif (value == "center"): self.__alignment = pango.ALIGN_CENTER
        else: self.__alignment = pango.ALIGN_LEFT


    def __set_justify(self, value):

        self.__justify = value


    #
    # "value" property.
    #
    def _setp_value(self, key, value):

        if (value != self.__old_value):
            self.__set_value(value)
            self._setp(key, value)
            self.__make_label()


    #
    # "font" property.
    #
    def _setp_font(self, key, value):

        if (value != self.get_prop("font")):
            self.__set_font(value)
            self._setp(key, value)
            self.__make_label()
            #self.__set_value(self.get_prop("value"))


    #
    # "color" property.
    #
    def _setp_color(self, key, value):

        self.__set_color(value)
        self._setp(key, value)
        self.__make_label()


    #
    # "wrap-at" property.
    #
    def _setp_wrap_at(self, key, value):

        self.__set_wrap(value)
        self._setp(key, value)
        self.__make_label()


    #
    # "alignment" property.
    #
    def _setp_alignment(self, key, value):

        self.__set_alignment(value)
        self._setp(key, value)
        self.__make_label()


    #
    # "justify" property.
    #
    def _setp_justify(self, key, value):

        self.__set_justify(value)
        self._setp(key, value)
        self.__make_label()