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()
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
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()