如何实现从Visual*到GdkVisual*的转换?已掌握反向转换API
Visual* to GdkVisual* 确实,GTK+ doesn't offer a direct reverse API for gdk_x11_visual_get_xvisual(), but there are a couple of reliable workarounds to get this done:
Method 1: Iterate through all available GdkVisuals and match the X11 Visual*
This is the most straightforward approach—enumerate all GdkVisual instances for your display/screen, extract their corresponding X11 Visual* using gdk_x11_visual_get_xvisual(), and compare to find a match with your target Visual*.
Example code:
GdkVisual* x11_visual_to_gdk_visual(Visual* x11_visual) { if (!x11_visual) return NULL; GdkDisplay* display = gdk_display_get_default(); GdkScreen* screen = gdk_display_get_default_screen(display); GList* visuals = gdk_screen_list_visuals(screen); GdkVisual* matched_visual = NULL; for (GList* l = visuals; l != NULL; l = l->next) { GdkVisual* current = GDK_VISUAL(l->data); Visual* current_x11_visual = gdk_x11_visual_get_xvisual(current); if (current_x11_visual == x11_visual) { matched_visual = current; g_object_ref(matched_visual); // Add reference to avoid accidental destruction later break; } } g_list_free(visuals); return matched_visual; }
Key Notes:
- Always call
g_object_ref()on the matchedGdkVisual—the list returned bygdk_screen_list_visuals()doesn't add extra references, so you need to hold your own if you plan to keep the object long-term. - If no match is found, it means the X11
Visual*isn't supported by the current GDK screen. Make sure to handle theNULLreturn case in your code.
Method 2: Narrow down candidates using visual properties first
If you know the depth or visual class (like TrueColor, PseudoColor) of your target Visual*, you can filter candidates before comparing pointers to speed things up:
GdkVisual* x11_visual_to_gdk_visual_by_properties(Visual* x11_visual) { if (!x11_visual) return NULL; GdkDisplay* display = gdk_display_get_default(); GdkScreen* screen = gdk_display_get_default_screen(display); int depth = x11_visual->depth; GdkVisualType visual_type = GDK_VISUAL_INVALID; // Map X11 visual class to GdkVisualType switch (x11_visual->class) { case StaticGray: visual_type = GDK_STATIC_GRAY; break; case GrayScale: visual_type = GDK_GRAYSCALE; break; case StaticColor: visual_type = GDK_STATIC_COLOR; break; case PseudoColor: visual_type = GDK_PSEUDO_COLOR; break; case TrueColor: visual_type = GDK_TRUE_COLOR; break; case DirectColor: visual_type = GDK_DIRECT_COLOR; break; default: visual_type = GDK_VISUAL_INVALID; break; } // Check if a matching type exists first GdkVisual* candidate = gdk_screen_get_visual_by_type(screen, visual_type); if (candidate) { Visual* candidate_x11 = gdk_x11_visual_get_xvisual(candidate); if (candidate_x11 == x11_visual) { g_object_ref(candidate); return candidate; } } // Fall back to full iteration if type-based lookup fails return x11_visual_to_gdk_visual(x11_visual); }
This reduces the number of comparisons needed in most cases, but you still need to verify the pointer match—multiple visuals can share the same type and depth.
Extra Tips
- For multi-screen setups, don't rely solely on the default screen. Use
XVisualIDFromVisual()to get the visual ID, then match it against the X screen ID fromgdk_x11_screen_get_xscreen()to find the correctGdkScreen. - Remember to call
g_object_unref()on theGdkVisual*when you're done with it to avoid memory leaks.
内容的提问来源于stack exchange,提问作者Naseeb Panghal

