📄 gmag-events.c
字号:
/* * 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 + -