Example #1
0
def window_grab_and_map(window, mask):
    """Returns a list of devices that have a grab or an empty list if
    something failed.

    If somethings failed the window will be hidden.
    """

    device = Gtk.get_current_event_device()
    event_time = Gtk.get_current_event_time()
    if not device:
        return []

    # On wayland we need to grab before mapping and on X11 and everywhere else
    # we can grab after we are mapped
    if not is_wayland():
        window.show()
    else:
        window.realize()

    Gtk.device_grab_add(window, device, True)

    status = device.grab(
        window.get_window(), Gdk.GrabOwnership.WINDOW, True,
        mask, None, event_time)

    if status != Gdk.GrabStatus.SUCCESS:
        Gtk.device_grab_remove(window, device)
        window.hide()
        return []

    associated_device = device.get_associated_device()
    if associated_device is None:
        if is_wayland():
            window.show()
        return [device]

    Gtk.device_grab_add(window, associated_device, True)

    status = associated_device.grab(
        window.get_window(), Gdk.GrabOwnership.WINDOW, True,
        mask, None, event_time)

    if status != Gdk.GrabStatus.SUCCESS:
        Gtk.device_grab_remove(window, associated_device)
        Gtk.device_grab_remove(window, device)
        device.ungrab(event_time)
        window.hide()
        return []

    if is_wayland():
        window.show()

    return [device, associated_device]
Example #2
0
def window_grab_and_map(window, mask):
    """Returns a list of devices that have a grab or an empty list if
    something failed.

    If somethings failed the window will be hidden.
    """

    device = Gtk.get_current_event_device()
    event_time = Gtk.get_current_event_time()
    if not device:
        return []

    # On wayland we need to grab before mapping and on X11 and everywhere else
    # we can grab after we are mapped
    if not is_wayland():
        window.show()
    else:
        window.realize()

    Gtk.device_grab_add(window, device, True)

    status = device.grab(
        window.get_window(), Gdk.GrabOwnership.WINDOW, True,
        mask, None, event_time)

    if status != Gdk.GrabStatus.SUCCESS:
        Gtk.device_grab_remove(window, device)
        window.hide()
        return []

    associated_device = device.get_associated_device()
    if associated_device is None:
        if is_wayland():
            window.show()
        return [device]

    Gtk.device_grab_add(window, associated_device, True)

    status = associated_device.grab(
        window.get_window(), Gdk.GrabOwnership.WINDOW, True,
        mask, None, event_time)

    if status != Gdk.GrabStatus.SUCCESS:
        Gtk.device_grab_remove(window, associated_device)
        Gtk.device_grab_remove(window, device)
        device.ungrab(event_time)
        window.hide()
        return []

    if is_wayland():
        window.show()

    return [device, associated_device]
    def __event(self, event):
        if not self.__view:
            return True

        # hack: present the main window on key press
        if event.type == Gdk.EventType.BUTTON_PRESS:
            # hack: present is overridden to present all windows.
            # bypass to only select one
            if not is_wayland():  # present duplicates windows in weston
                Gtk.Window.present(get_top_parent(self.__view))

        type_ = event.type
        real_event = None
        if type_ == Gdk.EventType.BUTTON_PRESS:
            real_event = event.button
        elif type_ == Gdk.EventType.BUTTON_RELEASE:
            real_event = event.button
        elif type_ == Gdk.EventType.MOTION_NOTIFY:
            real_event = event.motion

        if real_event:
            real_event.x += self.__dx
            real_event.y += self.__dy

        # modifying event.window is a necessary evil, made okay because
        # nobody else should tie to any TreeViewHints events ever.
        event.any.window = self.__view.get_bin_window()

        event.put()

        return True
Example #4
0
    def __calculate_screen_width(self, parent):
        if qltk.is_wayland():
            # no screen size with wayland, the parent window is
            # the next best thing..
            width, height = parent.get_size()
            width = int(width / 1.1)
            height = int(height / 1.1)
            return (width, height)
        else:
            win = parent.get_window()
            if win:
                if qltk.gtk_version[:2] >= (3, 22):
                    disp = Gdk.Display.get_default()
                    mon = disp.get_monitor_at_window(win)
                    rect = mon.get_geometry()
                else:
                    # The result should be the same as above, just using
                    # deprecated methods instead
                    screen = Gdk.Screen.get_default()
                    mon_num = screen.get_monitor_at_window(win)
                    rect = screen.get_monitor_geometry(mon_num)
                width = int(rect.width / 1.8)
                height = int(rect.height / 1.8)
                return (width, height)

            width = int(Gdk.Screen.width() / 1.8)
            height = int(Gdk.Screen.height() / 1.8)
            return (width, height)
Example #5
0
    def __calculate_screen_width(self, parent, scale=0.5):
        if qltk.is_wayland():
            # no screen size with wayland, the parent window is
            # the next best thing..
            width, height = parent.get_size()
            width = int(width / 1.1)
            height = int(height / 1.1)
            return (width, height)
        else:
            win = parent.get_window()
            if win:
                if qltk.gtk_version[:2] >= (3, 22):
                    disp = Gdk.Display.get_default()
                    mon = disp.get_monitor_at_window(win)
                    rect = mon.get_geometry()
                else:
                    # The result should be the same as above, just using
                    # deprecated methods instead
                    screen = Gdk.Screen.get_default()
                    mon_num = screen.get_monitor_at_window(win)
                    rect = screen.get_monitor_geometry(mon_num)
                width = int(rect.width * scale)
                height = int(rect.height * scale)
                return (width, height)

            width = int(Gdk.Screen.width() * scale)
            height = int(Gdk.Screen.height() * scale)
            return (width, height)
Example #6
0
    def __event(self, event):
        if not self.__view:
            return True

        # hack: present the main window on key press
        if event.type == Gdk.EventType.BUTTON_PRESS:
            # hack: present is overridden to present all windows.
            # bypass to only select one
            if not is_wayland():  # present duplicates windows in weston
                Gtk.Window.present(get_top_parent(self.__view))

        def translate_enter_leave_event(event):
            # enter/leave events have different x/y values as motion events
            # so it makes sense to push them to the underlying view as
            # additional motion events.
            # Warning: this may result in motion events outside of the
            # view window.. ?
            new_event = Gdk.Event.new(Gdk.EventType.MOTION_NOTIFY)
            struct = new_event.motion
            for attr in ["x", "y", "x_root", "y_root", "time", "window",
                         "state", "send_event"]:
                setattr(struct, attr, getattr(event.crossing, attr))
            device = Gtk.get_current_event_device()
            if device is not None:
                struct.set_device(device)
            return new_event

        # FIXME: We should translate motion events on the tooltip
        # to crossing events for the underlying view.
        # (I think, no tested) Currently the hover scrollbar stays visible
        # if the mouse leaves the view through the tooltip without the
        # knowledge of the view.

        type_ = event.type
        real_event = None
        if type_ == Gdk.EventType.BUTTON_PRESS:
            real_event = event.button
        elif type_ == Gdk.EventType.BUTTON_RELEASE:
            real_event = event.button
        elif type_ == Gdk.EventType.MOTION_NOTIFY:
            real_event = event.motion
        elif type_ == Gdk.EventType.ENTER_NOTIFY:
            event = translate_enter_leave_event(event)
            real_event = event.motion
        elif type_ == Gdk.EventType.LEAVE_NOTIFY:
            event = translate_enter_leave_event(event)
            real_event = event.motion

        if real_event:
            real_event.x += self.__dx
            real_event.y += self.__dy

        # modifying event.window is a necessary evil, made okay because
        # nobody else should tie to any TreeViewHints events ever.
        event.any.window = self.__view.get_bin_window()

        Gtk.main_do_event(event)

        return True
Example #7
0
def get_indicator_impl():
    """Returns a BaseIndicator implementation depending on the environ"""

    try:
        from .appindicator import AppIndicator
    except ImportError:
        # no indicator, fall back
        return SystemTray

    if is_unity() or is_wayland() or is_plasma():
        return AppIndicator
    return SystemTray
Example #8
0
    def __event(self, event):
        if not self.__view:
            return True

        # hack: present the main window on key press
        if event.type == Gdk.EventType.BUTTON_PRESS:
            # hack: present is overridden to present all windows.
            # bypass to only select one
            if not is_wayland():  # present duplicates windows in weston
                Gtk.Window.present(get_top_parent(self.__view))

        def translate_enter_leave_event(event):
            # enter/leave events have different x/y values as motion events
            # so it makes sense to push them to the underlying view as
            # additional motion events.
            # Warning: this may result in motion events outside of the
            # view window.. ?
            new_event = Gdk.Event()
            new_event.type = Gdk.EventType.MOTION_NOTIFY
            struct = new_event.motion
            for attr in ["x", "y", "x_root", "y_root", "time", "window",
                         "state", "send_event"]:
                setattr(struct, attr, getattr(event.crossing, attr))
            struct.device = Gtk.get_current_event_device()
            return new_event

        type_ = event.type
        real_event = None
        if type_ == Gdk.EventType.BUTTON_PRESS:
            real_event = event.button
        elif type_ == Gdk.EventType.BUTTON_RELEASE:
            real_event = event.button
        elif type_ == Gdk.EventType.MOTION_NOTIFY:
            real_event = event.motion
        elif type_ == Gdk.EventType.ENTER_NOTIFY:
            event = translate_enter_leave_event(event)
            real_event = event.motion
        elif type_ == Gdk.EventType.LEAVE_NOTIFY:
            event = translate_enter_leave_event(event)
            real_event = event.motion

        if real_event:
            real_event.x += self.__dx
            real_event.y += self.__dy

        # modifying event.window is a necessary evil, made okay because
        # nobody else should tie to any TreeViewHints events ever.
        event.any.window = self.__view.get_bin_window()

        Gtk.main_do_event(event)

        return True
Example #9
0
 def __init__(self, *args, **kwargs):
     self._header_bar = None
     dialog = kwargs.pop("dialog", True)
     super().__init__(*args, **kwargs)
     type(self).windows.append(self)
     if dialog:
         # Modal is the only way to center the window on the parent
         # with wayland atm
         if is_wayland():
             self.set_modal(True)
         self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
     self.set_destroy_with_parent(True)
     self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
     connect_obj(self, 'destroy', type(self).windows.remove, self)
     self.connect('key-press-event', self._on_key_press)
Example #10
0
    def __init__(self, title, fileobj, parent):
        super(BigCenteredImage, self).__init__(type=Gtk.WindowType.POPUP)
        self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP)

        assert parent
        parent = qltk.get_top_parent(parent)
        self.set_transient_for(parent)

        if qltk.is_wayland():
            # no screen size with wayland, the parent window is
            # the next best thing..
            width, height = parent.get_size()
            width = int(width / 1.1)
            height = int(height / 1.1)
        else:
            width = int(Gdk.Screen.width() / 1.8)
            height = int(Gdk.Screen.height() / 1.8)

        self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)

        scale_factor = self.get_scale_factor()

        pixbuf = None
        try:
            pixbuf = pixbuf_from_file(fileobj, (width, height), scale_factor)
        except GLib.GError:
            pass

        # failed to load, abort
        if not pixbuf:
            self.destroy()
            return

        image = Gtk.Image()
        image.set_from_surface(get_surface_for_pixbuf(self, pixbuf))

        event_box = Gtk.EventBox()
        event_box.add(image)

        frame = Gtk.Frame()
        frame.set_shadow_type(Gtk.ShadowType.OUT)
        frame.add(event_box)

        self.add(frame)

        event_box.connect('button-press-event', self.__destroy)
        event_box.connect('key-press-event', self.__destroy)
        self.get_child().show_all()
Example #11
0
    def __init__(self, title, fileobj, parent):
        super(BigCenteredImage, self).__init__(type=Gtk.WindowType.POPUP)
        self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP)

        assert parent
        parent = qltk.get_top_parent(parent)
        self.set_transient_for(parent)

        if qltk.is_wayland():
            # no screen size with wayland, the parent window is
            # the next best thing..
            width, height = parent.get_size()
            width = int(width / 1.1)
            height = int(height / 1.1)
        else:
            width = int(Gdk.Screen.width() / 1.75)
            height = int(Gdk.Screen.height() / 1.75)

        self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)

        scale_factor = get_scale_factor(self)

        pixbuf = None
        try:
            pixbuf = pixbuf_from_file(fileobj, (width, height), scale_factor)
        except GLib.GError:
            pass

        # failed to load, abort
        if not pixbuf:
            self.destroy()
            return

        image = Gtk.Image()
        set_image_from_pbosf(image, get_pbosf_for_pixbuf(self, pixbuf))

        event_box = Gtk.EventBox()
        event_box.add(image)

        frame = Gtk.Frame()
        frame.set_shadow_type(Gtk.ShadowType.OUT)
        frame.add(event_box)

        self.add(frame)

        event_box.connect('button-press-event', self.__destroy)
        event_box.connect('key-press-event', self.__destroy)
        self.get_child().show_all()
Example #12
0
def get_indicator_impl():
    """Returns a BaseIndicator implementation depending on the environ"""

    use_app_indicator = (is_unity() or is_wayland() or is_kde())

    print_d("use app indicator: %s" % use_app_indicator)
    if not use_app_indicator:
        return SystemTray
    else:
        try:
            from .appindicator import AppIndicator
        except ImportError:
            print_w("importing app indicator failed")
            print_exc()
            # no indicator, fall back
            return SystemTray
        else:
            return AppIndicator
Example #13
0
def get_indicator_impl():
    """Returns a BaseIndicator implementation depending on the environ"""

    use_app_indicator = (is_unity() or is_wayland() or is_kde())

    print_d("use app indicator: %s" % use_app_indicator)
    if not use_app_indicator:
        return SystemTray
    else:
        try:
            from .appindicator import AppIndicator
        except ImportError:
            print_w("importing app indicator failed")
            print_exc()
            # no indicator, fall back
            return SystemTray
        else:
            return AppIndicator
Example #14
0
    def __popup_position(self, menu, *args):
        path, col = self.get_cursor()

        # get a rectangle describing the cell render area (assume 3 px pad)
        rect = self.get_cell_area(path, col)
        padding = 3
        rect.x += padding
        rect.width = max(rect.width - padding * 2, 0)
        rect.y += padding
        rect.height = max(rect.height - padding * 2, 0)

        x, y = self.get_window().get_origin()[1:]
        x, y = self.convert_bin_window_to_widget_coords(x + rect.x, y + rect.y)

        menu.realize()
        ma = menu.get_allocation()
        menu_y = rect.height + y
        if self.get_direction() == Gtk.TextDirection.LTR:
            menu_x = x
        else:
            menu_x = x - ma.width + rect.width

        # on X11/win32 we can use the screen size
        if not is_wayland():

            # fit menu to screen, aligned per text direction
            screen = self.get_screen()
            screen_width = screen.get_width()
            screen_height = screen.get_height()

            # show above row if no space below and enough above
            if menu_y + ma.height > screen_height and y - ma.height > 0:
                menu_y = y - ma.height

            # make sure it's not outside of the screen
            if self.get_direction() == Gtk.TextDirection.LTR:
                menu_x = max(0, min(menu_x, screen_width - ma.width))
            else:
                menu_x = min(max(0, menu_x), screen_width)

        return (menu_x, menu_y, True)  # x, y, move_within_screen
    def __motion(self, view, event):
        label = self.__label
        clabel = self.__clabel

        # trigger over row area, not column headers
        if event.window is not view.get_bin_window():
            self.__undisplay()
            return False

        # hide if any modifier is active
        if event.get_state() & Gtk.accelerator_get_default_mod_mask():
            self.__undisplay()
            return False

        # get the cell at the mouse position
        x, y = map(int, [event.x, event.y])
        try:
            path, col, cellx, celly = view.get_path_at_pos(x, y)
        except TypeError:
            # no hints where no rows exist
            self.__undisplay()
            return False

        col_area = view.get_cell_area(path, col)
        # make sure we are on the same level
        if x < col_area.x:
            self.__undisplay()
            return False

        # hide for partial hidden rows at the bottom
        if y > view.get_visible_rect().height:
            self.__undisplay()
            return False

        # get the renderer at the mouse position and get the xpos/width
        renderers = col.get_cells()
        pos = sorted(zip(map(col.cell_get_position, renderers), renderers))
        pos = filter(lambda ((x, w), r): x < cellx, pos)
        if not pos:
            self.__undisplay()
            return False
        (render_offset, render_width), renderer = pos[-1]

        if self.__current_renderer == renderer and self.__current_path == path:
            return False

        # only ellipsized text renderers
        if not isinstance(renderer, Gtk.CellRendererText):
            self.__undisplay()
            return False

        ellipsize = renderer.get_property('ellipsize')
        if ellipsize == Pango.EllipsizeMode.END:
            expand_left = False
        elif ellipsize == Pango.EllipsizeMode.MIDDLE:
            # depending on where the cursor is
            expand_left = x > col_area.x + render_offset + render_width / 2
        elif ellipsize == Pango.EllipsizeMode.START:
            expand_left = True
        else:
            self.__undisplay()
            return False

        # don't display if the renderer is in editing mode
        if renderer.props.editing:
            self.__undisplay()
            return False

        # set the cell renderer attributes for the active cell
        model = view.get_model()
        col.cell_set_cell_data(model, model.get_iter(path), False, False)

        # the markup attribute is write only, so the markup text needs
        # to be saved on the python side, so we can copy it to the label
        markup = getattr(renderer, "markup", None)
        if markup is None:
            text = renderer.get_property('text')
            set_text = lambda l: l.set_text(text)
        else:
            # markup can also be column index
            if isinstance(markup, int):
                markup = model[path][markup]
            set_text = lambda l: l.set_markup(markup)

        # Use the renderer padding as label padding so the text offset matches
        render_xpad = renderer.get_property("xpad")
        label.set_padding(render_xpad, 0)
        set_text(clabel)
        clabel.set_padding(render_xpad, 0)
        label_width = clabel.get_layout().get_pixel_size()[0]
        label_width += clabel.get_layout_offsets()[0] or 0
        # layout offset includes the left padding, so add one more
        label_width += render_xpad

        # CellRenderer width is too large if it's the last one in a column.
        # Use cell_area width as a maximum and limit render_width.
        max_width = col_area.width
        if render_width + render_offset > max_width:
            render_width = max_width - render_offset

        # don't display if it doesn't need expansion
        if label_width < render_width:
            self.__undisplay()
            return False

        dummy, ox, oy = view.get_window().get_origin()

        # save for adjusting passthrough events
        self.__dx, self.__dy = col_area.x + render_offset, col_area.y
        if expand_left:
            # shift to the left
            # FIXME: ellipsize start produces a space at the end depending
            # on the text. I don't know how to compute it..
            self.__dx -= (label_width - render_width)

        # final window coordinates/size
        x = ox + self.__dx
        y = oy + self.__dy
        x, y = view.convert_bin_window_to_widget_coords(x, y)

        w = label_width
        h = col_area.height

        if not is_wayland():
            # clip if it's bigger than the screen
            screen_border = 5  # leave some space

            if not expand_left:
                space_right = Gdk.Screen.width() - x - w - screen_border

                if space_right < 0:
                    w += space_right
                    label.set_ellipsize(Pango.EllipsizeMode.END)
                else:
                    label.set_ellipsize(Pango.EllipsizeMode.NONE)
            else:
                space_left = x - screen_border
                if space_left < 0:
                    x -= space_left
                    self.__dx -= space_left
                    w += space_left
                    label.set_ellipsize(Pango.EllipsizeMode.START)
                else:
                    label.set_ellipsize(Pango.EllipsizeMode.NONE)
        else:
            label.set_ellipsize(Pango.EllipsizeMode.NONE)

        # Don't show if the resulting tooltip would be smaller
        # than the visible area (if not all is on the display)
        if w < render_width:
            self.__undisplay()
            return False

        self.__view = view
        self.__current_renderer = renderer
        self.__edit_id = renderer.connect('editing-started', self.__undisplay)
        self.__current_path = path
        self.__current_col = col

        if self.__hide_id:
            GLib.source_remove(self.__hide_id)
            self.__hide_id = None

        self.set_transient_for(get_top_parent(view))
        set_text(label)
        self.set_size_request(w, h)

        window = self.get_window()
        if self.get_visible() and window:
            window.move_resize(x, y, w, h)
        else:
            self.move(x, y)
            self.resize(w, h)
            self.show()

        return False
Example #16
0
    def __motion(self, view, event):
        label = self.__label
        clabel = self.__clabel

        # trigger over row area, not column headers
        if event.window is not view.get_bin_window():
            self.__undisplay()
            return False

        x, y = map(int, [event.x, event.y])

        # For gtk3.16 overlay scrollbars: if our event x coordinate
        # is contained in the scrollbar, hide the tooltip. Unlike other
        # hiding events we don't want to send a leave event to the scrolled
        # window so the overlay scrollbar does't hide and can be interacted
        # with.
        parent = view.get_parent()
        # We only need to check if the tooltip is there since events
        # on the scrollbars don't get forwarded to us anyway.
        if self.__view and parent and isinstance(parent, Gtk.ScrolledWindow):
            vscrollbar = parent.get_vscrollbar()
            res = vscrollbar.translate_coordinates(view, 0, 0)
            if res is not None:
                x_offset = res[0]
                vbar_width = vscrollbar.get_allocation().width
                if x_offset <= x <= x_offset + vbar_width:
                    self.__undisplay(send_leave=False)
                    return False

        # hide if any modifier is active.
        mask = Gtk.accelerator_get_default_mod_mask()
        mask = Gdk.Keymap.get_default().map_virtual_modifiers(mask)[1]
        if event.get_state() & mask:
            self.__undisplay()
            return False

        # get the cell at the mouse position
        try:
            path, col, cellx, celly = view.get_path_at_pos(x, y)
        except TypeError:
            # no hints where no rows exist
            self.__undisplay()
            return False

        col_area = view.get_cell_area(path, col)
        # make sure we are on the same level
        if x < col_area.x:
            self.__undisplay()
            return False

        # hide for partial hidden rows at the bottom
        if y > view.get_visible_rect().height:
            self.__undisplay()
            return False

        # get the renderer at the mouse position and get the xpos/width
        renderers = col.get_cells()
        pos = sorted(zip(map(col.cell_get_position, renderers), renderers))
        pos = list(filter(lambda p: p[0][0] < cellx, pos))
        if not pos:
            self.__undisplay()
            return False
        (render_offset, render_width), renderer = pos[-1]

        if self.__current_renderer == renderer and self.__current_path == path:
            return False

        # only ellipsized text renderers
        if not isinstance(renderer, Gtk.CellRendererText):
            self.__undisplay()
            return False

        ellipsize = renderer.get_property('ellipsize')
        if ellipsize == Pango.EllipsizeMode.END:
            expand_left = False
        elif ellipsize == Pango.EllipsizeMode.MIDDLE:
            # depending on where the cursor is
            expand_left = x > col_area.x + render_offset + render_width / 2
        elif ellipsize == Pango.EllipsizeMode.START:
            expand_left = True
        else:
            self.__undisplay()
            return False

        # don't display if the renderer is in editing mode
        if renderer.props.editing:
            self.__undisplay()
            return False

        # set the cell renderer attributes for the active cell
        model = view.get_model()
        col.cell_set_cell_data(model, model.get_iter(path), False, False)

        # the markup attribute is write only, so the markup text needs
        # to be saved on the python side, so we can copy it to the label
        markup = getattr(renderer, "markup", None)
        if markup is None:
            text = renderer.get_property('text')
            set_text = lambda l: l.set_text(text)
        else:
            # markup can also be column index
            if isinstance(markup, int):
                markup = model[path][markup]
            set_text = lambda l: l.set_markup(markup)

        # Use the renderer padding as label padding so the text offset matches
        render_xpad = renderer.get_property("xpad")

        # the renderer xpad is not enough for the tooltip, especially with
        # rounded corners the label gets nearly clipped.
        MIN_HINT_X_PAD = 4
        if render_xpad < MIN_HINT_X_PAD:
            extra_xpad = MIN_HINT_X_PAD - render_xpad
        else:
            extra_xpad = 0

        label.set_padding(render_xpad + extra_xpad, 0)
        set_text(clabel)
        clabel.set_padding(render_xpad, 0)
        label_width = clabel.get_layout().get_pixel_size()[0]
        label_width += clabel.get_layout_offsets()[0] or 0
        # layout offset includes the left padding, so add one more
        label_width += render_xpad

        # CellRenderer width is too large if it's the last one in a column.
        # Use cell_area width as a maximum and limit render_width.
        max_width = col_area.width
        if render_width + render_offset > max_width:
            render_width = max_width - render_offset

        # don't display if it doesn't need expansion
        if label_width < render_width:
            self.__undisplay()
            return False

        dummy, ox, oy = view.get_window().get_origin()
        bg_area = view.get_background_area(path, None)

        # save for adjusting passthrough events
        self.__dx, self.__dy = col_area.x + render_offset, bg_area.y
        self.__dx -= extra_xpad
        if expand_left:
            # shift to the left
            # FIXME: ellipsize start produces a space at the end depending
            # on the text. I don't know how to compute it..
            self.__dx -= (label_width - render_width)

        # final window coordinates/size
        x = ox + self.__dx
        y = oy + self.__dy
        x, y = view.convert_bin_window_to_widget_coords(x, y)

        w = label_width + extra_xpad * 2
        h = bg_area.height

        if not is_wayland():
            # clip if it's bigger than the monitor
            mon_border = 5  # leave some space
            screen = Gdk.Screen.get_default()
            if not expand_left:
                monitor_idx = screen.get_monitor_at_point(x, y)
                mon = screen.get_monitor_geometry(monitor_idx)
                space_right = mon.x + mon.width - x - w - mon_border

                if space_right < 0:
                    w += space_right
                    label.set_ellipsize(Pango.EllipsizeMode.END)
                else:
                    label.set_ellipsize(Pango.EllipsizeMode.NONE)
            else:
                monitor_idx = screen.get_monitor_at_point(x + w, y)
                mon = screen.get_monitor_geometry(monitor_idx)
                space_left = x - mon.x - mon_border

                if space_left < 0:
                    x -= space_left
                    self.__dx -= space_left
                    w += space_left
                    label.set_ellipsize(Pango.EllipsizeMode.START)
                else:
                    label.set_ellipsize(Pango.EllipsizeMode.NONE)
        else:
            label.set_ellipsize(Pango.EllipsizeMode.NONE)

        # Don't show if the resulting tooltip would be smaller
        # than the visible area (if not all is on the display)
        if w < render_width:
            self.__undisplay()
            return False

        self.__view = view
        self.__current_renderer = renderer
        self.__edit_id = renderer.connect('editing-started', self.__undisplay)
        self.__current_path = path
        self.__current_col = col

        if self.__hide_id:
            GLib.source_remove(self.__hide_id)
            self.__hide_id = None

        self.set_transient_for(get_top_parent(view))
        set_text(label)
        self.set_size_request(w, h)

        window = self.get_window()
        if self.get_visible() and window:
            window.move_resize(x, y, w, h)
        else:
            self.move(x, y)
            self.resize(w, h)
            self.show()

        return False
Example #17
0
 def __restore_window_state(self):
     if not is_wayland():
         self.__restore_state()
         self.__restore_position()
     self.__restore_size()
Example #18
0
    def __init__(self, title, fileobj, parent):
        super(BigCenteredImage, self).__init__(type=Gtk.WindowType.POPUP)
        self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP)

        assert parent
        parent = qltk.get_top_parent(parent)
        self.set_transient_for(parent)

        if qltk.is_wayland():
            # no screen size with wayland, the parent window is
            # the next best thing..
            width, height = parent.get_size()
            width = int(width / 1.1)
            height = int(height / 1.1)
        else:
            win = parent.get_window()
            if win:
                if qltk.gtk_version[:2] >= (3, 22):
                    disp = Gdk.Display.get_default()
                    mon = disp.get_monitor_at_window(win)
                    rect = mon.get_geometry()
                else:
                    # The result should be the same as above, just using
                    # deprecated methods instead
                    screen = Gdk.Screen.get_default()
                    mon_num = screen.get_monitor_at_window(win)
                    rect = screen.get_monitor_geometry(mon_num)
                width = int(rect.width / 1.8)
                height = int(rect.height / 1.8)
            else:
                width = int(Gdk.Screen.width() / 1.8)
                height = int(Gdk.Screen.height() / 1.8)

        self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)

        scale_factor = self.get_scale_factor()

        pixbuf = None
        try:
            pixbuf = pixbuf_from_file(fileobj, (width, height), scale_factor)
        except GLib.GError:
            pass

        # failed to load, abort
        if not pixbuf:
            self.destroy()
            return

        image = Gtk.Image()
        image.set_from_surface(get_surface_for_pixbuf(self, pixbuf))

        event_box = Gtk.EventBox()
        event_box.add(image)

        frame = Gtk.Frame()
        frame.set_shadow_type(Gtk.ShadowType.OUT)
        frame.add(event_box)

        self.add(frame)

        event_box.connect('button-press-event', self.__destroy)
        event_box.connect('key-press-event', self.__destroy)
        self.get_child().show_all()
Example #19
0
from gi.repository import Gtk, Gdk

from tests import TestCase, skipIf
from quodlibet.qltk.getstring import GetStringDialog
from quodlibet.qltk import is_wayland


class _ClipboadTestClass(GetStringDialog):
    _OK = True

    def _verify_clipboard(self, text):
        if self._OK:
            return text


@skipIf(is_wayland(), "blocks under wayland for some reason")
class TGetStringDialog(TestCase):
    def setUp(self):
        parent = Gtk.Window()
        self.gsd1 = GetStringDialog(parent, "title", "enter a string")
        self.gsd2 = _ClipboadTestClass(parent, "title", "enter a string")

    def test_getstring(self):
        ret = self.gsd1.run(text="foobar", test=True)
        self.failUnlessEqual(ret, "foobar")

    def test_tooltip(self):
        foo = GetStringDialog(Gtk.Window(), "title", "", tooltip="foo bar")
        self.failUnlessEqual(foo._val.get_tooltip_text(), "foo bar")

    def test_clipboard(self):
from gi.repository import Gtk, Gdk

from tests import TestCase, skipIf
from quodlibet.qltk.getstring import GetStringDialog
from quodlibet.qltk import is_wayland


class _ClipboadTestClass(GetStringDialog):
    _OK = True

    def _verify_clipboard(self, text):
        if self._OK:
            return text


@skipIf(is_wayland(), "blocks under wayland for some reason")
class TGetStringDialog(TestCase):
    def setUp(self):
        parent = Gtk.Window()
        self.gsd1 = GetStringDialog(parent, "title", "enter a string")
        self.gsd2 = _ClipboadTestClass(parent, "title", "enter a string")

    def test_getstring(self):
        ret = self.gsd1.run(text="foobar", test=True)
        self.failUnlessEqual(ret, "foobar")

    def test_tooltip(self):
        foo = GetStringDialog(Gtk.Window(), "title", "", tooltip="foo bar")
        self.failUnlessEqual(foo._val.get_tooltip_text(), "foo bar")

    def test_clipboard(self):
Example #21
0
    def __init__(self, title, fileobj, parent):
        super(BigCenteredImage, self).__init__(type=Gtk.WindowType.POPUP)
        self.set_type_hint(Gdk.WindowTypeHint.TOOLTIP)

        assert parent
        parent = qltk.get_top_parent(parent)
        self.set_transient_for(parent)

        if qltk.is_wayland():
            # no screen size with wayland, the parent window is
            # the next best thing..
            width, height = parent.get_size()
            width = int(width / 1.1)
            height = int(height / 1.1)
        else:
            win = parent.get_window()
            if win:
                if qltk.gtk_version[:2] >= (3, 22):
                    disp = Gdk.Display.get_default()
                    mon = disp.get_monitor_at_window(win)
                    rect = mon.get_geometry()
                else:
                    # The result should be the same as above, just using
                    # deprecated methods instead
                    screen = Gdk.Screen.get_default()
                    mon_num = screen.get_monitor_at_window(win)
                    rect = screen.get_monitor_geometry(mon_num)
                width = int(rect.width / 1.8)
                height = int(rect.height / 1.8)
            else:
                width = int(Gdk.Screen.width() / 1.8)
                height = int(Gdk.Screen.height() / 1.8)

        self.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)

        scale_factor = self.get_scale_factor()

        pixbuf = None
        try:
            pixbuf = pixbuf_from_file(fileobj, (width, height), scale_factor)
        except GLib.GError:
            pass

        # failed to load, abort
        if not pixbuf:
            self.destroy()
            return

        image = Gtk.Image()
        image.set_from_surface(get_surface_for_pixbuf(self, pixbuf))

        event_box = Gtk.EventBox()
        event_box.add(image)

        frame = Gtk.Frame()
        frame.set_shadow_type(Gtk.ShadowType.OUT)
        frame.add(event_box)

        self.add(frame)

        event_box.connect('button-press-event', self.__destroy)
        event_box.connect('key-press-event', self.__destroy)
        self.get_child().show_all()
Example #22
0
 def __restore_window_state(self):
     if not is_wayland():
         self.__restore_state()
         self.__restore_position()
     self.__restore_size()
Example #23
0
    def test_none(self):
        self.failUnlessRaises(ValueError, self.Kind, [])

    def test_some(self):
        self.some.set_active(2)
        self.failUnlessEqual(self.some.tag, "foobar")

    def test_all(self):
        tags = list(USER_TAGS)
        tags.sort()
        for i, value in enumerate(tags):
            self.all.set_active(i)
            self.failUnlessEqual(self.all.tag, value)


@skipIf(is_wayland(), "crashes..")
class TTagsComboBox(TagsCombo):
    from quodlibet.qltk.tagscombobox import TagsComboBox as Kind
    Kind


@skipIf(is_wayland(), "crashes..")
class TTagsComboBoxEntry(TagsCombo):
    from quodlibet.qltk.tagscombobox import TagsComboBoxEntry as Kind
    Kind

    def test_custom(self):
        self.all.get_child().set_text("a new tag")
        self.failUnlessEqual(self.all.tag, "a new tag")