📄 magnifier.c
字号:
static gintmagnifier_parse_display_name (Magnifier *magnifier, gchar *full_display_string, gchar **display_name){ gchar *screen_ptr; gchar **strings; if (display_name != NULL) { strings = g_strsplit (full_display_string, ":", 2); *display_name = strings [0]; if (strings [1] != NULL) g_free (strings [1]); } screen_ptr = rindex (full_display_string, '.'); if (screen_ptr != NULL) { return (gint) strtol (++screen_ptr, NULL, 10); } return 0;}static voidmagnifier_get_display_rect_bounds (Magnifier *magnifier, GNOME_Magnifier_RectBounds *rect_bounds, gboolean is_target){ if (is_target) { rect_bounds->x1 = 0; rect_bounds->x2 = gdk_screen_get_width ( gdk_display_get_screen (magnifier->target_display, magnifier->target_screen_num)); rect_bounds->y1 = 0; rect_bounds->y2 = gdk_screen_get_height ( gdk_display_get_screen (magnifier->target_display, magnifier->target_screen_num)); } else { rect_bounds->x1 = 0; rect_bounds->x2 = gdk_screen_get_width ( gdk_display_get_screen (magnifier->source_display, magnifier->source_screen_num)); rect_bounds->y1 = 0; rect_bounds->y2 = gdk_screen_get_height ( gdk_display_get_screen (magnifier->source_display, magnifier->source_screen_num)); }}static voidmagnifier_adjust_source_size (Magnifier *magnifier){ GNOME_Magnifier_RectBounds rect_bounds; gdouble vfract_top, vfract_bottom, hfract_left, hfract_right; magnifier_get_display_rect_bounds (magnifier, &rect_bounds, FALSE); hfract_left = (double) (magnifier->target_bounds.x1) / (double) rect_bounds.x2; vfract_top = (double) (magnifier->target_bounds.y1) / (double) rect_bounds.y2; hfract_right = (double) (rect_bounds.x2 - magnifier->target_bounds.x2) / (double) rect_bounds.x2; vfract_bottom = (double) (rect_bounds.y2 - magnifier->target_bounds.y2) / (double) rect_bounds.y2; /* we make our 'source' rectangle the largest available subsection which we aren't occupying */#ifdef HAVE_COMPOSITE if (!g_getenv ("MAGNIFIER_IGNORE_COMPOSITE")) { magnifier->source_bounds = rect_bounds; } else#endif if (MAX (hfract_left, hfract_right) > MAX (vfract_top, vfract_bottom)) /* vertical split, approximately */ { if (hfract_right > hfract_left) { magnifier->source_bounds.x1 = magnifier->target_bounds.x2; magnifier->source_bounds.x2 = rect_bounds.x2; } else { magnifier->source_bounds.x1 = rect_bounds.x1; magnifier->source_bounds.x2 = magnifier->target_bounds.x1; } magnifier->source_bounds.y1 = rect_bounds.y1; magnifier->source_bounds.y2 = rect_bounds.y2; } else /* more-or-less horizontally split */ { if (vfract_bottom > vfract_top) { magnifier->source_bounds.y1 = magnifier->target_bounds.y2; magnifier->source_bounds.y2 = rect_bounds.y2; } else { magnifier->source_bounds.y1 = rect_bounds.y1; magnifier->source_bounds.y2 = magnifier->target_bounds.y1; } magnifier->source_bounds.x1 = rect_bounds.x1; magnifier->source_bounds.x2 = rect_bounds.x2; } g_message ("set source bounds to %d,%d; %d,%d", magnifier->source_bounds.x1, magnifier->source_bounds.y1, magnifier->source_bounds.x2, magnifier->source_bounds.y2);}static voidmagnifier_unref_zoom_region (gpointer data, gpointer user_data){/* Magnifier *magnifier = user_data; NOT USED */ CORBA_Environment ev; GNOME_Magnifier_ZoomRegion zoom_region = data; CORBA_exception_init (&ev); DBG(g_message ("unreffing zoom region")); GNOME_Magnifier_ZoomRegion_dispose (zoom_region, &ev); if (!BONOBO_EX (&ev)) Bonobo_Unknown_unref (zoom_region, &ev);}static GSList*magnifier_zoom_regions_save (Magnifier *magnifier){ GList *list; GSList *save_props = NULL; g_assert (magnifier); list = magnifier->zoom_regions; DBG(g_message ("saving %d regions", g_list_length (list))); while (list) { GNOME_Magnifier_ZoomRegion zoom_region; CORBA_Environment ev; zoom_region = list->data; CORBA_exception_init (&ev); if (zoom_region) { Bonobo_PropertyBag properties; CORBA_any *value; MagnifierZoomRegionSaveProps *zoomer_props = g_new0 (MagnifierZoomRegionSaveProps, 1); zoomer_props->rectbounds = GNOME_Magnifier_ZoomRegion_getROI (zoom_region, &ev); properties = GNOME_Magnifier_ZoomRegion_getProperties (zoom_region, &ev); value = bonobo_pbclient_get_value (properties, "viewport", TC_GNOME_Magnifier_RectBounds, &ev); memcpy (&zoomer_props->viewport, value->_value, sizeof (GNOME_Magnifier_RectBounds)); CORBA_free (value); zoomer_props->is_managed = bonobo_pbclient_get_boolean (properties, "is-managed", NULL); zoomer_props->scroll_policy = bonobo_pbclient_get_short (properties, "smooth-scroll-policy", NULL); zoomer_props->contrast = bonobo_pbclient_get_float (properties, "contrast", NULL); zoomer_props->zx = bonobo_pbclient_get_float (properties, "mag-factor-x", NULL); zoomer_props->zy = bonobo_pbclient_get_float (properties, "mag-factor-y", NULL); zoomer_props->xalign = bonobo_pbclient_get_long (properties, "x-alignment", NULL); zoomer_props->yalign = bonobo_pbclient_get_long (properties, "y-alignment", NULL); zoomer_props->border_color = bonobo_pbclient_get_long (properties, "border-color", NULL); zoomer_props->border_size = bonobo_pbclient_get_long (properties, "border-size", NULL); zoomer_props->smoothing_type = bonobo_pbclient_get_string (properties, "smoothing-type", NULL); zoomer_props->inverse = bonobo_pbclient_get_boolean (properties, "inverse-video", NULL); bonobo_object_release_unref (properties, &ev); magnifier_unref_zoom_region ((gpointer) zoom_region, NULL); save_props = g_slist_append (save_props, zoomer_props); } list = g_list_next (list); } magnifier->zoom_regions = NULL; return save_props;}static voidmagnifier_zoom_regions_restore (Magnifier *magnifier, GSList *region_params){ GSList *list = region_params; while (list) { CORBA_Environment ev; MagnifierZoomRegionSaveProps *zoomer_props = list->data; GNOME_Magnifier_ZoomRegion new_region; Bonobo_PropertyBag new_properties; CORBA_exception_init (&ev); new_region = GNOME_Magnifier_Magnifier_createZoomRegion (BONOBO_OBJREF (magnifier), zoomer_props->zx, zoomer_props->zy, &zoomer_props->rectbounds, &zoomer_props->viewport, &ev); new_properties = GNOME_Magnifier_ZoomRegion_getProperties (new_region, &ev); bonobo_pbclient_set_boolean (new_properties, "is-managed", zoomer_props->is_managed, NULL); bonobo_pbclient_set_short (new_properties, "smooth-scroll-policy", zoomer_props->scroll_policy, NULL); bonobo_pbclient_set_float (new_properties, "contrast", zoomer_props->contrast, NULL);/* NOT YET USED bonobo_pbclient_set_long (new_properties, "x-alignment", zoomer_props->xalign, NULL); bonobo_pbclient_set_long (new_properties, "y-alignment", zoomer_props->yalign, NULL);*/ bonobo_pbclient_set_long (new_properties, "border-color", zoomer_props->border_color, NULL); bonobo_pbclient_set_long (new_properties, "border-size", zoomer_props->border_size, NULL); bonobo_pbclient_set_string (new_properties, "smoothing-type", zoomer_props->smoothing_type, NULL); bonobo_pbclient_set_boolean (new_properties, "inverse-video", zoomer_props->inverse, NULL); GNOME_Magnifier_Magnifier_addZoomRegion (BONOBO_OBJREF (magnifier), new_region, &ev); g_free (zoomer_props->smoothing_type); g_free (zoomer_props); bonobo_object_release_unref (new_properties, &ev); list = g_slist_next (list); } g_slist_free (region_params);}static voidmagnifier_init_display (Magnifier *magnifier, gchar *display_name, gboolean is_target){ if (!can_open_display (display_name)) return; if (is_target) { magnifier->target_screen_num = magnifier_parse_display_name (magnifier, display_name, NULL); magnifier->target_display = gdk_display_open (display_name); if (magnifier->target_display_name) g_free (magnifier->target_display_name); magnifier->target_display_name = g_strdup (display_name); magnifier->priv->root = gdk_screen_get_root_window ( gdk_display_get_screen ( magnifier->target_display, magnifier->target_screen_num)); } else { magnifier->source_screen_num = magnifier_parse_display_name (magnifier, display_name, NULL); magnifier->source_display = gdk_display_open (display_name); if (magnifier->source_display) { if (magnifier->source_display_name) g_free (magnifier->source_display_name); magnifier->source_display_name = g_strdup (display_name); magnifier->priv->root = gdk_screen_get_root_window ( gdk_display_get_screen ( magnifier->source_display, magnifier->source_screen_num)); } }}static voidmagnifier_exit (GtkObject *object){ gtk_main_quit (); exit (0);}#define GET_PIXEL(a,i,j,s,b) \(*(guint32 *)(memcpy (b,(a) + ((j) * s + (i) * pixel_size_t), pixel_size_t)))#define PUT_PIXEL(a,i,j,s,b) \(memcpy (a + ((j) * s + (i) * pixel_size_t), &(b), pixel_size_t))static voidmagnifier_recolor_pixbuf (Magnifier *magnifier, GdkPixbuf *pixbuf){ int rowstride = gdk_pixbuf_get_rowstride (pixbuf); int i, j; int w = gdk_pixbuf_get_width (pixbuf); int h = gdk_pixbuf_get_height (pixbuf); guchar *pixels = gdk_pixbuf_get_pixels (pixbuf); guint32 pixval = 0, cursor_color = 0; size_t pixel_size_t = 3; /* FIXME: invalid assumption ? */ cursor_color = ((magnifier->cursor_color & 0xFF0000) >> 16) + (magnifier->cursor_color & 0x00FF00) + ((magnifier->cursor_color & 0x0000FF) << 16); for (j = 0; j < h; ++j) { for (i = 0; i < w; ++i) { pixval = GET_PIXEL (pixels, i, j, rowstride, &pixval); if ((pixval & 0x808080) == 0) { pixval = cursor_color; PUT_PIXEL (pixels, i, j, rowstride, pixval); } } }}voidmagnifier_transform_cursor (Magnifier *magnifier){ if (magnifier->priv->cursor) /* don't do this if cursor isn't intialized yet */ { int width, height; int size_x, size_y; GdkPixbuf *scaled_cursor_pixbuf; GdkPixbuf *scaled_mask_pixbuf; GdkPixbuf *scaled_mask_pixbuf_alpha; GdkPixbuf *cursor_pixbuf; GdkPixbuf *mask_pixbuf; GdkPixmap *cursor_pixmap = magnifier->priv->cursor; GdkPixmap *mask_pixmap = magnifier->priv->cursor_mask; GdkGC *cgc; GdkGC *mgc; if (magnifier->cursor_size_x) { size_x = magnifier->cursor_size_x; size_y = magnifier->cursor_size_y; } else { size_x = magnifier->priv->cursor_default_size_x * magnifier->cursor_scale_factor; size_y = magnifier->priv->cursor_default_size_y * magnifier->cursor_scale_factor; } gdk_drawable_get_size (magnifier->priv->cursor, &width, &height); if ((size_x == width) && (size_y == height) && (magnifier->cursor_color == 0xFF000000)) { return; /* nothing changes */ } cgc = gdk_gc_new (cursor_pixmap); mgc = gdk_gc_new (mask_pixmap); cursor_pixbuf = gdk_pixbuf_get_from_drawable (NULL, cursor_pixmap, NULL, 0, 0, 0, 0, width, height); if (magnifier->cursor_color != 0xFF000000) magnifier_recolor_pixbuf (magnifier, cursor_pixbuf); mask_pixbuf = gdk_pixbuf_get_from_drawable (NULL, mask_pixmap, NULL, 0, 0, 0, 0, width, height); scaled_cursor_pixbuf = gdk_pixbuf_scale_simple ( cursor_pixbuf, size_x, size_y, GDK_INTERP_NEAREST); magnifier->cursor_hotspot.x = magnifier->priv->cursor_hotspot_x * size_x / magnifier->priv->cursor_default_size_x; magnifier->cursor_hotspot.y = magnifier->priv->cursor_hotspot_y * size_y / magnifier->priv->cursor_default_size_y; scaled_mask_pixbuf = gdk_pixbuf_scale_simple ( mask_pixbuf, size_x, size_y, GDK_INTERP_NEAREST); g_object_unref (cursor_pixbuf); g_object_unref (mask_pixbuf); g_object_unref (cursor_pixmap); g_object_unref (mask_pixmap); magnifier->priv->cursor = gdk_pixmap_new ( magnifier->priv->w->window, size_x, size_y, -1); if (!GDK_IS_DRAWABLE (magnifier->priv->cursor)) { DBG (g_warning ("NULL magnifier cursor pixmap.")); return; } magnifier->priv->cursor_mask = gdk_pixmap_new ( magnifier->priv->w->window, size_x, size_y, 1); if (GDK_IS_DRAWABLE (magnifier->priv->cursor)) { gdk_draw_pixbuf (magnifier->priv->cursor, cgc, scaled_cursor_pixbuf, 0, 0, 0, 0, size_x, size_y, GDK_RGB_DITHER_NONE, 0, 0 ); } else DBG (g_warning ("cursor pixmap is non-drawable.")); scaled_mask_pixbuf_alpha = gdk_pixbuf_add_alpha ( scaled_mask_pixbuf, True, 0, 0, 0); gdk_pixbuf_render_threshold_alpha (scaled_mask_pixbuf_alpha, magnifier->priv->cursor_mask, 0, 0, 0, 0, size_x, size_y, 0x80); g_object_unref (scaled_mask_pixbuf_alpha); g_object_unref (scaled_cursor_pixbuf); g_object_unref (scaled_mask_pixbuf); g_object_unref (mgc); g_object_unref (cgc); } }static voidmagnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set){ /* * we check the cursor-set property string here, * and create/apply the appropriate cursor settings */ magnifier->cursor_set = cursor_set;#ifdef HAVE_XFIXES magnifier->priv->use_source_cursor = (!strcmp (cursor_set, "default") && (fixes_event_base != 0));#else magnifier->priv->use_source_cursor = FALSE;#endif if (magnifier->priv->use_source_cursor) return; if (!strcmp (magnifier->cursor_set, "none")) { magnifier->priv->cursor = NULL; return; } else { GDir *cursor_dir; const gchar *filename; gchar *cursor_dirname; if (magnifier->priv->cursorlist) { g_hash_table_destroy (magnifier->priv->cursorlist); } magnifier->priv->cursorlist = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); cursor_dirname = g_strconcat (CURSORSDIR, "/", magnifier->cursor_set, NULL); cursor_dir = g_dir_open (cursor_dirname, 0, NULL); /* assignment, not comparison, is intentional */ while (cursor_dir && (filename = g_dir_read_name (cursor_dir)) != NULL) { if (filename) { gchar *path = g_strconcat (cursor_dirname, "/", filename, NULL); GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (path, NULL); if (pixbuf) { /* add this pixbuf and its name to our list */ gchar **sv, *cname; cname = g_path_get_basename (filename); sv = g_strsplit (cname, ".", 2); g_hash_table_insert (magnifier->priv->cursorlist, g_strdup (sv[0]), pixbuf); g_free (cname); g_strfreev (sv); } g_free (path); } } g_free (cursor_dirname); if (cursor_dir) g_dir_close (cursor_dir); } /* don't fallover to source cursor here, we haven't initialized X yet */ magnifier_set_cursor_pixmap_by_name (magnifier, "default", FALSE); magnifier_transform_cursor (magnifier);}static gbooleanmagnifier_reset_overlay_at_idle (gpointer data){#ifdef HAVE_COMPOSITE if (!g_getenv ("MAGNIFIER_IGNORE_COMPOSITE")) { if (data) { Magnifier *magnifier = MAGNIFIER (data); if (magnifier->priv && GTK_WIDGET_REALIZED (magnifier->priv->w)) if (magnifier->priv->w->window) {#ifdef HAVE_OVERLAY gint x, y, over_w, over_h; magnifier->priv->overlay = gdk_window_foreign_new (XCompositeGetOverlayWindow (GDK_WINDOW_XDISPLAY (magnifier->priv->w->window), GDK_WINDOW_XID (magnifier->priv->root))); gdk_window_get_position (
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -