예제 #1
0
class WindowItem(CairoButton):
    __gsignals__ = {
        "enter-notify-event": "override",
        "leave-notify-event": "override",
        "button-press-event": "override",
        "scroll-event": "override",
        "clicked": "override",
        "drag-motion": "override",
        "drag-leave": "override",
    }

    def __init__(self, window, group):
        CairoButton.__init__(self)
        self.set_no_show_all(True)

        self.window_r = weakref.ref(window)
        self.group_r = weakref.ref(group)
        self.globals = Globals()

        self.opacify_sid = None
        self.deopacify_sid = None
        self.press_sid = None
        self.pressed = False

        self.close_button = CairoCloseButton()
        self.close_button.set_no_show_all(True)
        if self.globals.settings["show_close_button"]:
            self.close_button.show()
        self.label = gtk.Label()
        self.label.set_ellipsize(pango.ELLIPSIZE_END)
        self.label.set_alignment(0, 0.5)
        self.__update_label()
        self.area.set_needs_attention(window.wnck.needs_attention())
        hbox = gtk.HBox()
        icon = window.wnck.get_mini_icon()
        self.icon_image = gtk.image_new_from_pixbuf(icon)
        hbox.pack_start(self.icon_image, False)
        hbox.pack_start(self.label, True, True, padding=4)
        alignment = gtk.Alignment(1, 0.5, 0, 0)
        alignment.add(self.close_button)
        hbox.pack_start(alignment, False, False)

        vbox = gtk.VBox()
        vbox.pack_start(hbox, False)
        self.preview_box = gtk.Alignment(0.5, 0.5, 0, 0)
        self.preview_box.set_padding(4, 2, 0, 0)
        self.preview = gtk.Image()
        self.preview_box.add(self.preview)
        self.preview.show()
        vbox.pack_start(self.preview_box, True, True)
        self.add(vbox)
        self.preview_box.set_no_show_all(True)
        vbox.show_all()

        self.show_all()
        self.update_show_state()

        self.drag_dest_set(0, [], 0)
        self.drag_entered = False

        self.close_button.connect("button-press-event", self.disable_click)
        self.close_button.connect("clicked", self.__on_close_button_clicked)
        self.close_button.connect("leave-notify-event",
                                  self.__on_close_button_leave)
        connect(self.globals, "show-close-button-changed",
                self.__on_show_close_button_changed)
        connect(self.globals, "color-changed", self.__update_label)
        connect(self.globals, "preview-size-changed", self.update_preview)
        connect(self.globals, "window-title-width-changed",
                self.__update_label)

    def clean_up(self):
        window = self.window_r()
        if self.deopacify_sid:
            gobject.source_remove(self.deopacify_sid)
            window.deopacify()
        if self.opacify_sid:
            gobject.source_remove(self.opacify_sid)
        if self.press_sid:
            gobject.source_remove(self.press_sid)
        self.close_button.destroy()

    def show(self):
        self.update_preview()
        CairoButton.show(self)

    def __on_show_close_button_changed(self, *args):
        if self.globals.settings["show_close_button"]:
            self.close_button.show()
        else:
            self.close_button.hide()
            self.label.queue_resize()

    #### Apperance
    def __update_label(self, arg=None):
        """Updates the style of the label according to window state."""
        window = self.window_r()
        text = escape(str(window.wnck.get_name()))
        if window.wnck.is_minimized():
            color = self.globals.colors["color4"]
        else:
            color = self.globals.colors["color2"]
        text = "<span foreground=\"" + color + "\">" + text + "</span>"
        self.label.set_text(text)
        self.label.set_use_markup(True)
        if self.globals.settings["preview"]:
            # The label should be 140px wide unless there are more room
            # because the preview takes up more.
            size = 140
        else:
            size = self.globals.settings["window_title_width"]
        self.label.set_size_request(size, -1)

    def __make_minimized_icon(self, icon):
        pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8,
                                icon.get_width(), icon.get_height())
        pixbuf.fill(0x00000000)
        minimized_icon = pixbuf.copy()
        icon.composite(pixbuf, 0, 0, pixbuf.get_width(), pixbuf.get_height(),
                       0, 0, 1, 1, gtk.gdk.INTERP_BILINEAR, 190)
        pixbuf.saturate_and_pixelate(minimized_icon, 0.12, False)
        return minimized_icon

    def __update_icon(self):
        window = self.window_r()
        icon = window.wnck.get_mini_icon()
        if window.wnck.is_minimized():
            pixbuf = self.__make_minimized_icon(icon)
            self.icon_image.set_from_pixbuf(pixbuf)
            if self.globals.settings["preview"] and \
               (self.globals.get_compiz_version() < "0.9" or \
               not self.globals.settings["preview_minimized"]):
                self.preview.set_from_pixbuf(window.wnck.get_icon())
        else:
            self.icon_image.set_from_pixbuf(icon)
            self.preview.clear()

    def minimized_changed(self):
        window = self.window_r()
        self.__update_label()
        self.__update_icon()
        self.area.set_minimized(window.wnck.is_minimized())

    def active_changed(self):
        window = self.window_r()
        self.area.set_active_window(window.is_active_window)
        self.__update_label()

    def icon_changed(self):
        self.__update_icon()

    def needs_attention_changed(self):
        window = self.window_r()
        self.area.set_needs_attention(window.wnck.needs_attention())
        self.__update_label()

    def name_changed(self):
        self.__update_label()

    def set_highlighted(self, highlighted):
        self.area.set_highlighted(highlighted)

    def update_show_state(self):
        window = self.window_r()
        if (self.globals.settings["show_only_current_desktop"] and \
           not window.on_current_desktop) or \
           (self.globals.settings["show_only_current_monitor"] and \
           window.monitor != self.group_r().monitor):
            self.hide()
        else:
            self.show()

    ####Preview
    def update_preview(self, *args):
        window = self.window_r()
        group = self.group_r()
        width = window.wnck.get_geometry()[2]
        height = window.wnck.get_geometry()[3]
        ar = group.monitor_aspect_ratio
        size = self.globals.settings["preview_size"]
        if width * ar < size and height < size:
            pass
        elif float(width) / height > ar:
            height = int(round(size * ar * height / width))
            width = int(round(size * ar))
        else:
            width = int(round(float(size) * width / height))
            height = size
        self.preview.set_size_request(width, height)
        return width, height

    def set_show_preview(self, show_preview):
        if show_preview:
            self.preview_box.show()
        else:
            self.preview_box.hide()

    def get_preview_allocation(self):
        a = self.preview.get_allocation()
        self.area.set_preview_allocation(a)
        return a

    #### Events
    def do_enter_notify_event(self, event):
        # In compiz there is a enter and
        # a leave event before a press event.
        # Keep that in mind when coding this def!
        CairoButton.do_enter_notify_event(self, event)
        if self.pressed:
            return
        if self.globals.settings["opacify"]:
            self.opacify_sid = \
                gobject.timeout_add(100, self.__opacify)

    def do_leave_notify_event(self, event):
        # In compiz there is a enter and a leave
        # event before a press event.
        # Keep that in mind when coding this def!
        CairoButton.do_leave_notify_event(self, event)
        self.pressed = False
        if self.globals.settings["opacify"]:
            self.deopacify_sid = \
                            gobject.timeout_add(200, self.__deopacify)

    def do_button_press_event(self, event):
        # In compiz there is a enter and a leave event before
        # a press event.
        # self.pressed is used to stop functions started with
        # gobject.timeout_add from self.__on_mouse_enter
        # or self.__on_mouse_leave.
        CairoButton.do_button_press_event(self, event)
        self.pressed = True
        self.press_sid = gobject.timeout_add(600, self.__set_pressed_false)

    def __set_pressed_false(self):
        # Helper function for __on_press_event.
        self.pressed = False
        self.press_sid = None
        return False

    def do_scroll_event(self, event):
        window = self.window_r()
        if self.globals.settings["opacify"]:
            window.deopacify()
        if not event.direction in (gtk.gdk.SCROLL_UP, gtk.gdk.SCROLL_DOWN):
            return
        direction = {
            gtk.gdk.SCROLL_UP: "scroll_up",
            gtk.gdk.SCROLL_DOWN: "scroll_down"
        }[event.direction]
        action = self.globals.settings["windowbutton_%s" % direction]
        window.action_function_dict[action](window, self, event)
        if self.globals.settings["windowbutton_close_popup_on_%s" % direction]:
            self.group_r().popup.hide()

    def do_clicked(self, event):
        window = self.window_r()
        if self.globals.settings["opacify"]:
            window.deopacify()

        if not event.button in (1, 2, 3):
            return
        button = {1: "left", 2: "middle", 3: "right"}[event.button]
        if event.state & gtk.gdk.SHIFT_MASK:
            mod = "shift_and_"
        else:
            mod = ""
        action_str = "windowbutton_%s%s_click_action" % (mod, button)
        action = self.globals.settings[action_str]
        window.action_function_dict[action](window, self, event)

        popup_close = "windowbutton_close_popup_on_%s%s_click" % (mod, button)
        if self.globals.settings[popup_close]:
            self.group_r().popup.hide()

    def __on_close_button_clicked(self, *args):
        window = self.window_r()
        if self.globals.settings["opacify"]:
            window.deopacify()
        window.action_close_window()

    def __on_close_button_leave(self, widget, event):
        if not self.pointer_is_inside():
            self.do_leave_notify_event(event)

    #### D'n'D
    def do_drag_motion(self, drag_context, x, y, t):
        if not self.drag_entered:
            self.group_r().popup.expose()
            self.drag_entered = True
            self.dnd_select_window = \
                gobject.timeout_add(600, self.window_r().action_select_window)
        drag_context.drag_status(gtk.gdk.ACTION_PRIVATE, t)
        return True

    def do_drag_leave(self, drag_context, t):
        self.drag_entered = False
        gobject.source_remove(self.dnd_select_window)
        self.group_r().popup.expose()
        self.group_r().popup.hide_if_not_hovered()

    #### Opacify
    def __opacify(self):
        window = self.window_r()
        if window.wnck.is_minimized():
            return False
        # if self.pressed is true, opacity_request is called by an
        # wrongly sent out enter_notification_event sent after a
        # press (because of a bug in compiz).
        if self.pressed:
            self.pressed = False
            return False
        # Check if mouse cursor still is over the window button.
        if self.pointer_is_inside():
            window.opacify()
            # Just for safety in case no leave-signal is sent
            self.deopacify_sid = \
                            gobject.timeout_add(500, self.__deopacify)
        return False

    def __deopacify(self):
        window = self.window_r()
        # Make sure that mouse cursor really has left the window button.
        b_m_x, b_m_y = self.get_pointer()
        b_r = self.get_allocation()
        if b_m_x >= 0 and b_m_x < b_r.width \
        and b_m_y >= 0 and b_m_y < b_r.height:
            return True
        # Wait before deopacifying in case a new windowbutton
        # should call opacify, to avoid flickering
        window.deopacify_sid = gobject.timeout_add(150, window.deopacify)
        return False

    #### Menu functions
    def show_menu(self, event):
        window = self.window_r()
        #Creates a popup menu
        menu = gtk.Menu()
        menu.connect("selection-done", self.__menu_closed)
        #(Un)Minimize
        minimize_item = None
        if window.wnck.get_actions() & WNCK_WINDOW_ACTION_MINIMIZE \
        and not window.wnck.is_minimized():
            minimize_item = gtk.MenuItem(_("_Minimize"))
        elif window.wnck.get_actions() & WNCK_WINDOW_ACTION_UNMINIMIZE \
        and window.wnck.is_minimized():
            minimize_item = gtk.MenuItem(_("Un_minimize"))
        if minimize_item:
            menu.append(minimize_item)
            minimize_item.connect("activate", window.action_minimize_window)
            minimize_item.show()
        # (Un)Maximize
        maximize_item = None
        if not window.wnck.is_maximized() \
        and window.wnck.get_actions() & WNCK_WINDOW_ACTION_MAXIMIZE:
            maximize_item = gtk.MenuItem(_("Ma_ximize"))
        elif window.wnck.is_maximized() \
        and window.wnck.get_actions() & WNCK_WINDOW_ACTION_UNMINIMIZE:
            maximize_item = gtk.MenuItem(_("Unma_ximize"))
        if maximize_item:
            menu.append(maximize_item)
            maximize_item.connect("activate", window.action_maximize_window)
            maximize_item.show()
        # Close
        close_item = gtk.MenuItem(_("_Close"))
        menu.append(close_item)
        close_item.connect("activate", window.action_close_window)
        close_item.show()
        menu.popup(None, None, None, event.button, event.time)
        self.globals.gtkmenu_showing = True

    def __menu_closed(self, menushell):
        self.globals.gtkmenu_showing = False
        self.group_r().popup.hide()
        menushell.destroy()
예제 #2
0
class CairoArea(gtk.Alignment):
    __gsignals__ = {"expose-event" : "override"}
    def __init__(self, text=None, area_type="window_item"):
        self.type = area_type
        self.text = text
        gtk.Alignment.__init__(self, 0, 0, 1, 1)
        self.popup_style = PopupStyle()
        lrp = int(self.popup_style.get("%s_lr_padding" % self.type,
                                                5))
        tdp = int(self.popup_style.get("%s_td_padding" % self.type,
                                                5))
        self.set_padding(lrp, lrp, tdp, tdp)
        self.set_app_paintable(1)
        self.globals = Globals()
        self.highlighted = False
        self.pressed_down = False
        self.active_window = False
        self.needs_attention = False
        self.minimized = False
        self.preview_allocation = [0, 0, 0, 0]
        if text:
            self.label = gtk.Label()
            self.add(self.label)
            self.label.show()
            color = self.globals.colors["color2"]
            self.set_label(text, color)
        else:
            self.label = None

    def set_label(self, text, color=None):
        self.text = text
        if color:
            text = "<span foreground=\"" + color + "\">" + escape(text) + \
                   "</span>"
        self.label.set_text(text)
        self.label.set_use_markup(True)
        self.label.set_use_underline(True)

    def set_padding(self, top, bottom, left, right):
        self.pressed_down = False
        gtk.Alignment.set_padding(self, top, bottom, left, right)

    def set_label_color(self, color):
        label = "<span foreground=\"" + color + "\">" + escape(self.text) + \
                "</span>"
        self.label.set_text(label)
        self.label.set_use_markup(True)
        self.label.set_use_underline(True)

    def do_expose_event(self, event, arg=None):
        a = self.get_allocation()
        mx , my = self.get_pointer()
        preview = self.globals.settings["preview"] and \
                  self.globals.get_compiz_version() >= "0.9" and \
                  (self.globals.settings["preview_minimized"] or \
                   not self.minimized)
        highlighted = self.highlighted or \
                      (mx >= 0 and mx < a.width and my >= 0 and my < a.height)
            
        if preview or self.active_window or \
           highlighted or self.needs_attention:
            ctx = self.window.cairo_create()
            ctx.rectangle(event.area.x, event.area.y,
                          event.area.width, event.area.height)
            ctx.clip()
        if self.needs_attention:
            self.draw_type_frame(ctx, a.x, a.y, a.width, a.height,
                                 "needs_attention_item")
        if self.active_window:
            self.draw_type_frame(ctx, a.x, a.y, a.width, a.height,
                                 "active_item")
        if highlighted:
            self.draw_frame(ctx, a.x, a.y, a.width, a.height)
        # Empty preview space
        if preview:
            ctx.rectangle(*self.preview_allocation)
            ctx.set_source_rgba(1, 1, 1, 0)
            ctx.set_operator(cairo.OPERATOR_SOURCE)
            ctx.fill()
        self.propagate_expose(self.get_child(), event)
        return

    def draw_frame(self, ctx, x, y, w, h):
        if self.is_composited():
            r, g, b = parse_color(self.globals.colors["color1"])
            alpha = parse_alpha(self.globals.colors["color1_alpha"])
        else:
            r = g = b = 0.0
            alpha = 0.25
        roundness = int(self.popup_style.get("%s_roundness" % \
                                                      self.type, 5))
        make_path(ctx, x, y, w, h, roundness)


        ctx.set_source_rgba(r, g, b, alpha)
        ctx.fill_preserve()
        bc = self.popup_style.get("%s_border_color" % self.type,
                                           "#FFFFFF")
        if not bc[0] == "#":
            bc = "#%s" % bc
        alpha = self.popup_style.get("%s_border_alpha" % self.type,
                                              80)
        alpha = float(alpha) / 100
        r, g, b = parse_color(bc)
        ctx.set_source_rgba(r, g, b, alpha)
        ctx.set_line_width(1)
        ctx.stroke()

    def draw_type_frame(self, ctx, x, y, w, h, type_):
        # Todo: make colors themable?
        if type_ == "active_item":
            color = self.globals.colors["color3"]
        elif type_ == "needs_attention_item":
            color = self.popup_style.get("%s_color" % type_,
                                                  "#FF0000")
        roundness = int(self.popup_style.get("%s_roundness" % \
                                                      self.type, 5))
        make_path(ctx, x, y, w, h, roundness)

        if color[0] != "#":
            color = "#%s" % color
        r, g, b = parse_color(color)
        # Todo: make alpha adjustable from theme.
        alpha = self.popup_style.get("%s_alpha" % type_, 15)
        alpha = float(alpha) / 100
        ctx.set_source_rgba(r, g, b, 0.25)
        ctx.fill_preserve()
        
        bc = self.popup_style.get("%s_border_color" % type_,
                                           "#FFFFFF")
        if not bc[0] == "#":
            bc = "#%s" % bc
        # Todo: make alpha adjustable from theme.
        r, g, b = parse_color(bc)
        alpha = self.popup_style.get("%s_border_alpha" % type_, 15)
        alpha = float(alpha) / 100
        ctx.set_source_rgba(r, g, b, alpha)
        ctx.set_line_width(1)
        ctx.stroke()

    def set_pressed_down(self, pressed):
        p = self.get_padding()
        if pressed and not self.pressed_down:
            gtk.Alignment.set_padding(self, p[0] + 1, p[1] - 1, p[2], p[3])
        elif self.pressed_down and not pressed:
            gtk.Alignment.set_padding(self, p[0] - 1, p[1] + 1, p[2], p[3])
        self.pressed_down = pressed

    def set_highlighted(self, highlighted):
        self.highlighted = highlighted
        self.queue_draw()

    def set_active_window(self, active):
        self.active_window = active
        self.queue_draw()

    def set_needs_attention(self, needs_attention):
        self.needs_attention = needs_attention
        self.queue_draw()

    def set_minimized(self, minimized):
        self.minimized = minimized
        self.queue_draw()

    def set_preview_allocation(self, allocation):
        self.preview_allocation = allocation

    def pointer_is_inside(self):
        mx,my = self.get_pointer()
        a = self.get_allocation()

        if mx >= 0 and mx < a.width \
        and my >= 0 and my < a.height:
            # Mouse pointer is inside the "rectangle"
            # but check if it's still outside the rounded corners
            x = None
            y = None
            r = int(self.popup_style.get("%s_roundness" % self.type,
                                                  5))
            if mx < r:
                x = r - mx
            if (a.width - mx) < r:
                x = mx - (a.width - r)
            if my < r:
                y = r - my
            if (a.height - my) < r:
                y = my - (a.height - r)
            if x is None or y is None \
            or (x**2 + y**2) < (r-1)**2:
                return True
        else:
            return False
예제 #3
0
class WindowItem(CairoButton):
    __gsignals__ = {"enter-notify-event": "override",
                    "leave-notify-event": "override",
                    "button-press-event": "override",
                    "scroll-event": "override",
                    "clicked": "override",
                    "drag-motion" : "override",
                    "drag-leave" : "override",}
    def __init__(self, window, group):
        CairoButton.__init__(self)
        self.set_no_show_all(True)

        self.window_r = weakref.ref(window)
        self.group_r = weakref.ref(group)
        self.globals = Globals()

        self.opacify_sid = None
        self.deopacify_sid = None
        self.press_sid = None
        self.pressed = False

        self.close_button = CairoCloseButton()
        self.close_button.set_no_show_all(True)
        if self.globals.settings["show_close_button"]:
            self.close_button.show()
        self.label = gtk.Label()
        self.label.set_ellipsize(pango.ELLIPSIZE_END)
        self.label.set_alignment(0, 0.5)
        self.__update_label()
        self.area.set_needs_attention(window.wnck.needs_attention())
        hbox = gtk.HBox()
        icon = window.wnck.get_mini_icon()
        self.icon_image = gtk.image_new_from_pixbuf(icon)
        hbox.pack_start(self.icon_image, False)
        hbox.pack_start(self.label, True, True, padding = 4)
        alignment = gtk.Alignment(1, 0.5, 0, 0)
        alignment.add(self.close_button)
        hbox.pack_start(alignment, False, False)

        vbox = gtk.VBox()
        vbox.pack_start(hbox, False)
        self.preview_box = gtk.Alignment(0.5, 0.5, 0, 0)
        self.preview_box.set_padding(4, 2, 0, 0)
        self.preview = gtk.Image()
        self.preview_box.add(self.preview)
        self.preview.show()
        vbox.pack_start(self.preview_box, True, True)
        self.add(vbox)
        self.preview_box.set_no_show_all(True)
        vbox.show_all()
        
        self.show_all()
        self.update_show_state()

        self.drag_dest_set(0, [], 0)
        self.drag_entered = False

        self.close_button.connect("button-press-event", self.disable_click)
        self.close_button.connect("clicked", self.__on_close_button_clicked)
        self.close_button.connect("leave-notify-event",
                                  self.__on_close_button_leave)
        connect(self.globals, "show-close-button-changed",
                              self.__on_show_close_button_changed)
        connect(self.globals, "color-changed", self.__update_label)
        connect(self.globals, "preview-size-changed", self.update_preview)
        connect(self.globals, "window-title-width-changed",
                              self.__update_label)

    def clean_up(self):
        window = self.window_r()
        if self.deopacify_sid:
            gobject.source_remove(self.deopacify_sid)
            window.deopacify()
        if self.opacify_sid:
            gobject.source_remove(self.opacify_sid)
        if self.press_sid:
            gobject.source_remove(self.press_sid)
        self.close_button.destroy()

    def show(self):
        self.update_preview()
        CairoButton.show(self)

    def __on_show_close_button_changed(self, *args):
        if self.globals.settings["show_close_button"]:
            self.close_button.show()
        else:
            self.close_button.hide()
            self.label.queue_resize()

    #### Apperance
    def __update_label(self, arg=None):
        """Updates the style of the label according to window state."""
        window = self.window_r()
        text = escape(str(window.wnck.get_name()))
        if window.wnck.is_minimized():
            color = self.globals.colors["color4"]
        else:
            color = self.globals.colors["color2"]
        text = "<span foreground=\"" + color + "\">" + text + "</span>"
        self.label.set_text(text)
        self.label.set_use_markup(True)
        if self.globals.settings["preview"]:
            # The label should be 140px wide unless there are more room
            # because the preview takes up more.
            size = 140
        else:
            size = self.globals.settings["window_title_width"]
        self.label.set_size_request(size, -1)

    def __make_minimized_icon(self, icon):
        pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True,
                                          8, icon.get_width(),
                                          icon.get_height())
        pixbuf.fill(0x00000000)
        minimized_icon = pixbuf.copy()
        icon.composite(pixbuf, 0, 0, pixbuf.get_width(),
                         pixbuf.get_height(), 0, 0, 1, 1,
                         gtk.gdk.INTERP_BILINEAR, 190)
        pixbuf.saturate_and_pixelate(minimized_icon, 0.12, False)
        return minimized_icon

    def __update_icon(self):
        window = self.window_r()
        icon = window.wnck.get_mini_icon()
        if window.wnck.is_minimized():
            pixbuf = self.__make_minimized_icon(icon)
            self.icon_image.set_from_pixbuf(pixbuf)
            if self.globals.settings["preview"] and \
               (self.globals.get_compiz_version() < "0.9" or \
               not self.globals.settings["preview_minimized"]):
                   self.preview.set_from_pixbuf(window.wnck.get_icon())
        else:
            self.icon_image.set_from_pixbuf(icon)
            self.preview.clear()

    def minimized_changed(self):
        window = self.window_r()
        self.__update_label()
        self.__update_icon()
        self.area.set_minimized(window.wnck.is_minimized())

    def active_changed(self):
        window = self.window_r()
        self.area.set_active_window(window.is_active_window)
        self.__update_label()

    def icon_changed(self):
        self.__update_icon()

    def needs_attention_changed(self):
        window = self.window_r()
        self.area.set_needs_attention(window.wnck.needs_attention())
        self.__update_label()

    def name_changed(self):
        self.__update_label()

    def set_highlighted(self, highlighted):
        self.area.set_highlighted(highlighted)

    def update_show_state(self):
        window = self.window_r()
        if (self.globals.settings["show_only_current_desktop"] and \
           not window.on_current_desktop) or \
           (self.globals.settings["show_only_current_monitor"] and \
           window.monitor != self.group_r().monitor):
            self.hide()
        else:
            self.show()

    ####Preview
    def update_preview(self, *args):
        window = self.window_r()
        group = self.group_r()
        width = window.wnck.get_geometry()[2]
        height = window.wnck.get_geometry()[3]
        ar = group.monitor_aspect_ratio
        size = self.globals.settings["preview_size"]
        if width*ar < size and height < size:
            pass
        elif float(width) / height > ar:
            height = int(round(size * ar * height / width))
            width = int(round(size * ar))
        else:
            width = int(round(float(size) * width / height))
            height = size
        self.preview.set_size_request(width, height)
        return width, height

    def set_show_preview(self, show_preview):
        if show_preview:
            self.preview_box.show()
        else:
            self.preview_box.hide()

    def get_preview_allocation(self):
        a = self.preview.get_allocation()
        self.area.set_preview_allocation(a)
        return a

    #### Events
    def do_enter_notify_event(self, event):
        # In compiz there is a enter and
        # a leave event before a press event.
        # Keep that in mind when coding this def!
        CairoButton.do_enter_notify_event(self, event)
        if self.pressed :
            return
        if self.globals.settings["opacify"]:
            self.opacify_sid = \
                gobject.timeout_add(100, self.__opacify)

    def do_leave_notify_event(self, event):
        # In compiz there is a enter and a leave
        # event before a press event.
        # Keep that in mind when coding this def!
        CairoButton.do_leave_notify_event(self, event)
        self.pressed = False
        if self.globals.settings["opacify"]:
            self.deopacify_sid = \
                            gobject.timeout_add(200, self.__deopacify)

    def do_button_press_event(self,event):
        # In compiz there is a enter and a leave event before
        # a press event.
        # self.pressed is used to stop functions started with
        # gobject.timeout_add from self.__on_mouse_enter
        # or self.__on_mouse_leave.
        CairoButton.do_button_press_event(self, event)
        self.pressed = True
        self.press_sid = gobject.timeout_add(600, self.__set_pressed_false)

    def __set_pressed_false(self):
        # Helper function for __on_press_event.
        self.pressed = False
        self.press_sid = None
        return False

    def do_scroll_event(self, event):
        window = self.window_r()
        if self.globals.settings["opacify"]:
            window.deopacify()
        if not event.direction in (gtk.gdk.SCROLL_UP, gtk.gdk.SCROLL_DOWN):
            return
        direction = {gtk.gdk.SCROLL_UP: "scroll_up",
                     gtk.gdk.SCROLL_DOWN: "scroll_down"}[event.direction]
        action = self.globals.settings["windowbutton_%s"%direction]
        window.action_function_dict[action](window, self, event)
        if self.globals.settings["windowbutton_close_popup_on_%s"%direction]:
            self.group_r().popup.hide()

    def do_clicked(self, event):
        window = self.window_r()
        if self.globals.settings["opacify"]:
            window.deopacify()

        if not event.button in (1, 2, 3):
            return
        button = {1:"left", 2: "middle", 3: "right"}[event.button]
        if event.state & gtk.gdk.SHIFT_MASK:
            mod = "shift_and_"
        else:
            mod = ""
        action_str = "windowbutton_%s%s_click_action"%(mod, button)
        action = self.globals.settings[action_str]
        window.action_function_dict[action](window, self, event)

        popup_close = "windowbutton_close_popup_on_%s%s_click"%(mod, button)
        if self.globals.settings[popup_close]:
            self.group_r().popup.hide()

    def __on_close_button_clicked(self, *args):
        window = self.window_r()
        if self.globals.settings["opacify"]:
            window.deopacify()
        window.action_close_window()

    def __on_close_button_leave(self, widget, event):
        if not self.pointer_is_inside():
            self.do_leave_notify_event(event)

    #### D'n'D
    def do_drag_motion(self, drag_context, x, y, t):
        if not self.drag_entered:
            self.group_r().popup.expose()
            self.drag_entered = True
            self.dnd_select_window = \
                gobject.timeout_add(600, self.window_r().action_select_window)
        drag_context.drag_status(gtk.gdk.ACTION_PRIVATE, t)
        return True

    def do_drag_leave(self, drag_context, t):
        self.drag_entered = False
        gobject.source_remove(self.dnd_select_window)
        self.group_r().popup.expose()
        self.group_r().popup.hide_if_not_hovered()

    #### Opacify
    def __opacify(self):
        window = self.window_r()
        if window.wnck.is_minimized():
            return False
        # if self.pressed is true, opacity_request is called by an
        # wrongly sent out enter_notification_event sent after a
        # press (because of a bug in compiz).
        if self.pressed:
            self.pressed = False
            return False
        # Check if mouse cursor still is over the window button.
        if self.pointer_is_inside():
            window.opacify()
            # Just for safety in case no leave-signal is sent
            self.deopacify_sid = \
                            gobject.timeout_add(500, self.__deopacify)
        return False

    def __deopacify(self):
        window = self.window_r()
        # Make sure that mouse cursor really has left the window button.
        b_m_x,b_m_y = self.get_pointer()
        b_r = self.get_allocation()
        if b_m_x >= 0 and b_m_x < b_r.width \
        and b_m_y >= 0 and b_m_y < b_r.height:
            return True
        # Wait before deopacifying in case a new windowbutton
        # should call opacify, to avoid flickering
        window.deopacify_sid = gobject.timeout_add(150, window.deopacify)
        return False

    #### Menu functions
    def show_menu(self, event):
        window = self.window_r()
        #Creates a popup menu
        menu = gtk.Menu()
        menu.connect("selection-done", self.__menu_closed)
        #(Un)Minimize
        minimize_item = None
        if window.wnck.get_actions() & WNCK_WINDOW_ACTION_MINIMIZE \
        and not window.wnck.is_minimized():
            minimize_item = gtk.MenuItem(_("_Minimize"))
        elif window.wnck.get_actions() & WNCK_WINDOW_ACTION_UNMINIMIZE \
        and window.wnck.is_minimized():
            minimize_item = gtk.MenuItem(_("Un_minimize"))
        if minimize_item:
            menu.append(minimize_item)
            minimize_item.connect("activate", window.action_minimize_window)
            minimize_item.show()
        # (Un)Maximize
        maximize_item = None
        if not window.wnck.is_maximized() \
        and window.wnck.get_actions() & WNCK_WINDOW_ACTION_MAXIMIZE:
            maximize_item = gtk.MenuItem(_("Ma_ximize"))
        elif window.wnck.is_maximized() \
        and window.wnck.get_actions() & WNCK_WINDOW_ACTION_UNMINIMIZE:
            maximize_item = gtk.MenuItem(_("Unma_ximize"))
        if maximize_item:
            menu.append(maximize_item)
            maximize_item.connect("activate", window.action_maximize_window)
            maximize_item.show()
        # Close
        close_item = gtk.MenuItem(_("_Close"))
        menu.append(close_item)
        close_item.connect("activate", window.action_close_window)
        close_item.show()
        menu.popup(None, None, None, event.button, event.time)
        self.globals.gtkmenu_showing = True

    def __menu_closed(self, menushell):
        self.globals.gtkmenu_showing = False
        self.group_r().popup.hide()
        menushell.destroy()