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 + -
显示快捷键?