gmag-events.c

来自「在Linux下实现magnification功能」· C语言 代码 · 共 1,216 行 · 第 1/3 页

C
1,216
字号
{#ifdef HAVE_XFIXES	XFixesCursorImage *cursor_image = XFixesGetCursorImage (		dpy_conn);        GdkPixbuf *cursor_pixbuf = NULL;	gchar s[6];	if (cursor_image)	{	        gmag_events_cursor_convert_to_rgba (magnifier, cursor_image);		cursor_pixbuf = gdk_pixbuf_new_from_data (			(guchar *) cursor_image->pixels, GDK_COLORSPACE_RGB,			TRUE, 8, cursor_image->width, cursor_image->height,			cursor_image->width * 4,			gmag_events_free_cursor_pixels, cursor_image);		gdk_pixbuf_set_option (cursor_pixbuf, "x_hot", 				       g_ascii_dtostr (					       s, 6,					       (gdouble) cursor_image->xhot));		gdk_pixbuf_set_option (cursor_pixbuf, "y_hot", 				       g_ascii_dtostr (					       s, 6,					       (gdouble) cursor_image->yhot));	}	return cursor_pixbuf;#else	return NULL;#endif /* HAVE_XFIXES */}gbooleangmag_events_source_has_damage_extension (Magnifier *magnifier){#ifdef HAVE_DAMAGE	gint event_base, error_base;	Display *dpy;	g_assert (magnifier);	dpy = GDK_DISPLAY_XDISPLAY (magnifier->source_display);	if (g_getenv ("MAGNIFIER_IGNORE_DAMAGE"))	        return FALSE;	if (XDamageQueryExtension (dpy, &event_base, &error_base))		return TRUE;#endif /* HAVE_DAMAGE */	return FALSE;}static gbooleangmag_events_handler (GIOChannel *source, GIOCondition condition, gpointer data){#ifdef HAVE_XFIXES	XEvent                   ev;	XFixesCursorNotifyEvent *cev = NULL;	gboolean                 cursor_changed = FALSE;	Magnifier               *magnifier = (Magnifier *) data;	XRectangle              *rectlist;#ifdef HAVE_COMPOSITE	gboolean                 calc_clip = FALSE;#endif /* HAVE_COMPOSITE */#ifdef HAVE_OVERLAY	if (magnifier->priv->overlay)		mag_window = GDK_WINDOW_XID (magnifier->priv->overlay);#else	if (magnifier->priv->w && magnifier->priv->w->window)		mag_window = GDK_WINDOW_XID (magnifier->priv->w->window);#endif /* HAVE_OVERLAY */	do	{		XNextEvent(dpy_conn, &ev);#ifdef HAVE_COMPOSITE		if (use_composite) {			switch (ev.type) {			case CirculateNotify:				gmag_events_circulate_notify_handler (&ev);				calc_clip = TRUE;				break;			case ConfigureNotify:				gmag_events_configure_notify_handler (&ev);				calc_clip = TRUE;				break;			case CreateNotify:				gmag_events_create_notify_handler (&ev);				calc_clip = TRUE;				break;			case DestroyNotify:				gmag_events_destroy_notify_handler (&ev);				calc_clip = TRUE;				break;			case MapNotify:				gmag_events_map_notify_handler (&ev);				calc_clip = TRUE;				break;			case UnmapNotify:				gmag_events_unmap_notify_handler (&ev);				calc_clip = TRUE;				break;			case ReparentNotify:				gmag_events_reparent_notify_handler (&ev);				calc_clip = TRUE;				break;			}		}#endif /* HAVE_COMPOSITE */#ifdef HAVE_DAMAGE		if (use_damage) {			if (ev.type == damage_event_base + XDamageNotify) {				gmag_events_damage_notify_handler (&ev);			}		}#endif /* HAVE_DAMAGE */#ifdef HAVE_XFIXES		if (ev.type == fixes_event_base + XFixesCursorNotify) {			cursor_changed = TRUE;			cev = (XFixesCursorNotifyEvent *) &ev;		}#endif /* HAVE_XFIXES */	} while (XPending (dpy_conn));#ifndef HAVE_OVERLAY	if (use_composite && mag_window) {		XRaiseWindow (dpy_conn, mag_window);	}#endif /* HAVE_OVERLAY */#ifdef HAVE_DAMAGE	if (!use_composite) {		XDamageSubtract (dpy_conn, root_window_damage, None,				 gmag_events_tmp_region);	}	if (use_damage) {		if (magnifier) {			int i, howmany;			/* TODO: maintain this list on the client instead, to			 * avoid the roundtrip below */#ifdef HAVE_COMPOSITE			if (use_composite) {				rectlist = XFixesFetchRegion (					dpy_conn,					off_screen_region,					&howmany);			} else {#endif /* HAVE_COMPOSITE */				rectlist = XFixesFetchRegion (					dpy_conn, gmag_events_tmp_region,					&howmany);#ifdef HAVE_COMPOSITE			}#endif /* HAVE_COMPOSITE */			if (rectlist == NULL) /* no reply from fetch */				return TRUE;			for (i=0; i < howmany; ++i) {				magnifier_notify_damage (magnifier,							 &rectlist[i]);			}			XFree (rectlist);		}	}#endif /* HAVE_DAMAGE */#ifdef HAVE_COMPOSITE	if (use_composite) {		if (calc_clip) {			gmag_events_calculate_windows_clip ();			gmag_events_paint_windows (exp_region);		}		gmag_events_paint_damaged_windows ();	}#endif /* HAVE_COMPOSITE */#ifdef HAVE_XFIXES	if (cursor_changed) {		if (magnifier->priv->use_source_cursor) {			GdkPixbuf *cursor_pixbuf =				gmag_events_get_source_pixbuf (magnifier);			magnifier_set_cursor_from_pixbuf (magnifier,							  cursor_pixbuf);			if (cursor_pixbuf) g_object_unref (cursor_pixbuf);		} else {			magnifier_set_cursor_pixmap_by_name (magnifier, cev ? gdk_x11_get_xatom_name (cev->cursor_name) : "default", TRUE);		}	  		magnifier_transform_cursor (magnifier);#ifdef CURSOR_DEBUG		if (cev)			g_message ("cursor changed: subtype=%d, " \				   "cursor_serial=%lu, name=[%x] %s\n",				   (int) cev->subtype, cev->cursor_serial,				   (int) cev->cursor_name,				   gdk_x11_get_xatom_name (cev->cursor_name));#endif /* CURSOR_DEBUG */		cursor_changed = FALSE;	}#endif /* HAVE_XFIXES */#ifdef HAVE_COMPOSITE	if (use_composite) {		XFixesSetRegion (dpy_conn, tmp_region, 0, 0);		XFixesSetRegion (dpy_conn, new_region, 0, 0);		XFixesSetRegion (dpy_conn, old_region, 0, 0);		XFixesSetRegion (dpy_conn, exp_region, 0, 0);		XFixesSetRegion (dpy_conn, off_screen_region, 0, 0);	}#endif /* HAVE_COMPOSITE */	XFlush (dpy_conn);#else	return FALSE;#endif /* HAVE_XFIXES */	return TRUE;}static gbooleangmag_events_use_damage (){#ifdef HAVE_DAMAGE	gint major, event, error;	if (XQueryExtension (dpy_conn, "DAMAGE", &major, &event, &error) &&	    !g_getenv ("MAGNIFIER_IGNORE_DAMAGE"))		return TRUE;	return FALSE;#else	return FALSE;#endif /* HAVE_DAMAGE */}static gbooleangmag_events_use_composite (){	if (!gmag_events_use_damage ()) {		return FALSE;	}#ifdef HAVE_COMPOSITE	gint major, event, error;	if (XQueryExtension (dpy_conn, "Composite", &major, &event, &error) &&	    !g_getenv ("MAGNIFIER_IGNORE_COMPOSITE"))		return TRUE;	return FALSE;#else	return FALSE;#endif /* HAVE_COMPOSITE */}voidgmag_events_client_init (Magnifier *magnifier){	GIOChannel               *ioc;	gint                      fd;	gint                      event_base, error_base;#ifdef HAVE_COMPOSITE	XRenderPictureAttributes  pic_attr;	XRenderPictFormat        *format;	GdkDisplay               *gdk_display_connection;	GdkScreen                *gdkscr;	gint                      scr = 0, root_w, root_h;#endif /* HAVE_COMPOSITE */	if (dpy_conn) {		/* remove the old watch */		if (dpy_gsource) 			g_source_remove (dpy_gsource);		XCloseDisplay (dpy_conn);	}	if (magnifier) {		/* we need our own connection here to keep from gumming up the		 * works */		dpy_conn = XOpenDisplay (magnifier->source_display_name); 		root_window = GDK_WINDOW_XWINDOW (magnifier->priv->root);	} else {		dpy_conn = XOpenDisplay (NULL);		root_window = RootWindow (dpy_conn, DefaultScreen (dpy_conn));		g_message ("warning - using DefaultScreen for X connection.");	}#ifdef EVENTS_DEBUG	XSynchronize (dpy_conn, True);#endif /* EVENTS_DEBUG */	fd = ConnectionNumber (dpy_conn);	ioc = g_io_channel_unix_new (fd);	dpy_gsource = g_io_add_watch (ioc,				      G_IO_IN | G_IO_HUP | G_IO_PRI | G_IO_ERR,				      gmag_events_handler, magnifier);	g_io_channel_unref (ioc); #ifdef HAVE_XFIXES	use_damage = gmag_events_use_damage ();	use_composite = gmag_events_use_composite ();	if (!XFixesQueryExtension (dpy_conn, &fixes_event_base,				   &fixes_error_base)) {		g_warning ("XFixes extension not currently active.\n");	} else {		XFixesSelectCursorInput (dpy_conn, root_window,					 XFixesDisplayCursorNotifyMask);		g_message ("added event source to xfixes cursor-notify " \			   "connection");	}#ifdef HAVE_DAMAGE	if (!XDamageQueryExtension (dpy_conn, &damage_event_base,				    &damage_error_base)) {		g_warning ("Damage extension not currently active.\n");	} else if (g_getenv ("MAGNIFIER_IGNORE_DAMAGE")) {		g_warning ("Damage extension being ignored at user request.");	} else {		gmag_events_tmp_region = XFixesCreateRegion (dpy_conn, 0, 0);		if (!use_composite) {			root_window_damage = XDamageCreate (				dpy_conn, root_window,				XDamageReportDeltaRectangles);			/* I don't know why, but without this XDamageSubtract			 * call below the damage events aren't hanled normally.			 * They start to be handled normally, without the call			 * below, only after you move your mouse.			 */			XDamageSubtract (dpy_conn, root_window_damage, None,					 None);		}		g_message ("added event source to damage connection");	}#else	g_warning ("this copy of gnome-mag was built without damage " \		   "extension support.\n");#endif /* HAVE_DAMAGE */#ifdef HAVE_COMPOSITE	if (!XCompositeQueryExtension (dpy_conn, &event_base, &error_base)) {		g_warning ("Composite extension not currently active.\n");	} else if (g_getenv ("MAGNIFIER_IGNORE_COMPOSITE")) {		g_warning ("Composite extension being ignored at user " \			   "request.");	} else if (!use_damage) {		g_setenv ("MAGNIFIER_IGNORE_COMPOSITE", "1", TRUE);		g_warning ("Composite extension being ignored due Damage " \			   "is not actived.");	} else {#ifndef HAVE_OVERLAY		g_warning ("update composite to version 0.3 or higher to " \			   "have overlay window support.\n");#endif /* HAVE_OVERLAY */		gdk_drawable_get_size (magnifier->priv->root, &root_w,				       &root_h);		magnifier->priv->source_drawable = gdk_pixmap_new (			magnifier->priv->root, root_w, root_h, -1);		/* GTK+ uses it's own connection with X, so we must flush that		 * to not receive a BadDrawable when creating a picture of this		 * drawable below. */		gdk_flush ();		gdk_display_connection = gdk_drawable_get_display (			magnifier->priv->root);		gdkscr = gdk_display_get_default_screen (			gdk_display_connection);	    		scr = GDK_SCREEN_XNUMBER (gdkscr);		XCompositeRedirectSubwindows (dpy_conn, root_window,					      CompositeRedirectAutomatic);		off_screen_region = XFixesCreateRegion (			dpy_conn, 0, 0);		tmp_region = XFixesCreateRegion (dpy_conn, 0, 0);		new_region = XFixesCreateRegion (dpy_conn, 0, 0);		old_region = XFixesCreateRegion (dpy_conn, 0, 0);		exp_region = XFixesCreateRegion (dpy_conn, 0, 0);		off_screen_damage = XDamageCreate (				dpy_conn, 				GDK_DRAWABLE_XID (					magnifier->priv->source_drawable),				XDamageReportDeltaRectangles);		format = XRenderFindVisualFormat (			dpy_conn,			DefaultVisual (dpy_conn, scr));		pic_attr.subwindow_mode = IncludeInferiors;		off_screen_picture = XRenderCreatePicture (			dpy_conn,			GDK_DRAWABLE_XID (magnifier->priv->source_drawable),			format, CPSubwindowMode, &pic_attr);		gmag_events_create_windows_list (gdk_display_connection,						 gdkscr);		gmag_events_calculate_windows_clip ();		g_message ("added event source to composite connection");	}#else	g_warning ("this copy of gnome-mag was built without composite " \		   "extension support.\n");#endif /* HAVE_COMPOSITE */#else	g_warning ("this copy of gnome-mag was built without xfixes " \		   "extension support.\n");	#endif /* HAVE_XFIXES */	XFlush (dpy_conn);}

⌨️ 快捷键说明

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