def log_to_canvas_rect(self, rect): if rect.is_empty(): return Rect() return Rect(self.log_to_canvas_x(rect.x), self.log_to_canvas_y(rect.y), self.scale_log_to_canvas_x(rect.w), self.scale_log_to_canvas_y(rect.h))
def _get_xembed_background_image(self): """ load the desktop background image in Unity """ try: pixbuf = self._xid_background_image except AttributeError: size, size_mm = get_monitor_dimensions(self) filename = config.get_desktop_background_filename() if not filename or \ size[0] <= 0 or size[1] <= 0: pixbuf = None else: try: # load image pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename) # Scale image to mimic the behavior of gnome-screen-saver. # Take the largest, aspect correct, centered rectangle # that fits on the monitor. rm = Rect(0, 0, size[0], size[1]) rp = Rect(0, 0, pixbuf.get_width(), pixbuf.get_height()) ra = rm.inscribe_with_aspect(rp) pixbuf = pixbuf.new_subpixbuf(*ra) pixbuf = pixbuf.scale_simple(size[0], size[1], GdkPixbuf.InterpType.BILINEAR) except Exception as ex: # private exception gi._glib.GError when # librsvg2-common wasn't installed _logger.error("_get_xembed_background_image(): " + \ unicode_str(ex)) pixbuf = None self._xid_background_image = pixbuf return pixbuf
def _calc_bounds(self): """ Compute the bounding box of the path. Doctests: # Simple move_to path, something inkscape would create. >>> p = KeyPath.from_svg_path("m 100,200 10,-10 z") >>> print(p.get_bounds()) Rect(x=100.0 y=190.0 w=10.0 h=10.0) """ try: xmin = xmax = self.segments[0][1][0] ymin = ymax = self.segments[0][1][1] except IndexError: return Rect() for command in self.segments: coords = command[1] for i in range(0, len(coords), 2): x = coords[i] y = coords[i + 1] if xmin > x: xmin = x if xmax < x: xmax = x if ymin > y: ymin = y if ymax < y: ymax = y return Rect(xmin, ymin, xmax - xmin, ymax - ymin)
def _draw_themed_icon(self, cr, icon_rect, color_scheme): """ draw themed icon """ keys = [RectKey("icon" + str(i)) for i in range(4)] # Default colors for the case when none of the icon keys # are defined in the color scheme. # background_rgba = [1.0, 1.0, 1.0, 1.0] fill_rgbas = [[0.9, 0.7, 0.0, 0.75], [1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0], [0.0, 0.54, 1.0, 1.0]] stroke_rgba = [0.0, 0.0, 0.0, 1.0] label_rgba = [0.0, 0.0, 0.0, 1.0] themed = False if color_scheme: if any(color_scheme.is_key_in_scheme(key) for key in keys): themed = True # four rounded rectangles rects = Rect(0.0, 0.0, 100.0, 100.0).deflate(5) \ .subdivide(2, 2, 6) cr.save() cr.scale(icon_rect.w / 100., icon_rect.h / 100.0) cr.translate(icon_rect.x, icon_rect.y) cr.select_font_face("sans-serif") cr.set_line_width(2) for i, key in enumerate(keys): rect = rects[i] if themed: fill_rgba = color_scheme.get_key_rgba(key, "fill") stroke_rgba = color_scheme.get_key_rgba(key, "stroke") label_rgba = color_scheme.get_key_rgba(key, "label") else: fill_rgba = fill_rgbas[i] roundrect_arc(cr, rect, 5) cr.set_source_rgba(*fill_rgba) cr.fill_preserve() cr.set_source_rgba(*stroke_rgba) cr.stroke() if i == 0 or i == 3: if i == 0: letter = "O" else: letter = "B" cr.set_font_size(25) (x_bearing, y_bearing, _width, _height, x_advance, y_advance) = cr.text_extents(letter) r = rect.align_rect(Rect(0, 0, _width, _height), 0.3, 0.33) cr.move_to(r.x - x_bearing, r.y - y_bearing) cr.set_source_rgba(*label_rgba) cr.show_text(letter) cr.new_path() cr.restore()
def get_repositioned_window_rect(self, view, home, limit_rects, test_clearance, move_clearance, horizontal=True, vertical=True): """ Get the alternative window rect suggested by auto-show or None if no repositioning is required. """ accessible = self._active_accessible if not accessible: return None accessible.invalidate_extents() acc_rect = accessible.get_extents() if acc_rect.is_empty() or \ self._lock_visible: return None method = config.get_auto_show_reposition_method() x = None y = None # The home_rect doesn't include window decoration, # make sure to add decoration for correct clearance. rh = home.copy() window = view.get_kbd_window() if window: offset = window.get_client_offset() rh.w += offset[0] rh.h += offset[1] # "Follow active window" method if method == RepositionMethodEnum.REDUCE_POINTER_TRAVEL: frame = accessible.get_frame() app_rect = frame.get_extents() \ if frame else Rect() x, y = self._find_close_position(view, rh, app_rect, acc_rect, limit_rects, test_clearance, move_clearance, horizontal, vertical) # "Only move when necessary" method if method == RepositionMethodEnum.PREVENT_OCCLUSION: x, y = self._find_non_occluding_position(view, rh, acc_rect, limit_rects, test_clearance, move_clearance, horizontal, vertical) if not x is None: return Rect(x, y, home.w, home.h) else: return None
def __init__(self): # logical rectangle as defined by the keyboard layout, # never changed after loading. self.initial_log_rect = Rect(0.0, 0.0, 1.0, 1.0) # includes border # logical rectangle as defined by the keyboard layout self.log_rect = Rect(0.0, 0.0, 1.0, 1.0) # includes border # canvas rectangle in drawing units self.canvas_rect = Rect(0.0, 0.0, 1.0, 1.0)
def get_accessible_extents(accessible): """ Screen rect of the given accessible, no caching """ try: ext = accessible.get_extents(Atspi.CoordType.SCREEN) except Exception as ex: # private exception gi._glib.GError when # right clicking onboards unity2d launcher (Precise) _logger.info("Invalid accessible," " failed to get extents: " + unicode_str(ex)) return Rect() return Rect(ext.x, ext.y, ext.width, ext.height)
def on_draw(self, widget, context): if not LabelPopup._pango_layout: LabelPopup._pango_layout = Pango.Layout( context=Gdk.pango_context_get()) rect = Rect(0, 0, self.get_allocated_width(), self.get_allocated_height()) content_rect = Rect(rect.x, rect.y, rect.w, rect.h - rect.h * self.ARROW_HEIGHT) arrow_rect = Rect(rect.x, content_rect.bottom(), rect.w, rect.h * self.ARROW_HEIGHT) \ .deflate((rect.w - rect.w * self.ARROW_WIDTH) / 2.0, 0) label_rect = content_rect.deflate(rect.w * self.LABEL_MARGIN) # background fill = self._key.get_fill_color() context.save() context.set_operator(cairo.OPERATOR_CLEAR) context.paint() context.restore() context.push_group() context.set_source_rgba(*fill) roundrect_arc(context, content_rect, config.CORNER_RADIUS) context.fill() l, t, r, b = arrow_rect.to_extents() t -= 1 context.move_to(l, t) context.line_to(r, t) context.line_to((l + r) / 2, b) context.fill() # draw label/image label_color = self._key.get_label_color() pixbuf = self._key.get_image(label_rect.w, label_rect.h) if pixbuf: pixbuf.draw(context, label_rect, label_color) else: label = self._key.get_label() if label: if label == " ": label = "␣" self._draw_text(context, label, label_rect, label_color) context.pop_group_to_source() context.paint_with_alpha(self._opacity)
def log_to_canvas_rect(self, rect): """ ~50% faster than the above. """ w = rect.w h = rect.h if w <= 0 or h <= 0: return Rect() canvas_rect = self.canvas_rect log_rect = self.log_rect scale_w = canvas_rect.w / log_rect.w scale_h = canvas_rect.h / log_rect.h return Rect(canvas_rect.x + (rect.x - log_rect.x) * scale_w, canvas_rect.y + (rect.y - log_rect.y) * scale_h, w * scale_w, h * scale_h)
def get_known_rects(self): """ Return all rects that may have resulted from internal window moves, not from user controlled drag operations. """ rects = list(self._known_window_rects) co = config.window.landscape rects.append(Rect(co.x, co.y, co.width, co.height)) co = config.window.portrait rects.append(Rect(co.x, co.y, co.width, co.height)) rects.append(self.home_rect) return rects
def _read_remaining_accessible_state(self, accessible): """ Read more attributes and find out as much as we can about the accessibles purpose. """ state = {} state["attributes"] = accessible.get_attributes() state["interfaces"] = accessible.get_interfaces() ext = accessible.get_extents(Atspi.CoordType.SCREEN) state["extents"] = Rect(ext.x, ext.y, ext.width, ext.height) # These are currently used only in debug output if _logger.isEnabledFor(logging.DEBUG): state["id"] = accessible.get_id() state["name"] = accessible.get_name() pid = accessible.get_process_id() state["process-id"] = pid if pid != -1: state["process-name"] = Process.get_process_name(pid) app = accessible.get_application() if app: state["app-name"] = app.get_name() state["app-description"] = app.get_description() return state
def update_position(self, canvas_rect): w, h = self._size w = min(w, canvas_rect.w / 3.0) w = min(w, canvas_rect.h / 3.0) h = w self._scale = 1.0 xc, yc = canvas_rect.get_center() if self.id is Handle.MOVE: # move handle? d = min(canvas_rect.w - 2.0 * w, canvas_rect.h - 2.0 * h) self._scale = 1.4 w = min(w * self._scale, d) h = min(h * self._scale, d) if self.id in [Handle.WEST, Handle.NORTH_WEST, Handle.SOUTH_WEST]: x = canvas_rect.left() if self.id in [Handle.NORTH, Handle.NORTH_WEST, Handle.NORTH_EAST]: y = canvas_rect.top() if self.id in [Handle.EAST, Handle.NORTH_EAST, Handle.SOUTH_EAST]: x = canvas_rect.right() - w if self.id in [Handle.SOUTH, Handle.SOUTH_WEST, Handle.SOUTH_EAST]: y = canvas_rect.bottom() - h if self.id in [Handle.MOVE, Handle.EAST, Handle.WEST]: y = yc - h / 2.0 if self.id in [Handle.MOVE, Handle.NORTH, Handle.SOUTH]: x = xc - w / 2.0 self._rect = Rect(x, y, w, h)
def _get_window_rect_for_accessible_rect(self, home, rect, limit_rects, test_clearance, move_clearance, horizontal=True, vertical=True): """ Find new window position based on the screen rect of the accessible. """ mode = "nooverlap" x = y = None if mode == "closest": x, y = rect.left(), rect.bottom() if mode == "nooverlap": x, y = self._find_non_occluding_position(home, rect, limit_rects, test_clearance, move_clearance, horizontal, vertical) if not x is None: return Rect(x, y, home.w, home.h) else: return None
def _draw_side_bars(self, context): """ Transparent bars left and right of the aspect corrected keyboard frame. """ rgba = self.get_background_rgba() rgba[3] = 0.5 rwin = Rect(0, 0, self.get_allocated_width(), self.get_allocated_height()) rframe = self.get_keyboard_frame_rect() if rwin.w > rframe.w: r = rframe.copy() context.set_source_rgba(*rgba) context.set_line_width(0) r.x = rwin.left() r.w = rframe.left() - rwin.left() context.rectangle(*r) context.fill() r.x = rframe.right() r.w = rwin.right() - rframe.right() context.rectangle(*r) context.fill()
def _on_draw(self, widget, cr): """ Draw the onboard icon. """ if not Gtk.cairo_should_draw_window(cr, self.get_window()): return False rect = Rect(0.0, 0.0, float(self.get_allocated_width()), float(self.get_allocated_height())) color_scheme = self.get_color_scheme() # clear background cr.save() cr.set_operator(cairo.OPERATOR_CLEAR) cr.paint() cr.restore() # draw background color background_rgba = list(color_scheme.get_icon_rgba("background")) if Gdk.Screen.get_default().is_composited(): background_rgba[3] *= 0.75 cr.set_source_rgba(*background_rgba) corner_radius = min(rect.w, rect.h) * 0.1 roundrect_arc(cr, rect, corner_radius) cr.fill() # decoration frame line_rect = rect.deflate(2) cr.set_line_width(2) roundrect_arc(cr, line_rect, corner_radius) cr.stroke() else: cr.set_source_rgba(*background_rgba) cr.paint() # draw themed icon self._draw_themed_icon(cr, rect, color_scheme) # draw dwell progress rgba = [0.8, 0.0, 0.0, 0.5] bg_rgba = [0.1, 0.1, 0.1, 0.5] if color_scheme: key = RectKey( "icon0") # take dwell color from the first icon "key" rgba = color_scheme.get_key_rgba(key, "dwell-progress") rgba[3] = min(0.75, rgba[3]) # more transparency key = RectKey("icon1") bg_rgba = color_scheme.get_key_rgba(key, "fill") bg_rgba[3] = min(0.75, rgba[3]) # more transparency dwell_rect = rect.grow(0.5) self._dwell_progress.draw(cr, dwell_rect, rgba, bg_rgba) return True
def reposition(self, x, y): """ Move the window from a transition, not meant for user positioning. """ # remember rects to distimguish from user move/resize w, h = self.get_size() self.remember_rect(Rect(x, y, w, h)) self.move(x, y)
def _find_non_occluding_position(self, view, home, acc_rect, limit_rects, test_clearance, move_clearance, horizontal=True, vertical=True): rh = home # Leave some clearance around the accessible to account for # window frames and position errors of firefox entries. ra = acc_rect.apply_border(*test_clearance) if rh.intersects(ra): # Leave a different clearance for the new, # yet to be found positions. ra = acc_rect.apply_border(*move_clearance) x, y = rh.get_position() # candidate positions vp = [] if horizontal: vp.append([ra.left() - rh.w, y]) vp.append([ra.right(), y]) if vertical: vp.append([x, ra.top() - rh.h]) vp.append([x, ra.bottom()]) # limited, non-intersecting candidate rectangles vr = [] for p in vp: pl = view.limit_position(p[0], p[1], view.canvas_rect, limit_rects) r = Rect(pl[0], pl[1], rh.w, rh.h) if not r.intersects(ra): vr.append(r) # candidate with smallest center-to-center distance wins chx, chy = rh.get_center() dmin = None rmin = None for r in vr: cx, cy = r.get_center() dx, dy = cx - chx, cy - chy d2 = dx * dx + dy * dy if dmin is None or dmin > d2: dmin = d2 rmin = r if not rmin is None: return rmin.get_position() return None, None
def test_valid_test_environment(self): # write to dconf database to make sure it exists self._gsettings_set("org.onboard", "use-system-defaults", True) self.assertEqual( self._gsettings_get("org.onboard", "use-system-defaults"), True) self.assertTrue(os.path.exists(self._dconf_db_fn)) # database must be reset to defaults self.assertEqual(str(self._get_window_rect()), str(Rect(100, 50, 700, 205)))
def get_accessible_extents(accessible): """ Screen rect of the given accessible, no caching """ try: rect = AtspiStateTracker._get_accessible_extents(accessible) # private exception gi._glib.GError when # right clicking onboards unity2d launcher (Precise) except Exception as ex: _logger.atspi("Invalid accessible," " failed to get extents: " + unicode_str(ex)) rect = Rect() return rect
def read_window_rect(self, orientation): """ Read orientation dependent rect. Overload for WindowRectPersist. """ if orientation == Orientation.LANDSCAPE: co = config.icp.landscape else: co = config.icp.portrait rect = Rect(co.x, co.y, max(co.width, 10), max(co.height, 10)) return rect
def read_window_rect(self, orientation): """ Read orientation dependent rect. Overload for WindowRectTracker. """ if orientation == Orientation.LANDSCAPE: co = config.window.landscape else: co = config.window.portrait rect = Rect(co.x, co.y, co.width, co.height) return rect
def _calc_bounds(self): """ Calculate the bounding rectangle over all items of this panel """ # If there is no visible item return an empty rect if all(not item.is_visible() for item in self.items): return Rect() compact = self.compact bounds = None for item in self.items: if not compact or item.visible: rect = item.get_border_rect() if not rect.is_empty(): if bounds is None: bounds = rect else: bounds = bounds.union(rect) if bounds is None: return Rect() return bounds
def get_character_extents(self, accessible, offset): """ Screen rect of the character at offset """ try: rect = self._get_character_extents(offset) except Exception as ex: # private exception gi._glib.GError when # right clicking onboards unity2d launcher (Precise) _logger.atspi("Invalid accessible," " failed to get character extents: " + unicode_str(ex)) rect = Rect() return rect
def limit_size(self, rect): """ Limits the given window rect to fit on screen. """ screen = self.get_screen() limits = Rect(0, 0, screen.get_width(), screen.get_height()) r = rect.copy() if r.w > limits.w: r.w = limits.w - 40 if r.h > limits.h: r.h = limits.h - 20 return r
def get_docking_monitor_rects(self): screen = self.get_screen() mon = self.get_docking_monitor() area = self._monitor_workarea.get(mon) if area is None: area = self.update_monitor_workarea() geom = screen.get_monitor_geometry(mon) geom = Rect(geom.x, geom.y, geom.width, geom.height) return area, geom
def get_keyboard_frame_rect(self): """ Rectangle of the potentially aspect-corrected frame around the layout. """ layout = self.get_layout() if layout: rect = layout.get_canvas_border_rect() rect = rect.inflate(self.get_frame_width()) else: rect = Rect(0, 0, self.get_allocated_width(), self.get_allocated_height()) return rect.int()
def __init__(self, keyboard): self.keyboard = keyboard self.supports_alpha = False self._lod = LOD.FULL self._font_sizes_valid = False self._shadow_quality_valid = False self._last_canvas_shadow_rect = Rect() self._starting_up = True self._keys_pre_rendered = False self.keyboard.register_view(self)
def canvas_to_root_window_rect(window, rect): """ Convert rect in canvas coordinates to root window coordinates. """ gdk_win = window.get_window() if gdk_win: x0, y0 = gdk_win.get_root_coords(rect.x, rect.y) x1, y1 = gdk_win.get_root_coords(rect.x + rect.w, rect.y + rect.h) rect = Rect.from_extents(x0, y0, x1, y1) else: rect = Rect() return rect
def build(source_key, color_scheme, layout): context = source_key.context frame_width = LayoutBuilder._calc_frame_width(context) layout = LayoutRoot(layout) layout.update_log_rect() log_rect = layout.get_border_rect() canvas_rect = Rect(frame_width, frame_width, log_rect.w * context.scale_log_to_canvas_x(1.0), log_rect.h * context.scale_log_to_canvas_y(1.0)) layout.fit_inside_canvas(canvas_rect) return layout, frame_width
def get_monitor_rects(screen): """ Screen limits, one rect per monitor. Monitors may have different sizes and arbitrary relative positions. """ rects = [] if screen: for i in range(screen.get_n_monitors()): r = screen.get_monitor_geometry(i) rects.append(Rect(r.x, r.y, r.width, r.height)) else: rootwin = Gdk.get_default_root_window() r = Rect.from_position_size(rootwin.get_position(), (rootwin.get_width(), rootwin.get_height())) rects.append(r) return rects