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: 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 _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 _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 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 _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 _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 _find_close_position(self, view, home, app_rect, acc_rect, limit_rects, test_clearance, move_clearance, horizontal = True, vertical = True): rh = home move_clearance = Rect(10, 10, 10, 10) # Leave a different clearance for the new, yet to be found, positions. ra = acc_rect.apply_border(*move_clearance) rp = app_rect.apply_border(*move_clearance) # candidate positions vp = [] if vertical: xc = acc_rect.get_center()[0] - rh.w / 2 if app_rect.w > rh.w: xc = max(xc, app_rect.left()) xc = min(xc, app_rect.right() - rh.w) # below window vp.append([xc, rp.bottom(), app_rect]) # above window vp.append([xc, rp.top() - rh.h, app_rect]) # inside maximized window, y at home.y vp.append([xc, home.y, acc_rect]) # vp.append([xc, rp.bottom()-ymargin, app_rect.deflate(rh.h+move_clearance[3]+ymargin)]) # below text entry vp.append([xc, ra.bottom(), acc_rect]) # above text entry vp.append([xc, ra.top() - rh.h, acc_rect]) # limited, non-intersecting candidate rectangles rresult = None 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) ri = p[2] rcs = [ri, acc_rect] # collision rects if not any(r.intersects(rc) for rc in rcs): rresult = r break if rresult is None: # try again, this time horizontally and vertically rhtmp = Rect(vp[0][0], vp[0][1], home.w, home.h) return self._find_non_occluding_position(view, home, acc_rect, limit_rects, test_clearance, move_clearance, horizontal, vertical) else: return rresult.get_position()
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 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 _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 __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 _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 if config.scanner.color_type == "custom_color" and config.scanner.enabled == True: # scan label popup color color_rgba = [] for val in config.scanner.scan_color: color_rgba.append(val) rgb = color_rgba[:3] opacity = color_rgba[3] fill = rgb + [opacity] else: fill = self._key.get_fill_color() context.save() context.set_operator(cairo.OPERATOR_CLEAR) context.paint() context.restore() 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: self._draw_image(context, pixbuf, label_rect, label_color) else: label = self._key.get_label() if label: if label == " ": label = "␣" self._draw_text(context, label, label_rect, label_color)
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 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 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 limit_size(self, rect): """ Limit 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 not limits.is_empty(): # LP #1633284 if r.w > limits.w: r.w = limits.w - 40 if r.h > limits.h: r.h = limits.h - 20 return r
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 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 _find_non_occluding_position(self, home, acc_rect, vertical = True, horizontal = True): # Leave some clearance around the accessible to account for # window frames and position errors of firefox entries. ra = acc_rect.apply_border(*config.auto_show.widget_clearance) rh = home if rh.intersects(ra): 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 = self._keyboard.limit_position( p[0], p[1], self._keyboard.canvas_rect) r = Rect(pl[0], pl[1], rh.w, rh.h) chx, chy = rh.get_center() cx, cy = r.get_center() d2 = cx * chx + cy * chy 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 start_drag(self, point = None): # Find the pointer position for the occasions when we are # not being called from an event (move button). if not point: rootwin = Gdk.get_default_root_window() dunno, x_root, y_root, mask = rootwin.get_pointer() point = (x_root, y_root) # rmember pointer and window positions window = self.get_drag_window() x, y = window.get_position() self._drag_start_pointer = point self._drag_start_offset = [point[0] - x, point[1] - y] self._drag_start_rect = Rect.from_position_size(window.get_position(), window.get_size()) # not yet actually moving the window self._drag_active = False # get the threshold self._drag_threshold = self.get_drag_threshold() # check if the temporary threshold unlocking has expired if not self.drag_protection or \ not self._temporary_unlock_time is None and \ time.time() - self._temporary_unlock_time > \ self.temporary_unlock_delay: self._temporary_unlock_time = None # give keyboard window a chance to react self.on_drag_initiated()
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 update_window_rect(self): """ Call this on configure event, the only time when get_position, get_size, etc. can be trusted. """ visible = self.is_visible() if visible: pos = Gtk.Window.get_position(self) size = Gtk.Window.get_size(self) origin = self.get_window().get_origin() if len(origin) == 3: # What is the first parameter for? Gdk bug? origin = origin[1:] if _logger.isEnabledFor(logging.DEBUG): _logger.debug( "update_window_rect1: pos {}, size {}, origin {}".format( pos, size, origin)) pos = self._apply_window_scaling_factor(pos) self._window_rect = Rect.from_position_size(pos, size) self._origin = origin self._client_offset = (origin[0] - pos[0], origin[1] - pos[1]) self._screen_orientation = self.get_screen_orientation() if _logger.isEnabledFor(logging.DEBUG): _logger.debug("update_window_rect2: pos {}, client_offset {}, " "screen_orientation {}".format( pos, self._client_offset, self._screen_orientation))
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
def start_drag(self, point = None): self._monitor_rects = None # Find the pointer position for the occasions when we are # not being called from an event (move button). if not point: rootwin = Gdk.get_default_root_window() dunno, x_root, y_root, mask = rootwin.get_pointer() point = (x_root, y_root) # rmember pointer and window positions window = self.get_drag_window() x, y = window.get_position() self._drag_start_pointer = point self._drag_start_offset = [point[0] - x, point[1] - y] self._drag_start_rect = Rect.from_position_size(window.get_position(), window.get_size()) # not yet actually moving the window self._drag_active = False # get the threshold self._drag_threshold = self.get_drag_threshold() # check if the temporary threshold unlocking has expired if not self.drag_protection or \ not self._temporary_unlock_time is None and \ time.time() - self._temporary_unlock_time > \ self.temporary_unlock_delay: self._temporary_unlock_time = None # give keyboard window a chance to react self.on_drag_initiated()
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 _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 _on_draw(self, widget, context): #_logger.debug("Draw: clip_extents=" + str(context.clip_extents())) #self.get_window().set_debug_updates(True) if not Gtk.cairo_should_draw_window(context, self.get_window()): return clip_rect = Rect.from_extents(*context.clip_extents()) # draw background decorated = self.draw_background(context) # On first run quickly overwrite the background only. # This gives a slightly smoother startup with desktop remnants # flashing though for a shorter time. if self._first_draw: self._first_draw = False self.queue_draw() return if not self.layout: return # run through all visible layout items layer_ids = self.layout.get_layer_ids() for item in self.layout.iter_visible_items(): if item.layer_id: # draw layer background layer_index = layer_ids.index(item.layer_id) parent = item.parent if parent and \ layer_index != 0: rect = parent.get_canvas_rect() context.rectangle(*rect.inflate(1)) if self.color_scheme: rgba = self.color_scheme.get_layer_fill_rgba(layer_index) else: rgba = [0.5, 0.5, 0.5, 0.9] context.set_source_rgba(*rgba) context.fill() self.draw_dish_key_background(context, 1.0, item.layer_id) # draw key if item.is_key() and \ clip_rect.intersects(item.get_canvas_rect()): item.draw(context) item.draw_image(context) item.draw_label(context) # draw touch handles (enlarged move and resize handles) if self.touch_handles.active: corner_radius = config.CORNER_RADIUS if decorated else 0 self.touch_handles.set_corner_radius(corner_radius) self.touch_handles.draw(context)
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 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 draw_window_frame(self, context, lod): corner_radius = config.CORNER_RADIUS border_rgba = self.get_popup_window_rgba("border") alpha = border_rgba[3] colors = [ [[0.5, 0.5, 0.5, alpha], 0, 1], [border_rgba, 1.5, 2.0], ] rect = Rect(0, 0, self.get_allocated_width(), self.get_allocated_height()) for rgba, pos, width in colors: r = rect.deflate(width) roundrect_arc(context, r, corner_radius) context.set_line_width(width) context.set_source_rgba(*rgba) context.stroke()
def draw_window_frame(self, context, lod): corner_radius = config.CORNER_RADIUS border_rgba = self.get_popup_window_rgba("border") alpha = border_rgba[3] colors = [ [[0.5, 0.5, 0.5, alpha], 0 , 1], [border_rgba, 1.5, 2.0], ] rect = Rect(0, 0, self.get_allocated_width(), self.get_allocated_height()) for rgba, pos, width in colors: r = rect.deflate(width) roundrect_arc(context, r, corner_radius) context.set_line_width(width) context.set_source_rgba(*rgba) context.stroke()
def get_damage_rect(self, context): clip_rect = Rect.from_extents(*context.clip_extents()) # Draw a little more than just the clip_rect. # Prevents glitches around pressed keys in at least classic theme. layout = self.get_layout() if layout: extra_size = layout.context.scale_log_to_canvas((2.0, 2.0)) else: extra_size = 0, 0 return clip_rect.inflate(*extra_size)
def update_window_rect(self): """ Call this on configure event, the only time when get_position, get_size, etc. can be trusted. """ visible = self.is_visible() if visible: self._window_rect = Rect.from_position_size(Gtk.Window.get_position(self), Gtk.Window.get_size(self)) self._origin = self.get_window().get_origin() self._screen_orientation = self.get_screen_orientation()
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 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 position_at(self, x, y, x_align, y_align): """ Align the window with the given point. x, y in root window coordinates. """ rect = Rect.from_position_size(self.get_position(), self.get_size()) rect = rect.align_at_point(x, y, x_align, y_align) rect = self.limit_to_workarea(rect) x, y = rect.get_position() self.move(x, y)
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 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 _clear_xembed_background(self, context): """ fill with plain layer 0 color; no alpha support required """ rect = Rect(0, 0, self.get_allocated_width(), self.get_allocated_height()) # draw background image if config.get_xembed_background_image_enabled(): pixbuf = self._get_xembed_background_image() if pixbuf: src_size = (pixbuf.get_width(), pixbuf.get_height()) x, y = 0, rect.bottom() - src_size[1] Gdk.cairo_set_source_pixbuf(context, pixbuf, x, y) context.paint() # draw solid colored bar on top (with transparency, usually) rgba = config.get_xembed_background_rgba() if rgba is None: rgba = self.get_background_rgba() rgba[3] = 0.5 context.set_source_rgba(*rgba) context.rectangle(*rect) context.fill()
def get_repositioned_window_rect(self, home): """ Get the alternative window rect suggested by auto-show or None if no repositioning is required. """ accessible = self._focused_accessible if accessible: try: ext = accessible.get_extents(Atspi.CoordType.SCREEN) except: # private exception gi._glib.GError when # right clicking onboards unity2d launcher (Precise) _logger.info("AtspiAutoHide: Invalid accessible," " failed to get extents") return None rect = Rect(ext.x, ext.y, ext.width, ext.height) if not rect.is_empty() and \ not self._lock_visible: return self._get_window_rect_for_accessible_rect(home, rect) return None
def draw(self, context): if self.opacity: clip_rect = Rect.from_extents(*context.clip_extents()) for handle in self.handles: rect = handle.get_shadow_rect() if rect.intersects(clip_rect): context.save() context.rectangle(*rect.int()) context.clip() context.push_group() handle.draw(context) context.pop_group_to_source() context.paint_with_alpha(self.opacity); context.restore()
def get_dock_rect(self): area, geom = self.get_docking_monitor_rects() edge = config.window.docking_edge width, height = self.get_dock_size() rect = Rect(area.x, 0, area.w, height) if edge: # Bottom rect.y = area.y + area.h - height else: # Top rect.y = area.y expand = self.get_dock_expand() if expand: rect.w = area.w rect.x = area.x else: rect.w = min(width, area.w) rect.x = rect.x + (area.w - rect.w) // 2 return rect
def get_display_limits(self): rootwin = Gdk.get_default_root_window() return Rect.from_position_size(rootwin.get_position(), (rootwin.get_width(), rootwin.get_height()))
def _on_draw(self, widget, cr): """ Draw the onboard icon. """ if not Gtk.cairo_should_draw_window(cr, self.get_window()): return False width = float(self.get_allocated_width()) height = float(self.get_allocated_height()) # draw themed icon keys = [RectKey("icon" + str(i)) for i in range(4)] color_scheme = self.get_color_scheme() # 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_schema(key) for key in keys): themed = True # 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) rect = Rect(0, 0, width, height) corner_radius = min(width, height) * 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() # four rounded rectangles rects = Rect(0.0, 0.0, 100.0, 100.0).deflate(5) \ .subdivide(2, 2, 6) cr.save() cr.scale(width / 100., height / 100.0) 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() return True
def _parse_legacy_layout(self, dom_node): # parse panes panes = [] is_scan = False for i, pane_node in enumerate(dom_node.getElementsByTagName("pane")): item = LayoutPanel() item.layer_id = "layer {}".format(i) item.id = pane_node.attributes["id"].value item.filename = pane_node.attributes["filename"].value # parse keys keys = [] for node in pane_node.getElementsByTagName("key"): key = self._parse_key(node, item) if key: # some keys have changed since Onboard 0.95 if key.id == "middleClick": key.set_id("middleclick") key.action_type = KeyCommon.BUTTON_ACTION if key.id == "secondaryClick": key.set_id("secondaryclick") key.action_type = KeyCommon.BUTTON_ACTION keys.append(key) item.set_items(keys) # check for scan columns if pane_node.getElementsByTagName("column"): is_scan = True panes.append(item) layer_area = LayoutPanel() layer_area.id = "layer_area" layer_area.set_items(panes) # find the most frequent key width histogram = {} for key in layer_area.iter_keys(): w = key.get_border_rect().w histogram[w] = histogram.get(w, 0) + 1 most_frequent_width = max(list(zip(list(histogram.values()), list(histogram.keys()))))[1] \ if histogram else 18 # Legacy onboard had automatic tab-keys for pane switching. # Simulate this by generating layer buttons from scratch. keys = [] group = "__layer_buttons__" widen = 1.4 if not is_scan else 1.0 rect = Rect(0, 0, most_frequent_width * widen, 20) key = RectKey() attributes = {} attributes["id"] = "hide" attributes["group"] = group attributes["image"] = "close.svg" attributes["button"] = "true" attributes["scannable"] = "false" self._init_key(key, attributes) key.set_border_rect(rect.copy()) keys.append(key) key = RectKey() attributes = {} attributes["id"] = "move" attributes["group"] = group attributes["image"] = "move.svg" attributes["button"] = "true" attributes["scannable"] = "false" self._init_key(key, attributes) key.set_border_rect(rect.copy()) keys.append(key) if len(panes) > 1: for i, pane in enumerate(panes): key = RectKey() attributes = {} attributes["id"] = "layer{}".format(i) attributes["group"] = group attributes["label"] = pane.id attributes["button"] = "true" self._init_key(key, attributes) key.set_border_rect(rect.copy()) keys.append(key) layer_switch_column = LayoutBox() layer_switch_column.horizontal = False layer_switch_column.set_items(keys) layout = LayoutBox() layout.border = 1 layout.spacing = 2 layout.set_items([layer_area, layer_switch_column]) return [layout]
def get_rootwin_rect(): rootwin = Gdk.get_default_root_window() return Rect.from_position_size(rootwin.get_position(), (rootwin.get_width(), rootwin.get_height()))