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

📄 gmag-events.c

📁 在Linux下实现magnification功能
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * GNOME-MAG Magnification service for GNOME * * Copyright 2006 Carlos Eduardo Rodrigues Di骻enes * Copyright 2004 Sun Microsystems Inc. (damage-client.c) * Copyright 2001 Sun Microsystems Inc. (magnifier.c) * * 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 "gmag-events.h"#include <stdlib.h>#include <X11/Xlib.h>#ifdef HAVE_XFIXES#include <X11/extensions/Xfixes.h>#ifdef HAVE_DAMAGE#include <X11/extensions/Xdamage.h>#ifdef HAVE_COMPOSITE#include <X11/extensions/Xrender.h>#include <X11/extensions/Xcomposite.h>#endif /* HAVE_COMPOSITE */#endif /* HAVE_DAMAGE */#endif /* HAVE_XFIXES */#include <glib.h>#include <gdk/gdkx.h>#include <gtk/gtk.h>static Display       *dpy_conn = NULL;static guint          dpy_gsource = 0;static Window         root_window, mag_window;static gboolean       use_damage, use_composite;gint                  fixes_event_base = 0, fixes_error_base;#ifdef HAVE_XFIXES#ifdef HAVE_DAMAGEstatic gint           damage_event_base, damage_error_base;static Damage         root_window_damage;static XserverRegion  gmag_events_tmp_region;#ifdef HAVE_COMPOSITEstatic GQueue        *mag_windows_list;static Damage         off_screen_damage;static Picture        off_screen_picture;static XserverRegion  off_screen_region;static XserverRegion  tmp_region, new_region, old_region, exp_region;#endif /* HAVE_COMPOSITE */#endif /* HAVE_DAMAGE */#endif /* HAVE_XFIXES */#define EVENTS_DEBUG#undef  EVENTS_DEBUG#ifdef  EVENTS_DEBUG#ifdef HAVE_DAMAGE#define DAMAGE_DEBUG#undef  DAMAGE_DEBUG#endif /* HAVE_DAMAGE */#ifdef HAVE_COMPOSITE#define COMPOSITE_DEBUG#undef  COMPOSITE_DEBUG#endif /* HAVE_COMPOSITE */#ifdef HAVE_XFIXES#define CURSOR_DEBUG#undef  CURSOR_DEBUG#define XFIXES_DEBUG#undef  XFIXES_DEBUG#endif /* HAVE_XFIXES */#endif /* EVENTS_DEBUG */#ifdef HAVE_XFIXES#ifdef HAVE_COMPOSITE/* * GCompareFunc used in g_queue_find_custom to find windows in * mag_windows_list. */static gintgmag_events_g_compare_func (GmagWinPtr pgmag_win, Window xwin){	if (pgmag_win->xwin == xwin)		return 0;	return 1;}/* * Calculates the clip for all windows in mag_windows_list. */static voidgmag_events_calculate_windows_clip (){	GList         *elem = NULL;	XserverRegion clipSum;	clipSum = XFixesCreateRegion (dpy_conn, 0, 0);	elem = g_queue_peek_tail_link (mag_windows_list);	if (!elem) {		XFixesDestroyRegion (dpy_conn, clipSum);		return;	}	do {		GmagWinPtr pgmag_win = (GmagWinPtr) elem->data;		if (pgmag_win->pic)			if (pgmag_win->attr.map_state == IsViewable) {				XFixesCopyRegion (					dpy_conn,					pgmag_win->clip,					XFixesCreateRegionFromWindow (						dpy_conn,						pgmag_win->xwin,						WindowRegionBounding));				XFixesTranslateRegion (					dpy_conn,					pgmag_win->clip, pgmag_win->attr.x,					pgmag_win->attr.y);				XFixesCopyRegion (					dpy_conn,					pgmag_win->win_region,					pgmag_win->clip);				XFixesSubtractRegion (					dpy_conn,					pgmag_win->clip, pgmag_win->clip,					clipSum);				XFixesUnionRegion (					dpy_conn,					clipSum, clipSum,					pgmag_win->win_region);			}	} while ((elem = g_list_previous (elem)));	XFixesDestroyRegion (dpy_conn, clipSum);}/* * Calculates the clip of a single window in mag_windows_list. */static voidgmag_events_calculate_window_clip (GmagWinPtr pgmag_win_newclip){	GList         *elem = NULL;	XserverRegion clipSum;	clipSum = XFixesCreateRegion (dpy_conn, 0, 0);	elem = g_queue_peek_tail_link (mag_windows_list);	if (!elem) {		XFixesDestroyRegion (dpy_conn, clipSum);		return;	}	do {		GmagWinPtr pgmag_win = (GmagWinPtr) elem->data;		if (pgmag_win->xwin == pgmag_win_newclip->xwin) {			/* the window that must have a new clip was founded */			XFixesCopyRegion (				dpy_conn,				pgmag_win->clip,				XFixesCreateRegionFromWindow (					dpy_conn,					pgmag_win->xwin,					WindowRegionBounding));			XFixesTranslateRegion (dpy_conn,					       pgmag_win->clip,					       pgmag_win->attr.x,					       pgmag_win->attr.y);			XFixesCopyRegion (dpy_conn,					  pgmag_win->win_region,					  pgmag_win->clip);			XFixesSubtractRegion (dpy_conn,					      pgmag_win->clip, pgmag_win->clip,					      clipSum);			break;		}		if (pgmag_win->pic)			if (pgmag_win->attr.map_state == IsViewable) {				XFixesUnionRegion (					dpy_conn,					clipSum, clipSum,					pgmag_win->win_region);			}	} while ((elem = g_list_previous (elem)));	XFixesDestroyRegion (dpy_conn, clipSum);}/* * Paint a window. If region is None, the window clip region is painted, else * the intersection of the window clip region and region is painted. */static voidgmag_events_paint_window (GmagWinPtr pgmag_win, XserverRegion region){	static XserverRegion final_clip = None;	if (!pgmag_win->damaged && !region)		return;	if (!pgmag_win->pic)		return;	if (pgmag_win->attr.map_state != IsViewable)		return;	if (!final_clip)		final_clip = XFixesCreateRegion (			dpy_conn, 0, 0);	XFixesSetRegion (dpy_conn, final_clip, 0, 0);	if (region) {		XFixesIntersectRegion (dpy_conn,				       final_clip, region, pgmag_win->clip);		XFixesSetPictureClipRegion (dpy_conn,					    pgmag_win->pic,					    -(pgmag_win->attr.x),					    -(pgmag_win->attr.y), final_clip);	} else		XFixesSetPictureClipRegion (dpy_conn,					    pgmag_win->pic,					    -(pgmag_win->attr.x),					    -(pgmag_win->attr.y),					    pgmag_win->clip);	XRenderComposite (dpy_conn, PictOpSrc,			  pgmag_win->pic, None, off_screen_picture,			  0, 0, 0, 0, pgmag_win->attr.x, pgmag_win->attr.y,			  pgmag_win->attr.width, pgmag_win->attr.height);}/* * Paint all the windows in mag_windows_list with the specified * exposedRegion. */static voidgmag_events_paint_windows (XserverRegion exposedRegion){	GList      *elem;	GmagWinPtr  pgmag_win;	elem = g_queue_peek_head_link (mag_windows_list);	while (elem) {		pgmag_win = (GmagWinPtr) elem->data;		gmag_events_paint_window (pgmag_win, exposedRegion);		elem = g_list_next (elem);	}}/* * Sometimes XGetWindowAttributes fail (when the window is destroied), so we * put default values in it to not have problems in other parts of the program. * I think that only some ones need to be setted, but this was copied from * Compiz, so... */static voidgmag_events_set_default_window_attributes (XWindowAttributes *wa){	wa->x		          = 0;	wa->y		          = 0;	wa->width		  = 1;	wa->height		  = 1;	wa->border_width	  = 0;	wa->depth		  = 0;	wa->visual		  = NULL;	wa->root		  = None;	wa->class		  = InputOnly;	wa->bit_gravity	          = NorthWestGravity;	wa->win_gravity	          = NorthWestGravity;	wa->backing_store	  = NotUseful;	wa->backing_planes	  = 0;	wa->backing_pixel	  = 0;	wa->save_under	          = FALSE;	wa->colormap	          = None;	wa->map_installed	  = FALSE;	wa->map_state	          = IsUnviewable;	wa->all_event_masks	  = 0;	wa->your_event_mask	  = 0;	wa->do_not_propagate_mask = 0;	wa->override_redirect     = TRUE;	wa->screen		  = NULL;}/* * Creates the necessary information of a redirected window and add it to * mag_windows_list. */static voidgmag_events_add_window (Window xwin){	GmagWinPtr                new;	XRenderPictureAttributes  pic_attr;	XRenderPictFormat        *format;	new = (GmagWinPtr) malloc (sizeof (GmagWin));	if (!new)		g_error ("can't allocate GmagWin (struct _GmagWin)");	if (!XGetWindowAttributes (dpy_conn, xwin,				   &new->attr))		gmag_events_set_default_window_attributes (&new->attr);	new->xwin = xwin;	if (new->attr.class == InputOnly) {		new->pic = None;		new->damage = None;		new->damaged = FALSE;		new->damaged_region = None;	} else {		format = XRenderFindVisualFormat (			dpy_conn, new->attr.visual);		pic_attr.subwindow_mode = IncludeInferiors;		new->pic = XRenderCreatePicture (			dpy_conn, xwin, format,			CPSubwindowMode, &pic_attr);		new->damage = XDamageCreate (dpy_conn, xwin,					     XDamageReportDeltaRectangles);		new->damaged = TRUE;		new->damaged_region = XFixesCreateRegion (dpy_conn, 0, 0);		new->clip = XFixesCreateRegion (dpy_conn, 0, 0);		new->win_region = XFixesCreateRegion (dpy_conn, 0, 0);	}		g_queue_push_tail (mag_windows_list, new);}/* * Create the mag_windows_list querying the xserver for the actual * windows and adding them to the windows list. */static voidgmag_events_create_windows_list (){	Window  root_return, parent_return, *children;	guint   nchildren;	gint    i;	if (!mag_windows_list)		mag_windows_list = g_queue_new ();	XGrabServer (dpy_conn);	XSelectInput (dpy_conn, root_window,		      SubstructureNotifyMask);	XQueryTree (dpy_conn, root_window,		    &root_return, &parent_return, &children, &nchildren);	for (i = 0; i < nchildren; i++)		gmag_events_add_window (children[i]);	XFree (children);	XUngrabServer (dpy_conn);}/* * Destroy the window resources and remove it from the * mag_windows_list. */static voidgmag_events_remove_window (Window xwin){	GList     *elem = NULL;	GmagWinPtr pgmag_win;	elem = g_queue_find_custom (mag_windows_list,				    (gconstpointer) xwin,				    (GCompareFunc) gmag_events_g_compare_func);	if (elem) {		pgmag_win = (GmagWinPtr) elem->data;		g_queue_remove (mag_windows_list, pgmag_win);		XFixesDestroyRegion (dpy_conn,				     pgmag_win->clip);		XFixesDestroyRegion (dpy_conn,				     pgmag_win->win_region);		free (pgmag_win);	}}/* * Add a window damaged region, making a union with the actual damaged region, * to the window in mag_windows_list. */static voidgmag_events_add_win_damaged_region (Window xwin, XserverRegion region){	GList      *elem;	GmagWinPtr  pgmag_win;	elem = g_queue_find_custom (mag_windows_list,				    (gconstpointer) xwin,				    (GCompareFunc) gmag_events_g_compare_func);	if (elem) {

⌨️ 快捷键说明

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