⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 magnifier.c

📁 在Linux下实现magnification功能
💻 C
📖 第 1 页 / 共 4 页
字号:
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 + -