📄 zoom-region.c
字号:
/* * 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 <stdlib.h>#include <string.h>#include <popt.h>#ifdef HAVE_COLORBLIND#include <colorblind.h>#endif /* HAVE_COLORBLIND */#include <gdk/gdkwindow.h>#include <gtk/gtk.h>#ifdef USE_GDKPIXBUF_RENDER_TO_DRAWABLE#include <gdk/gdkpixbuf.h>#else#include <gdk/gdk.h>#endif#include <gdk/gdkx.h>#include <gdk/gdkrgb.h>#include <libbonobo.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/cursorfont.h>#include <X11/extensions/XTest.h>#include <math.h>#undef ZOOM_REGION_DEBUG#include "zoom-region.h"#include "zoom-region-private.h"#include "magnifier.h" /* needed to access parent data */#include "magnifier-private.h" /* needed to access parent data */#define DEBUG_CLIENT_CALLS#ifdef DEBUG_CLIENT_CALLSstatic gboolean client_debug = FALSE;#define DBG(a) if (client_debug) { (a); }#else#define DBG(a) #endifstatic GObjectClass *parent_class = NULL;enum { ZOOM_REGION_MANAGED_PROP, ZOOM_REGION_POLL_MOUSE_PROP, ZOOM_REGION_SMOOTHSCROLL_PROP, ZOOM_REGION_COLORBLIND_PROP, ZOOM_REGION_INVERT_PROP, ZOOM_REGION_SMOOTHING_PROP, ZOOM_REGION_CONTRASTR_PROP, ZOOM_REGION_CONTRASTG_PROP, ZOOM_REGION_CONTRASTB_PROP, ZOOM_REGION_BRIGHTR_PROP, ZOOM_REGION_BRIGHTG_PROP, ZOOM_REGION_BRIGHTB_PROP, ZOOM_REGION_XSCALE_PROP, ZOOM_REGION_YSCALE_PROP, ZOOM_REGION_BORDERSIZE_PROP, ZOOM_REGION_BORDERCOLOR_PROP, ZOOM_REGION_XALIGN_PROP, ZOOM_REGION_YALIGN_PROP, ZOOM_REGION_VIEWPORT_PROP, ZOOM_REGION_TESTPATTERN_PROP, ZOOM_REGION_TIMING_TEST_PROP, ZOOM_REGION_TIMING_OUTPUT_PROP, ZOOM_REGION_TIMING_PAN_RATE_PROP, ZOOM_REGION_EXIT_MAGNIFIER} PropIdx;#ifdef DEBUG_CLIENT_CALLSgchar* prop_names[ZOOM_REGION_EXIT_MAGNIFIER + 1] = { "MANAGED", "POLLMOUSE" "SMOOTHSCROLL", "INVERT", "SMOOTHING", "CONTRASTR", "CONTRASTG", "CONTRASTB", "XSCALE", "YSCALE", "BORDERSIZE", "BORDERCOLOR", "XALIGN", "YALIGN", "VIEWPORT", "TESTPATTERN", "TIMING_TEST", "TIMING_OUTPUT", "TIMING_PAN_RATE", "EXIT_MAGNIFIER"};#endiftypedef enum { ZOOM_REGION_ERROR_NONE, ZOOM_REGION_ERROR_NO_TARGET_DRAWABLE, ZOOM_REGION_ERROR_TOO_BIG} ZoomRegionPixmapCreationError;static float timing_scale_max = 0;static float timing_idle_max = 0;static float timing_frame_max = 0;static float cps_max = 0;static float nrr_max = 0;static float update_nrr_max = 0;static gboolean reset_timing = FALSE;static gboolean timing_test = FALSE;static guint pending_idle_handler = 0;static gboolean processing_updates = FALSE;static gboolean timing_start = FALSE;#ifdef TEST_XTST_CURSORstatic Cursor *x_cursors;static Window cursor_window = None;#endifstatic gboolean can_coalesce = TRUE ; /* change this when event coalescing is working */#define CLAMP_B_C(v) (t = (v), CLAMP (t, -1, 1));static void zoom_region_sync (ZoomRegion *region);static void zoom_region_finalize (GObject *object);static void zoom_region_update (ZoomRegion *zoom_region, const GdkRectangle rect);static void zoom_region_queue_update (ZoomRegion *zoom_region, const GdkRectangle rect);static int zoom_region_process_updates (gpointer data);static void zoom_region_paint (ZoomRegion *zoom_region, GdkRectangle *rect);static void zoom_region_paint_pixmap (ZoomRegion *zoom_region, GdkRectangle *rect);static int zoom_region_update_pointer_timeout (gpointer data);static GdkRectangle zoom_region_rect_from_bounds (ZoomRegion *zoom_region, const GNOME_Magnifier_RectBounds *bounds);static ZoomRegionPixmapCreationError zoom_region_create_pixmap (ZoomRegion *zoom_region);static GdkRectangle zoom_region_update_pixmap (ZoomRegion *zoom_region, const GdkRectangle update_rect, GdkRectangle *paint_rect);voidreset_timing_stats(){ timing_scale_max = 0; timing_idle_max = 0; timing_frame_max = 0; cps_max = 0; nrr_max = 0; update_nrr_max = 0; mag_timing.num_scale_samples = 0; mag_timing.num_idle_samples = 0; mag_timing.num_frame_samples = 0; mag_timing.num_line_samples = 0; mag_timing.scale_total = 0; mag_timing.idle_total = 0; mag_timing.frame_total = 0; mag_timing.update_pixels_total = 0; mag_timing.update_pixels_total = 0; mag_timing.dx_total = 0; mag_timing.dy_total = 0; mag_timing.last_frame_val = 0; mag_timing.last_dy = 0; g_timer_start (mag_timing.process);}/** DEBUG STUFF **/#undef DEBUG#ifdef DEBUG#define DEBUG_RECT(a, b) _debug_announce_rect (a, b)#else#define DEBUG_RECT(a, b) #endifstatic void_debug_announce_rect (char *msg, GdkRectangle rect){ fprintf (stderr, "%s: (%d,%d - %d,%d)\n", msg, rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);}static gboolean_diff_pixbufs (const GdkPixbuf *a, const GdkPixbuf *b){ long i, j; int bits_per_byte = 8; /* always true? */ guchar *pa = gdk_pixbuf_get_pixels (a); guchar *pb = gdk_pixbuf_get_pixels (b); guchar *cpa, *cpb; long rsa = gdk_pixbuf_get_rowstride (a); long rsb = gdk_pixbuf_get_rowstride (b); long rowbytes = gdk_pixbuf_get_width (a) * gdk_pixbuf_get_bits_per_sample (a) * gdk_pixbuf_get_n_channels (a)/ bits_per_byte; long n_rows = gdk_pixbuf_get_height (a); if (gdk_pixbuf_get_height (b) != n_rows) return TRUE; if (gdk_pixbuf_get_width (b) != gdk_pixbuf_get_width (a)) return TRUE; for (j = 0; j < n_rows; ++j) { cpa = pa + j * rsa; cpb = pb + j * rsb; for (i = 0; i < rowbytes; ++i) { if (*cpa != *cpb) { return TRUE; } cpa++; cpb++; } } return FALSE;}/** EVENT COALESCING **/#ifdef BROKEN_COALESCE_STUFF_GETS_FIXED/** * _combine_rects: * combines two GdkRectangles IFF the union of the two form * a rectangle. * a: the first GdkRectangle, which will be changed to the new bounds if * coalesce operation can be performed, otherwise unchanged. * b: the second GdkRectangle. * returns: True if the two are coalesced, FALSE otherwise. **/static gboolean_combine_rects (GdkRectangle *a, GdkRectangle *b){ gboolean can_combine = FALSE; if ((a->x == b->x) && (a->x + a->width == b->x + b->width)) { can_combine = TRUE; } else if ((a->y == b->y) && (a->y + a->height == b->y + b->height)) { can_combine = TRUE; } if (can_combine) { GdkRectangle c; /* TODO: check and fix this */ if (gdk_rectangle_intersect (a, b, &c)) { gdk_rectangle_union (a, b, &c); *a = c; can_combine = TRUE; } else { can_combine = FALSE; } } return can_combine;}/** * _refactor_rects: * Refactor GdkRectangles whose union forms an 'L' shape, swapping * the long and short elements. e.g. turns * * xxx xxx * xxx xxx * oooooo into oooxxx * oooooo oooxxx * * returns: TRUE if the refactor was performed, FALSE if it could not be * completed (i.e. if the rectangles did not form a suitable union). **/static gboolean_refactor_rects (GdkRectangle *p, GdkRectangle *n){ gboolean refactored = FALSE; GdkRectangle *a, *b; if (p->x == n->x) { if (p->width < n->width) { a = p; b = n; } else { a = n; b = p; } if (a->y == b->y + b->height) { a->y -= b->height; a->height += b->height; b->x += a->width; b->width -= a->width; refactored = TRUE; } else if (a->y + a->height == b->y) { a->height += b->height; b->x += a->width; b->width -= a->width; refactored = TRUE; } if (refactored) fprintf (stderr, "REFACTOR 1\n"); } else if (p->y == n->y) { if (p->height < n->height) { a = p; b = n; } else { a = n; b = p; } if (a->x == b->x + b->width) { a->x -= b->width; a->width += b->width; b->y += a->height; b->height -= a->height; refactored = TRUE; } else if (a->x + a->width == b->x) { a->width += b->width; b->y += a->height; b->height -= a->height; refactored = TRUE; } if (refactored) fprintf (stderr, "REFACTOR 2\n"); } else if (p->x + p->width == n->x + n->width) { if (p->width < n->width) { a = p; b = n; } else { a = n; b = p; } if (a->y == b->y + b->height) { a->y -= b->height; a->height += b->height; b->width -= a->width; refactored = TRUE; } else if (a->y + a->height == b->y) { a->height += b->height; b->width -= a->width; refactored = TRUE; } if (refactored) fprintf (stderr, "REFACTOR 3\n"); } else if (p->y + p->height == n->y + n->height) { if (p->height < n->height) { a = p; b = n; } else { a = n; b = p; } if (a->x == b->x + b->width) { a->x -= b->width; a->width += b->width; b->height -= a->height; refactored = TRUE; } else if (a->x + a->width == b->x) { a->width += b->width; b->height -= a->height; refactored = TRUE; } if (refactored) fprintf (stderr, "REFACTOR 4\n"); } return refactored;}static GList*_combine_update_rects (GList *q, int lookahead_n){ int i = 0; GdkRectangle *a = q->data; GList *p = q; while (i < lookahead_n && p && p->next) { if (_combine_rects (a, q->next->data)) { q = g_list_delete_link (q, p->next); } else { p = p->next; ++i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -