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

📄 magnifier.c

📁 在Linux下实现magnification功能
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * AT-SPI - Assistive Technology Service Provider Interface * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * * Copyright 2001 Sun Microsystems Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include "config.h"#include "magnifier.h"#include "magnifier-private.h"#include "zoom-region.h"#include "zoom-region-private.h"#include "gmag-events.h"#include "GNOME_Magnifier.h"#include <stdlib.h>#include <string.h>#include <strings.h>#include <X11/Xatom.h>#ifdef HAVE_XFIXES#include <X11/extensions/Xfixes.h>#ifdef HAVE_COMPOSITE#include <X11/extensions/shape.h>#include <X11/extensions/Xcomposite.h>#endif /* HAVE_COMPOSITE */#endif /* HAVE_XFIXES */#include <libbonobo.h>#include <login-helper/login-helper.h>#include <gdk-pixbuf/gdk-pixbuf-io.h>#include <gdk/gdkx.h>#include <gdk/gdk.h>#include <gtk/gtk.h>/* if you #define this, don't forget to set MAG_CLIENT_DEBUG env variable */#define DEBUG_CLIENT_CALLS#ifdef DEBUG_CLIENT_CALLSstatic gboolean client_debug = FALSE;#define DBG(a) if (client_debug) { (a); }#else#define DBG(a)#endiftypedef struct{    LoginHelper parent;    Magnifier *mag;} MagLoginHelper;typedef struct {    LoginHelperClass parent_class;} MagLoginHelperClass;static GObjectClass *parent_class = NULL;enum {	STRUT_LEFT = 0,	STRUT_RIGHT = 1,	STRUT_TOP = 2,	STRUT_BOTTOM = 3,	STRUT_LEFT_START = 4,	STRUT_LEFT_END = 5,	STRUT_RIGHT_START = 6,	STRUT_RIGHT_END = 7,	STRUT_TOP_START = 8,	STRUT_TOP_END = 9,	STRUT_BOTTOM_START = 10,	STRUT_BOTTOM_END = 11};enum {	MAGNIFIER_SOURCE_DISPLAY_PROP,	MAGNIFIER_TARGET_DISPLAY_PROP,	MAGNIFIER_SOURCE_SIZE_PROP,	MAGNIFIER_TARGET_SIZE_PROP,	MAGNIFIER_CURSOR_SET_PROP,	MAGNIFIER_CURSOR_SIZE_PROP,	MAGNIFIER_CURSOR_ZOOM_PROP,	MAGNIFIER_CURSOR_COLOR_PROP,	MAGNIFIER_CURSOR_HOTSPOT_PROP,	MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,	MAGNIFIER_CROSSWIRE_SIZE_PROP,	MAGNIFIER_CROSSWIRE_CLIP_PROP,	MAGNIFIER_CROSSWIRE_COLOR_PROP} PropIdx;typedef struct{	GNOME_Magnifier_RectBounds rectbounds;	GNOME_Magnifier_RectBounds viewport;	gboolean is_managed;	gint scroll_policy;	gfloat contrast;	gfloat zx;	gfloat zy;	gint32 xalign;	gint32 yalign;	guint32 border_color;	gint32 border_size;	gchar *smoothing_type;	gboolean inverse;} MagnifierZoomRegionSaveProps;#ifdef DEBUG_CLIENT_CALLSgchar* mag_prop_names[MAGNIFIER_CROSSWIRE_COLOR_PROP + 1] = {    "SOURCE_DISPLAY",    "TARGET_DISPLAY",    "SOURCE_SIZE",    "TARGET_SIZE",    "CURSOR_SET",    "CURSOR_SIZE",    "CURSOR_ZOOM",    "CURSOR_COLOR",    "CURSOR_HOTSPOT",    "CURSOR_DEFAULT_SIZE",    "CROSSWIRE_SIZE",    "CROSSWIRE_CLIP",    "CROSSWIRE_COLOR"};#endifstatic int _x_error = 0;static Magnifier *_this_magnifier = NULL;extern gint       fixes_event_base;static void magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set);static void magnifier_init_window (Magnifier *magnifier, GdkScreen *screen);static gboolean magnifier_check_set_struts (Magnifier *magnifier);static gboolean magnifier_reset_struts_at_idle (gpointer data);static void magnifier_init_window (Magnifier *magnifier, GdkScreen *screen);static void magnifier_adjust_source_size (Magnifier *magnifier);static gboolean _is_override_redirect = FALSE;static Window*mag_login_helper_get_raise_windows (LoginHelper *helper){    Window *mainwin = NULL;    MagLoginHelper *mag_helper = (MagLoginHelper *) helper;    Magnifier *magnifier = MAGNIFIER (mag_helper->mag);    if (magnifier && magnifier->priv && magnifier->priv->w)    {	mainwin = g_new0 (Window, 2);	mainwin[0] = GDK_WINDOW_XWINDOW (magnifier->priv->w->window);	mainwin[1] = None;    }    return mainwin;}static LoginHelperDeviceReqFlagsmag_login_helper_get_device_reqs (LoginHelper *helper){    /* means "don't grab the xserver or core pointer",        and "we need to raise windows" */    return LOGIN_HELPER_GUI_EVENTS | 	LOGIN_HELPER_POST_WINDOWS | 	LOGIN_HELPER_CORE_POINTER;}static gbooleanmag_login_helper_set_safe (LoginHelper *helper, gboolean ignored){    return TRUE;}static voidmag_login_helper_class_init (MagLoginHelperClass *klass){	LoginHelperClass *login_helper_class = LOGIN_HELPER_CLASS(klass);	login_helper_class->get_raise_windows = mag_login_helper_get_raise_windows;	login_helper_class->get_device_reqs = mag_login_helper_get_device_reqs;	login_helper_class->set_safe = mag_login_helper_set_safe;}static voidmag_login_helper_init (MagLoginHelper *helper){    helper->mag = NULL; /* we set this with mag_login_helper_set_magnifier */}static voidmag_login_helper_set_magnifier (MagLoginHelper *helper, Magnifier *mag){    if (helper) 	helper->mag = mag;}BONOBO_TYPE_FUNC (MagLoginHelper, 		  LOGIN_HELPER_TYPE,		  mag_login_helper)gbooleanmagnifier_error_check (void){	if (_x_error) {		_x_error = 0;		return TRUE;	}	return FALSE;}static intmagnifier_x_error_handler (Display	 *display,			   XErrorEvent *error){	if (error->error_code == BadAlloc) {		_x_error = error->error_code;	}	else {		return -1;	}	return 0;}static gbooleancan_open_display (gchar *display_name){    Display *d;    if ((d = XOpenDisplay (display_name)))    {	XCloseDisplay (d);	return TRUE;    }    return FALSE;}static voidmagnifier_warp_cursor_to_screen (Magnifier *magnifier){	int x, y, unused_x, unused_y;	unsigned int mask;	Window root_return, child_return;	if (magnifier->source_display)	{	    if (!XQueryPointer (GDK_DISPLAY_XDISPLAY (magnifier->source_display), 				GDK_WINDOW_XWINDOW (magnifier->priv->root), 				&root_return,				&child_return,				&x, &y,				&unused_x, &unused_y,				&mask))	    {		XWarpPointer (GDK_DISPLAY_XDISPLAY (magnifier->source_display),			      None,			      GDK_WINDOW_XWINDOW (magnifier->priv->root),			      0, 0, 0, 0,			      x, y);		XSync (GDK_DISPLAY_XDISPLAY (magnifier->source_display), FALSE);	    }	}}static voidmagnifier_zoom_regions_mark_dirty (Magnifier *magnifier, GNOME_Magnifier_RectBounds rect_bounds){	GList *list;	g_assert (magnifier);	list = magnifier->zoom_regions;	while (list) 	{		/* propagate the expose events to the zoom regions */		GNOME_Magnifier_ZoomRegion zoom_region;		CORBA_Environment ev;		zoom_region = list->data;		CORBA_exception_init (&ev);		if (zoom_region)			GNOME_Magnifier_ZoomRegion_markDirty (CORBA_Object_duplicate (zoom_region, &ev),							      &rect_bounds,							      &ev);		list = g_list_next (list);	}}voidmagnifier_set_cursor_from_pixbuf (Magnifier *magnifier, GdkPixbuf *cursor_pixbuf){	GdkPixmap *pixmap, *mask;	gint width, height;	GdkGC *gc;	GdkDrawable *drawable = magnifier->priv->w->window;	if (magnifier->priv->cursor) {		g_object_unref (magnifier->priv->cursor);		magnifier->priv->cursor = NULL;	}	if (drawable && cursor_pixbuf)	{		const gchar *xhot_string = NULL, *yhot_string = NULL;		width = gdk_pixbuf_get_width (cursor_pixbuf);		height = gdk_pixbuf_get_height (cursor_pixbuf);		pixmap = gdk_pixmap_new (drawable, width, height, -1);		gc = gdk_gc_new (pixmap);		if (GDK_IS_DRAWABLE (pixmap))		    gdk_draw_pixbuf (pixmap, gc, cursor_pixbuf, 0, 0, 0, 0, 				     width, height,				     GDK_RGB_DITHER_NONE, 0, 0);		else		    DBG (g_warning ("empty cursor pixmap created."));		mask = gdk_pixmap_new (drawable, width, height, 1);		gdk_pixbuf_render_threshold_alpha (cursor_pixbuf, mask, 0, 0, 0, 0, 						   width, height,						   200);		g_object_unref (gc);		magnifier->priv->cursor = pixmap;		magnifier->priv->cursor_mask = mask;		xhot_string = gdk_pixbuf_get_option (cursor_pixbuf,"x_hot");		yhot_string = gdk_pixbuf_get_option (cursor_pixbuf,"y_hot");		if (xhot_string) magnifier->cursor_hotspot.x = atoi (xhot_string);		if (yhot_string) magnifier->cursor_hotspot.y = atoi (yhot_string);		if (pixmap) {			gdk_drawable_get_size (pixmap,					       &magnifier->priv->cursor_default_size_x,					       &magnifier->priv->cursor_default_size_y);			magnifier->priv->cursor_hotspot_x = magnifier->cursor_hotspot.x;			magnifier->priv->cursor_hotspot_y = magnifier->cursor_hotspot.y;		}	}}GdkPixbuf *magnifier_get_pixbuf_for_name (Magnifier *magnifier, const gchar *cursor_name){    GdkPixbuf *retval = NULL;    if (magnifier->priv->cursorlist) 	    retval = g_hash_table_lookup (magnifier->priv->cursorlist, cursor_name);    if (retval) 	    g_object_ref (retval);    return retval;}voidmagnifier_set_cursor_pixmap_by_name (Magnifier *magnifier,				     const gchar *cursor_name, 				     gboolean source_fallback){	GdkPixbuf *pixbuf;	/* search local table; if not found, use source screen's cursor if source_fallback is TRUE */	if ((pixbuf = magnifier_get_pixbuf_for_name (magnifier, cursor_name)) == NULL) {#ifndef HAVE_XFIXES		source_fallback = FALSE;#endif		if (source_fallback == TRUE)		{			pixbuf = gmag_events_get_source_pixbuf (magnifier);		}		else		{			pixbuf = magnifier_get_pixbuf_for_name (magnifier, "default");		}	}	magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);	if (pixbuf) g_object_unref (pixbuf);}voidmagnifier_notify_damage (Magnifier *magnifier, XRectangle *rect){	GNOME_Magnifier_RectBounds rect_bounds;	rect_bounds.x1 = rect->x;	rect_bounds.y1 = rect->y;	rect_bounds.x2 = rect->x + rect->width;	rect_bounds.y2 = rect->y + rect->height;#undef DEBUG_DAMAGE#ifdef DEBUG_DAMAGE	g_message ("damage");	g_message ("dirty %d, %d to %d, %d", rect_bounds.x1, rect_bounds.y1, rect_bounds.x2, rect_bounds.y2);#endif	magnifier_zoom_regions_mark_dirty (magnifier, rect_bounds);}static voidmagnifier_set_extension_listeners (Magnifier *magnifier, GdkWindow *root){	gmag_events_client_init (magnifier);	magnifier->source_initialized = TRUE;}static voidmagnifier_size_allocate (GtkWidget *widget){	magnifier_check_set_struts (_this_magnifier);}static voidmagnifier_realize (GtkWidget *widget){	XWMHints wm_hints;	Atom wm_window_protocols[2];	Atom wm_type_atoms[1];	Atom net_wm_window_type;	GdkDisplay *target_display = gdk_drawable_get_display (widget->window);		static gboolean initialized = FALSE;#ifndef MAG_WINDOW_OVERRIDE_REDIRECT		if (!initialized) {		wm_window_protocols[0] = gdk_x11_get_xatom_by_name_for_display (target_display,										"WM_DELETE_WINDOW");		wm_window_protocols[1] = gdk_x11_get_xatom_by_name_for_display (target_display,										"_NET_WM_PING");		/* use DOCK until Metacity RFE for new window type goes in */                wm_type_atoms[0] = gdk_x11_get_xatom_by_name_for_display (target_display,									  "_NET_WM_WINDOW_TYPE_DOCK");	}  	wm_hints.flags = InputHint;	wm_hints.input = False;		XSetWMHints (GDK_WINDOW_XDISPLAY (widget->window),		     GDK_WINDOW_XWINDOW (widget->window), &wm_hints);		XSetWMProtocols (GDK_WINDOW_XDISPLAY (widget->window),			 GDK_WINDOW_XWINDOW (widget->window), wm_window_protocols, 2);	net_wm_window_type = gdk_x11_get_xatom_by_name_for_display 		(target_display, "_NET_WM_WINDOW_TYPE");	if (net_wm_window_type && wm_type_atoms[0])		XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window),				 GDK_WINDOW_XWINDOW (widget->window),				 net_wm_window_type,				 XA_ATOM, 32, PropModeReplace,				 (guchar *)wm_type_atoms,				 1);#else#endif	/* TODO: make sure this works/is reset if the DISPLAY 	 * (as well as the SCREEN) changes.	 */	XSetErrorHandler (magnifier_x_error_handler);}GdkWindow*magnifier_get_root (Magnifier *magnifier){    if (!magnifier->priv->root && magnifier->source_display) {	magnifier->priv->root = gdk_screen_get_root_window (	    gdk_display_get_screen (magnifier->source_display,				    magnifier->source_screen_num));    }    return magnifier->priv->root;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -