def _get_target_area_geometry(screen, mon_num):
    """Get a rect for putting windows in: normally based on monitor.

    :param Gdk.Screen screen: Target screen.
    :param int mon_num: Monitor number, e.g. that of the pointer.
    :returns: A hopefully usable target area.
    :rtype: lib.helpers.Rect

    This function operates like gdk_screen_get_monitor_geometry(), but
    falls back to the screen geometry for cases when that returns NULL.
    It also returns a type which has (around GTK 3.18.x) fewer weird
    typelib issues with construction or use.

    Ref: https://github.com/mypaint/mypaint/issues/424
    Ref: https://github.com/mypaint/mypaint/issues/437

    """
    geom = None
    if mon_num >= 0:
        geom = screen.get_monitor_geometry(mon_num)
    if geom is not None:
        geom = Rect.new_from_gdk_rectangle(geom)
    else:
        logger.warning("gdk_screen_get_monitor_geometry() returned NULL: "
                       "using screen size instead as a fallback.")
        geom = Rect(0, 0, screen.get_width(), screen.get_height())
    return geom
示例#2
0
 def tdw_allocation(self):
     if not self._alloc:
         self._alloc = Rect.new_from_gdk_rectangle(
             self.tdw.get_allocation())
     return self._alloc
示例#3
0
    def _recalculate_coordinates(self, redraw, *args):
        """Calculates geometric data that does not need updating every time"""
        # Skip calculations when the frame is not enabled (this is important
        # because otherwise all of this would be recalculated on moving,
        # scaling and rotating the canvas.
        if not (self.doc.model.frame_enabled or redraw):
            return
        tdw = self.doc.tdw
        # Canvas rectangle - regular and offset
        self._canvas_rect = Rect.new_from_gdk_rectangle(tdw.get_allocation())
        self._canvas_rect_offset = self._canvas_rect.expanded(
            self.OUTLINE_WIDTH * 4)
        # Frame corners in model coordinates
        x, y, w, h = tuple(self.doc.model.get_frame())
        corners = [(x, y), (x + w, y), (x + w, y + h), (x, y + h)]
        # Pixel-aligned frame corners in display space
        d_corners = [tdw.model_to_display(mx, my) for mx, my in corners]
        pxoffs = 0.5 if (self.OUTLINE_WIDTH % 2) else 0.0
        self._prev_display_corners = self._display_corners
        self._display_corners = tuple(
            (int(x) + pxoffs, int(y) + pxoffs) for x, y in d_corners)
        # Position of the button for disabling/deleting the frame
        # Placed near the center of the frame, clamped to the viewport,
        # with an offset so it does not cover visually small frames
        # (when the frame _is_ small, or when zoomed out).
        xs, ys = zip(*d_corners)
        r = gui.style.FLOATING_BUTTON_RADIUS
        tx, ty = self._canvas_rect.expanded(-2 * r).clamped_point(
            sum(xs) / 4.0,
            sum(ys) / 4.0)
        self._trash_btn_pos = tx, ty
        r += 6  # margin for drop shadows
        self._prev_disable_button_rectangle = self._disable_button_rectangle
        self._disable_button_rectangle = (tx - r, ty - r, r * 2, r * 2)
        # Corners
        self._zone_corners = []
        radius = gui.style.DRAGGABLE_POINT_HANDLE_SIZE
        canvas_limit = self._canvas_rect.expanded(radius)
        for i, (cx, cy) in enumerate(d_corners):
            if canvas_limit.contains_pixel(cx, cy):
                self._zone_corners.append((cx, cy, self._ZONE_EDGES[i]))
        # Intersecting frame lines & calculation of rectangles
        l_type = LineType.SEGMENT
        cx, cy, cw, ch = self._canvas_rect
        canvas_corners = ((cx, cy), (cx + cw, cy), (cx + cw, cy + ch),
                          (cx, cy + ch))
        intersections = [
            intersection_of_vector_and_poly(canvas_corners, p1, p2, l_type)
            for p1, p2 in pairwise(d_corners)
        ]

        self._prev_rectangles = self._new_rectangles
        self._new_rectangles = [(), (), (), ()]
        if intersections != [None, None, None, None]:
            self._new_rectangles = []
            m = radius + 6  # margin for handle drop shadows
            for intersection in intersections:
                if not intersection:
                    self._new_rectangles.append(())
                    continue
                (x0, y0), (x1, y1) = intersection
                w = abs(x1 - x0) + 2 * m
                h = abs(y1 - y0) + 2 * m
                x = min(x0, x1) - m
                y = min(y0, y1) - m
                self._new_rectangles.append(Rect(x, y, w, h))
        if redraw:
            self.redraw()