📄 gdkwindow.c
字号:
while (tmp_list) { new_list = g_list_prepend (new_list, tmp_list->data); tmp_list = tmp_list->next; } return new_list;}/* * propagate the shapes from all child windows of a GDK window to the parent * window. Shamelessly ripped from Enlightenment's code * * - Raster */struct _gdk_span{ gint start; gint end; struct _gdk_span *next;};static voidgdk_add_to_span (struct _gdk_span **s, gint x, gint xx){ struct _gdk_span *ptr1, *ptr2, *noo, *ss; gchar spanning; ptr2 = NULL; ptr1 = *s; spanning = 0; ss = NULL; /* scan the spans for this line */ while (ptr1) { /* -- -> new span */ /* == -> existing span */ /* ## -> spans intersect */ /* if we are in the middle of spanning the span into the line */ if (spanning) { /* case: ---- ==== */ if (xx < ptr1->start - 1) { /* ends before next span - extend to here */ ss->end = xx; return; } /* case: ----##=== */ else if (xx <= ptr1->end) { /* crosses into next span - delete next span and append */ ss->end = ptr1->end; ss->next = ptr1->next; g_free (ptr1); return; } /* case: ---###--- */ else { /* overlaps next span - delete and keep checking */ ss->next = ptr1->next; g_free (ptr1); ptr1 = ss; } } /* otherwise havent started spanning it in yet */ else { /* case: ---- ==== */ if (xx < ptr1->start - 1) { /* insert span here in list */ noo = g_malloc (sizeof (struct _gdk_span)); if (noo) { noo->start = x; noo->end = xx; noo->next = ptr1; if (ptr2) ptr2->next = noo; else *s = noo; } return; } /* case: ----##=== */ else if ((x < ptr1->start) && (xx <= ptr1->end)) { /* expand this span to the left point of the new one */ ptr1->start = x; return; } /* case: ===###=== */ else if ((x >= ptr1->start) && (xx <= ptr1->end)) { /* throw the span away */ return; } /* case: ---###--- */ else if ((x < ptr1->start) && (xx > ptr1->end)) { ss = ptr1; spanning = 1; ptr1->start = x; ptr1->end = xx; } /* case: ===##---- */ else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end)) { ss = ptr1; spanning = 1; ptr1->end = xx; } /* case: ==== ---- */ /* case handled by next loop iteration - first case */ } ptr2 = ptr1; ptr1 = ptr1->next; } /* it started in the middle but spans beyond your current list */ if (spanning) { ptr2->end = xx; return; } /* it does not start inside a span or in the middle, so add it to the end */ noo = g_malloc (sizeof (struct _gdk_span)); if (noo) { noo->start = x; noo->end = xx; if (ptr2) { noo->next = ptr2->next; ptr2->next = noo; } else { noo->next = NULL; *s = noo; } } return;}static voidgdk_add_rectangles (Display *disp, Window win, struct _gdk_span **spans, gint basew, gint baseh, gint x, gint y){ gint a, k; gint x1, y1, x2, y2; gint rn, ord; XRectangle *rl; rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord); if (rl) { /* go through all clip rects in this window's shape */ for (k = 0; k < rn; k++) { /* for each clip rect, add it to each line's spans */ x1 = x + rl[k].x; x2 = x + rl[k].x + (rl[k].width - 1); y1 = y + rl[k].y; y2 = y + rl[k].y + (rl[k].height - 1); if (x1 < 0) x1 = 0; if (y1 < 0) y1 = 0; if (x2 >= basew) x2 = basew - 1; if (y2 >= baseh) y2 = baseh - 1; for (a = y1; a <= y2; a++) { if ((x2 - x1) >= 0) gdk_add_to_span (&spans[a], x1, x2); } } XFree (rl); }}static voidgdk_propagate_shapes (Display *disp, Window win, gboolean merge){ Window rt, par, *list = NULL; gint i, j, num = 0, num_rects = 0; gint x, y, contig; guint w, h, d; gint baseh, basew; XRectangle *rects = NULL; struct _gdk_span **spans = NULL, *ptr1, *ptr2, *ptr3; XWindowAttributes xatt; XGetGeometry (disp, win, &rt, &x, &y, &w, &h, &d, &d); if (h <= 0) return; basew = w; baseh = h; spans = g_malloc (sizeof (struct _gdk_span *) * h); for (i = 0; i < h; i++) spans[i] = NULL; XQueryTree (disp, win, &rt, &par, &list, (unsigned int *)&num); if (list) { /* go through all child windows and create/insert spans */ for (i = 0; i < num; i++) { if (XGetWindowAttributes (disp, list[i], &xatt) && (xatt.map_state != IsUnmapped)) if (XGetGeometry (disp, list[i], &rt, &x, &y, &w, &h, &d, &d)) gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y); } if (merge) gdk_add_rectangles (disp, win, spans, basew, baseh, x, y); /* go through the spans list and build a list of rects */ rects = g_malloc (sizeof (XRectangle) * 256); num_rects = 0; for (i = 0; i < baseh; i++) { ptr1 = spans[i]; /* go through the line for all spans */ while (ptr1) { rects[num_rects].x = ptr1->start; rects[num_rects].y = i; rects[num_rects].width = ptr1->end - ptr1->start + 1; rects[num_rects].height = 1; j = i + 1; /* if there are more lines */ contig = 1; /* while contigous rects (same start/end coords) exist */ while ((contig) && (j < baseh)) { /* search next line for spans matching this one */ contig = 0; ptr2 = spans[j]; ptr3 = NULL; while (ptr2) { /* if we have an exact span match set contig */ if ((ptr2->start == ptr1->start) && (ptr2->end == ptr1->end)) { contig = 1; /* remove the span - not needed */ if (ptr3) { ptr3->next = ptr2->next; g_free (ptr2); ptr2 = NULL; } else { spans[j] = ptr2->next; g_free (ptr2); ptr2 = NULL; } break; } /* gone past the span point no point looking */ else if (ptr2->start < ptr1->start) break; if (ptr2) { ptr3 = ptr2; ptr2 = ptr2->next; } } /* if a contiguous span was found increase the rect h */ if (contig) { rects[num_rects].height++; j++; } } /* up the rect count */ num_rects++; /* every 256 new rects increase the rect array */ if ((num_rects % 256) == 0) rects = g_realloc (rects, sizeof (XRectangle) * (num_rects + 256)); ptr1 = ptr1->next; } } /* set the rects as the shape mask */ if (rects) { XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects, ShapeSet, YXSorted); g_free (rects); } XFree (list); } /* free up all the spans we made */ for (i = 0; i < baseh; i++) { ptr1 = spans[i]; while (ptr1) { ptr2 = ptr1; ptr1 = ptr1->next; g_free (ptr2); } } g_free (spans);}voidgdk_window_set_child_shapes (GdkWindow *window){ GdkWindowPrivate *private; g_return_if_fail (window != NULL); #ifdef HAVE_SHAPE_EXT private = (GdkWindowPrivate*) window; if (private->destroyed) return; if (gdk_window_have_shape_ext ()) gdk_propagate_shapes (private->xdisplay, private->xwindow, FALSE);#endif }voidgdk_window_merge_child_shapes (GdkWindow *window){ GdkWindowPrivate *private; g_return_if_fail (window != NULL); #ifdef HAVE_SHAPE_EXT private = (GdkWindowPrivate*) window; if (private->destroyed) return; if (gdk_window_have_shape_ext ()) gdk_propagate_shapes (private->xdisplay, private->xwindow, TRUE);#endif }/************************************************************* * gdk_window_is_visible: * Check if the given window is mapped. * arguments: * window: * results: * is the window mapped *************************************************************/gboolean gdk_window_is_visible (GdkWindow *window){ GdkWindowPrivate *private = (GdkWindowPrivate *)window; g_return_val_if_fail (window != NULL, FALSE); return private->mapped;}/************************************************************* * gdk_window_is_viewable: * Check if the window and all ancestors of the window * are mapped. (This is not necessarily "viewable" in * the X sense, since we only check as far as we have * GDK window parents, not to the root window) * arguments: * window: * results: * is the window viewable *************************************************************/gboolean gdk_window_is_viewable (GdkWindow *window){ GdkWindowPrivate *private = (GdkWindowPrivate *)window; g_return_val_if_fail (window != NULL, FALSE); while (private && (private != &gdk_root_parent) && (private->window_type != GDK_WINDOW_FOREIGN)) { if (!private->mapped) return FALSE; private = (GdkWindowPrivate *)private->parent; } return TRUE;}void gdk_drawable_set_data (GdkDrawable *drawable, const gchar *key, gpointer data, GDestroyNotify destroy_func){ g_dataset_set_data_full (drawable, key, data, destroy_func);}/* Support for windows that can be guffaw-scrolled * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt) */static gbooleangdk_window_gravity_works (void){ enum { UNKNOWN, NO, YES }; static gint gravity_works = UNKNOWN; if (gravity_works == UNKNOWN) { GdkWindowAttr attr; GdkWindow *parent; GdkWindow *child; gint y; /* This particular server apparently has a bug so that the test * works but the actual code crashes it */ if ((!strcmp (XServerVendor (gdk_display), "Sun Microsystems, Inc.")) && (VendorRelease (gdk_display) == 3400)) { gravity_works = NO; return FALSE; } attr.window_type = GDK_WINDOW_TEMP; attr.wclass = GDK_INPUT_OUTPUT; attr.x = 0; attr.y = 0; attr.width = 100; attr.height = 100; attr.event_mask = 0; parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y); attr.window_type = GDK_WINDOW_CHILD; child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y); gdk_window_set_static_win_gravity (child, TRUE); gdk_window_resize (parent, 100, 110); gdk_window_move (parent, 0, -10); gdk_window_move_resize (parent, 0, 0, 100, 100); gdk_window_resize (parent, 100, 110); gdk_window_move (parent, 0, -10); gdk_window_move_resize (parent, 0, 0, 100, 100); gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL); gdk_window_destroy (parent); gdk_window_destroy (child); gravity_works = ((y == -20) ? YES : NO); } return (gravity_works == YES);}static voidgdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on){ GdkWindowPrivate *private = (GdkWindowPrivate *)window; XSetWindowAttributes xattributes; g_return_if_fail (window != NULL); xattributes.bit_gravity = on ? StaticGravity : ForgetGravity; XChangeWindowAttributes (private->xdisplay, private->xwindow, CWBitGravity, &xattributes);}static voidgdk_window_set_static_win_gravity (GdkWindow *window, gboolean on){ GdkWindowPrivate *private = (GdkWindowPrivate *)window; XSetWindowAttributes xattributes; g_return_if_fail (window != NULL); xattributes.win_gravity = on ? StaticGravity : NorthWestGravity; XChangeWindowAttributes (private->xdisplay, private->xwindow, CWWinGravity, &xattributes);}/************************************************************* * gdk_window_set_static_gravities: * Set the bit gravity of the given window to static, * and flag it so all children get static subwindow * gravity. * arguments: * window: window for which to set static gravity * use_static: Whether to turn static gravity on or off. * results: * Does the XServer support static gravity? *************************************************************/gboolean gdk_window_set_static_gravities (GdkWindow *window, gboolean use_static){ GdkWindowPrivate *private = (GdkWindowPrivate *)window; GList *tmp_list; g_return_val_if_fail (window != NULL, FALSE); if (!use_static == !private->guffaw_gravity) return TRUE; if (use_static && !gdk_window_gravity_works ()) return FALSE; private->guffaw_gravity = use_static; gdk_window_set_static_bit_gravity (window, use_static); tmp_list = private->children; while (tmp_list) { gdk_window_set_static_win_gravity (window, use_static); tmp_list = tmp_list->next; } return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -