1 | /* |
2 | * Copyright (c) 2014 Red Hat, Inc. |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | #include "config.h" |
19 | #include <glib/gi18n-lib.h> |
20 | |
21 | #include "general.h" |
22 | #include "window.h" |
23 | |
24 | #include "gtkdebug.h" |
25 | #include "gtklabel.h" |
26 | #include "gtkscale.h" |
27 | #include "gtkswitch.h" |
28 | #include "gtklistbox.h" |
29 | #include "gtkprivate.h" |
30 | #include "gtksizegroup.h" |
31 | #include "gtkimage.h" |
32 | #include "gtkadjustment.h" |
33 | #include "gtkbox.h" |
34 | #include "gtkbinlayout.h" |
35 | #include "gtkmediafileprivate.h" |
36 | #include "gtkimmoduleprivate.h" |
37 | |
38 | #include "gdk/gdkdebug.h" |
39 | |
40 | #ifdef GDK_WINDOWING_X11 |
41 | #include "x11/gdkx.h" |
42 | #include <epoxy/glx.h> |
43 | #include <epoxy/egl.h> |
44 | #endif |
45 | |
46 | #ifdef GDK_WINDOWING_WIN32 |
47 | #include "win32/gdkwin32.h" |
48 | #include "gdkglcontextprivate.h" |
49 | #include <epoxy/wgl.h> |
50 | #ifdef GDK_WIN32_ENABLE_EGL |
51 | #include <epoxy/egl.h> |
52 | #endif |
53 | #endif |
54 | |
55 | #ifdef GDK_WINDOWING_MACOS |
56 | #include "macos/gdkmacos.h" |
57 | #endif |
58 | |
59 | #ifdef GDK_WINDOWING_WAYLAND |
60 | #include "wayland/gdkwayland.h" |
61 | #include <epoxy/egl.h> |
62 | #include <xkbcommon/xkbcommon.h> |
63 | #endif |
64 | |
65 | #ifdef GDK_WINDOWING_BROADWAY |
66 | #include "broadway/gdkbroadway.h" |
67 | #endif |
68 | |
69 | #ifdef GDK_RENDERING_VULKAN |
70 | #include <vulkan/vulkan.h> |
71 | #endif |
72 | |
73 | struct _GtkInspectorGeneral |
74 | { |
75 | GtkWidget parent; |
76 | |
77 | GtkWidget *swin; |
78 | GtkWidget *box; |
79 | GtkWidget *version_box; |
80 | GtkWidget *env_box; |
81 | GtkWidget *display_box; |
82 | GtkWidget *monitor_box; |
83 | GtkWidget *gl_box; |
84 | GtkWidget *vulkan_box; |
85 | GtkWidget *device_box; |
86 | GtkWidget *gtk_version; |
87 | GtkWidget *gdk_backend; |
88 | GtkWidget *gsk_renderer; |
89 | GtkWidget *pango_fontmap; |
90 | GtkWidget *media_backend; |
91 | GtkWidget *im_module; |
92 | GtkWidget *gl_version; |
93 | GtkWidget *gl_error; |
94 | GtkWidget *gl_error_row; |
95 | GtkWidget *gl_vendor; |
96 | GtkWidget *gl_vendor_row; |
97 | GtkWidget *vk_device; |
98 | GtkWidget *vk_api_version; |
99 | GtkWidget *vk_driver_version; |
100 | GtkWidget *app_id_frame; |
101 | GtkWidget *app_id; |
102 | GtkWidget *resource_path; |
103 | GtkWidget *prefix; |
104 | GtkWidget *xdg_data_home; |
105 | GtkWidget *xdg_data_dirs; |
106 | GtkWidget *gtk_path; |
107 | GtkWidget *gtk_exe_prefix; |
108 | GtkWidget *gtk_data_prefix; |
109 | GtkWidget *gsettings_schema_dir; |
110 | GtkWidget *display_name; |
111 | GtkWidget *display_rgba; |
112 | GtkWidget *display_composited; |
113 | GtkSizeGroup *labels; |
114 | |
115 | GdkDisplay *display; |
116 | }; |
117 | |
118 | typedef struct _GtkInspectorGeneralClass |
119 | { |
120 | GtkWidgetClass parent_class; |
121 | } GtkInspectorGeneralClass; |
122 | |
123 | G_DEFINE_TYPE (GtkInspectorGeneral, gtk_inspector_general, GTK_TYPE_WIDGET) |
124 | |
125 | static void |
126 | init_version (GtkInspectorGeneral *gen) |
127 | { |
128 | const char *backend; |
129 | GdkSurface *surface; |
130 | GskRenderer *gsk_renderer; |
131 | const char *renderer; |
132 | |
133 | #ifdef GDK_WINDOWING_X11 |
134 | if (GDK_IS_X11_DISPLAY (gen->display)) |
135 | backend = "X11" ; |
136 | else |
137 | #endif |
138 | #ifdef GDK_WINDOWING_WAYLAND |
139 | if (GDK_IS_WAYLAND_DISPLAY (gen->display)) |
140 | backend = "Wayland" ; |
141 | else |
142 | #endif |
143 | #ifdef GDK_WINDOWING_BROADWAY |
144 | if (GDK_IS_BROADWAY_DISPLAY (gen->display)) |
145 | backend = "Broadway" ; |
146 | else |
147 | #endif |
148 | #ifdef GDK_WINDOWING_WIN32 |
149 | if (GDK_IS_WIN32_DISPLAY (gen->display)) |
150 | backend = "Windows" ; |
151 | else |
152 | #endif |
153 | #ifdef GDK_WINDOWING_MACOS |
154 | if (GDK_IS_MACOS_DISPLAY (gen->display)) |
155 | backend = "MacOS" ; |
156 | else |
157 | #endif |
158 | backend = "Unknown" ; |
159 | |
160 | surface = gdk_surface_new_toplevel (display: gen->display); |
161 | gsk_renderer = gsk_renderer_new_for_surface (surface); |
162 | if (strcmp (G_OBJECT_TYPE_NAME (gsk_renderer), s2: "GskVulkanRenderer" ) == 0) |
163 | renderer = "Vulkan" ; |
164 | else if (strcmp (G_OBJECT_TYPE_NAME (gsk_renderer), s2: "GskGLRenderer" ) == 0) |
165 | renderer = "GL" ; |
166 | else if (strcmp (G_OBJECT_TYPE_NAME (gsk_renderer), s2: "GskCairoRenderer" ) == 0) |
167 | renderer = "Cairo" ; |
168 | else |
169 | renderer = "Unknown" ; |
170 | |
171 | gsk_renderer_unrealize (renderer: gsk_renderer); |
172 | g_object_unref (object: gsk_renderer); |
173 | gdk_surface_destroy (surface); |
174 | |
175 | gtk_label_set_text (GTK_LABEL (gen->gtk_version), GTK_VERSION); |
176 | gtk_label_set_text (GTK_LABEL (gen->gdk_backend), str: backend); |
177 | gtk_label_set_text (GTK_LABEL (gen->gsk_renderer), str: renderer); |
178 | } |
179 | |
180 | static void |
181 | init_app_id (GtkInspectorGeneral *gen) |
182 | { |
183 | GApplication *app; |
184 | |
185 | app = g_application_get_default (); |
186 | if (!app) |
187 | { |
188 | gtk_widget_hide (widget: gen->app_id_frame); |
189 | return; |
190 | } |
191 | |
192 | gtk_label_set_text (GTK_LABEL (gen->app_id), |
193 | str: g_application_get_application_id (application: app)); |
194 | gtk_label_set_text (GTK_LABEL (gen->resource_path), |
195 | str: g_application_get_resource_base_path (application: app)); |
196 | } |
197 | |
198 | static G_GNUC_UNUSED void |
199 | add_check_row (GtkInspectorGeneral *gen, |
200 | GtkListBox *list, |
201 | const char *name, |
202 | gboolean value, |
203 | int indent) |
204 | { |
205 | GtkWidget *row, *box, *label, *check; |
206 | |
207 | box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 40); |
208 | g_object_set (object: box, first_property_name: "margin-start" , indent, NULL); |
209 | |
210 | label = gtk_label_new (str: name); |
211 | gtk_widget_set_halign (widget: label, align: GTK_ALIGN_START); |
212 | gtk_widget_set_valign (widget: label, align: GTK_ALIGN_BASELINE); |
213 | gtk_label_set_xalign (GTK_LABEL (label), xalign: 0.0); |
214 | gtk_widget_set_hexpand (widget: label, TRUE); |
215 | gtk_box_append (GTK_BOX (box), child: label); |
216 | |
217 | check = gtk_image_new_from_icon_name (icon_name: "object-select-symbolic" ); |
218 | gtk_widget_set_halign (widget: check, align: GTK_ALIGN_END); |
219 | gtk_widget_set_valign (widget: check, align: GTK_ALIGN_BASELINE); |
220 | gtk_widget_set_opacity (widget: check, opacity: value ? 1.0 : 0.0); |
221 | gtk_box_append (GTK_BOX (box), child: check); |
222 | |
223 | row = gtk_list_box_row_new (); |
224 | gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), child: box); |
225 | gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); |
226 | |
227 | gtk_widget_set_hexpand (widget: box, FALSE); |
228 | gtk_list_box_insert (box: list, child: row, position: -1); |
229 | |
230 | gtk_size_group_add_widget (GTK_SIZE_GROUP (gen->labels), widget: label); |
231 | } |
232 | |
233 | static void |
234 | add_label_row (GtkInspectorGeneral *gen, |
235 | GtkListBox *list, |
236 | const char *name, |
237 | const char *value, |
238 | int indent) |
239 | { |
240 | GtkWidget *box; |
241 | GtkWidget *label; |
242 | GtkWidget *row; |
243 | |
244 | box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 40); |
245 | g_object_set (object: box, first_property_name: "margin-start" , indent, NULL); |
246 | |
247 | label = gtk_label_new (str: name); |
248 | gtk_widget_set_halign (widget: label, align: GTK_ALIGN_START); |
249 | gtk_widget_set_valign (widget: label, align: GTK_ALIGN_BASELINE); |
250 | gtk_label_set_xalign (GTK_LABEL (label), xalign: 0.0); |
251 | gtk_widget_set_hexpand (widget: label, TRUE); |
252 | gtk_box_append (GTK_BOX (box), child: label); |
253 | |
254 | label = gtk_label_new (str: value); |
255 | gtk_label_set_selectable (GTK_LABEL (label), TRUE); |
256 | gtk_widget_set_halign (widget: label, align: GTK_ALIGN_END); |
257 | gtk_widget_set_valign (widget: label, align: GTK_ALIGN_BASELINE); |
258 | gtk_label_set_xalign (GTK_LABEL (label), xalign: 1.0); |
259 | gtk_box_append (GTK_BOX (box), child: label); |
260 | |
261 | row = gtk_list_box_row_new (); |
262 | gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), child: box); |
263 | gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE); |
264 | |
265 | gtk_widget_set_hexpand (widget: box, FALSE); |
266 | gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1); |
267 | |
268 | gtk_size_group_add_widget (GTK_SIZE_GROUP (gen->labels), widget: label); |
269 | } |
270 | |
271 | #ifdef GDK_WINDOWING_X11 |
272 | static void |
273 | append_glx_extension_row (GtkInspectorGeneral *gen, |
274 | Display *dpy, |
275 | const char *ext) |
276 | { |
277 | add_check_row (gen, GTK_LIST_BOX (gen->gl_box), name: ext, value: epoxy_has_glx_extension (dpy, screen: 0, extension: ext), indent: 0); |
278 | } |
279 | #endif |
280 | |
281 | #ifdef GDK_WINDOWING_WIN32 |
282 | static void |
283 | append_wgl_extension_row (GtkInspectorGeneral *gen, |
284 | const char *ext) |
285 | { |
286 | HDC hdc = 0; |
287 | |
288 | add_check_row (gen, GTK_LIST_BOX (gen->gl_box), ext, epoxy_has_wgl_extension (hdc, ext), 0); |
289 | } |
290 | #endif |
291 | |
292 | #if defined(GDK_WINDOWING_WAYLAND) || defined (GDK_WINDOWING_X11) || (defined (GDK_WINDOWING_WIN32) && defined(GDK_WIN32_ENABLE_EGL)) |
293 | static void |
294 | append_egl_extension_row (GtkInspectorGeneral *gen, |
295 | EGLDisplay dpy, |
296 | const char *ext) |
297 | { |
298 | add_check_row (gen, GTK_LIST_BOX (gen->gl_box), name: ext, value: epoxy_has_egl_extension (dpy, extension: ext), indent: 0); |
299 | } |
300 | |
301 | static EGLDisplay |
302 | get_egl_display (GdkDisplay *display) |
303 | { |
304 | #ifdef GDK_WINDOWING_WAYLAND |
305 | if (GDK_IS_WAYLAND_DISPLAY (display)) |
306 | return gdk_wayland_display_get_egl_display (display); |
307 | else |
308 | #endif |
309 | #ifdef GDK_WINDOWING_X11 |
310 | if (GDK_IS_X11_DISPLAY (display)) |
311 | return gdk_x11_display_get_egl_display (display); |
312 | else |
313 | #endif |
314 | #ifdef GDK_WINDOWING_WIN32 |
315 | if (GDK_IS_WIN32_DISPLAY (display)) |
316 | return gdk_win32_display_get_egl_display (display); |
317 | else |
318 | #endif |
319 | return NULL; |
320 | } |
321 | #endif |
322 | |
323 | static void |
324 | init_gl (GtkInspectorGeneral *gen) |
325 | { |
326 | GError *error = NULL; |
327 | |
328 | if (!gdk_display_prepare_gl (self: gen->display, error: &error)) |
329 | { |
330 | gtk_label_set_text (GTK_LABEL (gen->gl_version), C_("GL version" , "None" )); |
331 | gtk_widget_set_visible (widget: gen->gl_vendor_row, FALSE); |
332 | gtk_widget_set_visible (widget: gen->gl_error_row, TRUE); |
333 | gtk_label_set_text (GTK_LABEL (gen->gl_error), str: error->message); |
334 | g_error_free (error); |
335 | } |
336 | |
337 | if (gdk_display_get_debug_flags (display: gen->display) & GDK_DEBUG_GL_DISABLE) |
338 | { |
339 | gtk_label_set_text (GTK_LABEL (gen->gl_version), C_("GL version" , "Disabled" )); |
340 | gtk_label_set_text (GTK_LABEL (gen->gl_vendor), C_("GL vendor" , "Disabled" )); |
341 | return; |
342 | } |
343 | |
344 | #if defined(GDK_WINDOWING_X11) || defined(GDK_WINDOWING_WAYLAND) || (defined(GDK_WINDOWING_WIN32) && defined(GDK_WIN32_ENABLE_EGL)) |
345 | EGLDisplay egl_display = get_egl_display (display: gen->display); |
346 | if (egl_display) |
347 | { |
348 | char *version; |
349 | |
350 | version = g_strconcat (string1: "EGL " , eglQueryString (egl_display, EGL_VERSION), NULL); |
351 | gtk_label_set_text (GTK_LABEL (gen->gl_version), str: version); |
352 | g_free (mem: version); |
353 | |
354 | gtk_label_set_text (GTK_LABEL (gen->gl_vendor), eglQueryString (egl_display, EGL_VENDOR)); |
355 | |
356 | append_egl_extension_row (gen, dpy: egl_display, ext: "EGL_KHR_create_context" ); |
357 | append_egl_extension_row (gen, dpy: egl_display, ext: "EGL_EXT_buffer_age" ); |
358 | append_egl_extension_row (gen, dpy: egl_display, ext: "EGL_EXT_swap_buffers_with_damage" ); |
359 | append_egl_extension_row (gen, dpy: egl_display, ext: "EGL_KHR_surfaceless_context" ); |
360 | } |
361 | else |
362 | #endif |
363 | #ifdef GDK_WINDOWING_X11 |
364 | if (GDK_IS_X11_DISPLAY (gen->display)) |
365 | { |
366 | Display *dpy = GDK_DISPLAY_XDISPLAY (gen->display); |
367 | int error_base, event_base; |
368 | char *version; |
369 | |
370 | if (!glXQueryExtension (dpy, &error_base, &event_base)) |
371 | return; |
372 | |
373 | version = g_strconcat (string1: "GLX " , glXGetClientString (dpy, GLX_VERSION), NULL); |
374 | gtk_label_set_text (GTK_LABEL (gen->gl_version), str: version); |
375 | g_free (mem: version); |
376 | gtk_label_set_text (GTK_LABEL (gen->gl_vendor), glXGetClientString (dpy, GLX_VENDOR)); |
377 | |
378 | append_glx_extension_row (gen, dpy, ext: "GLX_ARB_create_context_profile" ); |
379 | append_glx_extension_row (gen, dpy, ext: "GLX_SGI_swap_control" ); |
380 | append_glx_extension_row (gen, dpy, ext: "GLX_EXT_texture_from_pixmap" ); |
381 | append_glx_extension_row (gen, dpy, ext: "GLX_SGI_video_sync" ); |
382 | append_glx_extension_row (gen, dpy, ext: "GLX_EXT_buffer_age" ); |
383 | append_glx_extension_row (gen, dpy, ext: "GLX_OML_sync_control" ); |
384 | append_glx_extension_row (gen, dpy, ext: "GLX_ARB_multisample" ); |
385 | append_glx_extension_row (gen, dpy, ext: "GLX_EXT_visual_rating" ); |
386 | } |
387 | else |
388 | #endif |
389 | #ifdef GDK_WINDOWING_WIN32 |
390 | if (GDK_IS_WIN32_DISPLAY (gen->display) && |
391 | gdk_gl_backend_can_be_used (GDK_GL_WGL, NULL)) |
392 | { |
393 | int gl_version; |
394 | char *version; |
395 | |
396 | gl_version = epoxy_gl_version (); |
397 | version = g_strdup_printf ("WGL %d.%d" , gl_version / 10, gl_version % 10); |
398 | gtk_label_set_text (GTK_LABEL (gen->gl_version), version); |
399 | g_free (version); |
400 | gtk_label_set_text (GTK_LABEL (gen->gl_vendor), (const char *) glGetString (GL_VENDOR)); |
401 | |
402 | append_wgl_extension_row (gen, "WGL_EXT_create_context" ); |
403 | append_wgl_extension_row (gen, "WGL_EXT_swap_control" ); |
404 | append_wgl_extension_row (gen, "WGL_OML_sync_control" ); |
405 | append_wgl_extension_row (gen, "WGL_ARB_pixel_format" ); |
406 | append_wgl_extension_row (gen, "WGL_ARB_multisample" ); |
407 | } |
408 | else |
409 | #endif |
410 | { |
411 | gtk_label_set_text (GTK_LABEL (gen->gl_version), C_("GL version" , "None" )); |
412 | gtk_label_set_text (GTK_LABEL (gen->gl_vendor), C_("GL vendor" , "None" )); |
413 | } |
414 | } |
415 | |
416 | #ifdef GDK_RENDERING_VULKAN |
417 | static gboolean |
418 | has_debug_extension (GdkVulkanContext *context) |
419 | { |
420 | uint32_t i; |
421 | uint32_t n_extensions; |
422 | vkEnumerateInstanceExtensionProperties (NULL, &n_extensions, NULL); |
423 | VkExtensionProperties *extensions = g_newa (VkExtensionProperties, n_extensions); |
424 | vkEnumerateInstanceExtensionProperties (NULL, &n_extensions, extensions); |
425 | |
426 | for (i = 0; i < n_extensions; i++) |
427 | { |
428 | if (g_str_equal (extensions[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) |
429 | return TRUE; |
430 | } |
431 | |
432 | return FALSE; |
433 | } |
434 | |
435 | static gboolean |
436 | has_validation_layer (GdkVulkanContext *context) |
437 | { |
438 | uint32_t i; |
439 | uint32_t n_layers; |
440 | vkEnumerateInstanceLayerProperties (&n_layers, NULL); |
441 | VkLayerProperties *layers = g_newa (VkLayerProperties, n_layers); |
442 | vkEnumerateInstanceLayerProperties (&n_layers, layers); |
443 | |
444 | for (i = 0; i < n_layers; i++) |
445 | { |
446 | if (g_str_equal (layers[i].layerName, "VK_LAYER_LUNARG_standard_validation" )) |
447 | return TRUE; |
448 | } |
449 | |
450 | return FALSE; |
451 | } |
452 | #endif |
453 | |
454 | static void |
455 | init_vulkan (GtkInspectorGeneral *gen) |
456 | { |
457 | #ifdef GDK_RENDERING_VULKAN |
458 | GdkSurface *surface; |
459 | GdkVulkanContext *context; |
460 | |
461 | if (gdk_display_get_debug_flags (gen->display) & GDK_DEBUG_VULKAN_DISABLE) |
462 | { |
463 | gtk_label_set_text (GTK_LABEL (gen->vk_device), C_("Vulkan device" , "Disabled" )); |
464 | gtk_label_set_text (GTK_LABEL (gen->vk_api_version), C_("Vulkan version" , "Disabled" )); |
465 | gtk_label_set_text (GTK_LABEL (gen->vk_driver_version), C_("Vulkan version" , "Disabled" )); |
466 | return; |
467 | } |
468 | |
469 | surface = gdk_surface_new_toplevel (gen->display); |
470 | context = gdk_surface_create_vulkan_context (surface, NULL); |
471 | gdk_surface_destroy (surface); |
472 | |
473 | if (context) |
474 | { |
475 | VkPhysicalDevice vk_device; |
476 | VkPhysicalDeviceProperties props; |
477 | char *device_name; |
478 | char *api_version; |
479 | char *driver_version; |
480 | |
481 | vk_device = gdk_vulkan_context_get_physical_device (context); |
482 | vkGetPhysicalDeviceProperties (vk_device, &props); |
483 | |
484 | device_name = g_strdup_printf ("%s (%d)" , props.deviceName, props.deviceType); |
485 | api_version = g_strdup_printf ("%d.%d.%d" , |
486 | VK_VERSION_MAJOR (props.apiVersion), |
487 | VK_VERSION_MINOR (props.apiVersion), |
488 | VK_VERSION_PATCH (props.apiVersion)); |
489 | driver_version = g_strdup_printf ("%d.%d.%d" , |
490 | VK_VERSION_MAJOR (props.driverVersion), |
491 | VK_VERSION_MINOR (props.driverVersion), |
492 | VK_VERSION_PATCH (props.driverVersion)); |
493 | |
494 | gtk_label_set_text (GTK_LABEL (gen->vk_device), device_name); |
495 | gtk_label_set_text (GTK_LABEL (gen->vk_api_version), api_version); |
496 | gtk_label_set_text (GTK_LABEL (gen->vk_driver_version), driver_version); |
497 | |
498 | g_free (device_name); |
499 | g_free (api_version); |
500 | g_free (driver_version); |
501 | |
502 | add_check_row (gen, GTK_LIST_BOX (gen->vulkan_box), VK_KHR_SURFACE_EXTENSION_NAME, TRUE, 0); |
503 | #ifdef GDK_WINDOWING_X11 |
504 | if (GDK_IS_X11_DISPLAY (gen->display)) |
505 | add_check_row (gen, GTK_LIST_BOX (gen->vulkan_box), "VK_KHR_xlib_surface" , TRUE, 0); |
506 | #endif |
507 | #ifdef GDK_WINDOWING_WAYLAND |
508 | if (GDK_IS_WAYLAND_DISPLAY (gen->display)) |
509 | add_check_row (gen, GTK_LIST_BOX (gen->vulkan_box), "VK_KHR_wayland_surface" , TRUE, 0); |
510 | #endif |
511 | add_check_row (gen, GTK_LIST_BOX (gen->vulkan_box), VK_EXT_DEBUG_REPORT_EXTENSION_NAME, |
512 | has_debug_extension (context), 0); |
513 | add_check_row (gen, GTK_LIST_BOX (gen->vulkan_box), "VK_LAYER_LUNARG_standard_validation" , |
514 | has_validation_layer (context), 0); |
515 | |
516 | g_object_unref (context); |
517 | } |
518 | else |
519 | #endif |
520 | { |
521 | gtk_label_set_text (GTK_LABEL (gen->vk_device), C_("Vulkan device" , "None" )); |
522 | gtk_label_set_text (GTK_LABEL (gen->vk_api_version), C_("Vulkan version" , "None" )); |
523 | gtk_label_set_text (GTK_LABEL (gen->vk_driver_version), C_("Vulkan version" , "None" )); |
524 | } |
525 | } |
526 | |
527 | static void |
528 | set_monospace_font (GtkWidget *w) |
529 | { |
530 | PangoAttrList *attrs; |
531 | |
532 | attrs = pango_attr_list_new (); |
533 | pango_attr_list_insert (list: attrs, attr: pango_attr_fallback_new (FALSE)); |
534 | pango_attr_list_insert (list: attrs, attr: pango_attr_family_new (family: "Monospace" )); |
535 | gtk_label_set_attributes (GTK_LABEL (w), attrs); |
536 | pango_attr_list_unref (list: attrs); |
537 | } |
538 | |
539 | static void |
540 | set_path_label (GtkWidget *w, |
541 | const char *var) |
542 | { |
543 | const char *v; |
544 | |
545 | v = g_getenv (variable: var); |
546 | if (v != NULL) |
547 | { |
548 | set_monospace_font (w); |
549 | gtk_label_set_text (GTK_LABEL (w), str: v); |
550 | } |
551 | else |
552 | { |
553 | GtkWidget *r; |
554 | r = gtk_widget_get_ancestor (widget: w, GTK_TYPE_LIST_BOX_ROW); |
555 | gtk_widget_hide (widget: r); |
556 | } |
557 | } |
558 | |
559 | static void |
560 | init_env (GtkInspectorGeneral *gen) |
561 | { |
562 | set_monospace_font (gen->prefix); |
563 | gtk_label_set_text (GTK_LABEL (gen->prefix), str: _gtk_get_data_prefix ()); |
564 | set_path_label (w: gen->xdg_data_home, var: "XDG_DATA_HOME" ); |
565 | set_path_label (w: gen->xdg_data_dirs, var: "XDG_DATA_DIRS" ); |
566 | set_path_label (w: gen->gtk_path, var: "GTK_PATH" ); |
567 | set_path_label (w: gen->gtk_exe_prefix, var: "GTK_EXE_PREFIX" ); |
568 | set_path_label (w: gen->gtk_data_prefix, var: "GTK_DATA_PREFIX" ); |
569 | set_path_label (w: gen->gsettings_schema_dir, var: "GSETTINGS_SCHEMA_DIR" ); |
570 | } |
571 | |
572 | static const char * |
573 | translate_subpixel_layout (GdkSubpixelLayout subpixel) |
574 | { |
575 | switch (subpixel) |
576 | { |
577 | case GDK_SUBPIXEL_LAYOUT_NONE: return "none" ; |
578 | case GDK_SUBPIXEL_LAYOUT_UNKNOWN: return "unknown" ; |
579 | case GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB: return "horizontal rgb" ; |
580 | case GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR: return "horizontal bgr" ; |
581 | case GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB: return "vertical rgb" ; |
582 | case GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR: return "vertical bgr" ; |
583 | default: g_assert_not_reached (); return "none" ; |
584 | } |
585 | } |
586 | |
587 | static void |
588 | populate_display (GdkDisplay *display, GtkInspectorGeneral *gen) |
589 | { |
590 | GList *children, *l; |
591 | GtkWidget *child; |
592 | GtkListBox *list; |
593 | |
594 | gtk_widget_show (widget: gen->display_composited); |
595 | list = GTK_LIST_BOX (gen->display_box); |
596 | children = NULL; |
597 | for (child = gtk_widget_get_first_child (GTK_WIDGET (list)); |
598 | child != NULL; |
599 | child = gtk_widget_get_next_sibling (widget: child)) |
600 | { |
601 | if (GTK_IS_LIST_BOX_ROW (child)) |
602 | children = g_list_prepend (list: children, data: child); |
603 | } |
604 | for (l = children; l; l = l->next) |
605 | { |
606 | child = l->data; |
607 | if (gtk_widget_is_ancestor (widget: gen->display_name, ancestor: child) || |
608 | gtk_widget_is_ancestor (widget: gen->display_rgba, ancestor: child) || |
609 | gtk_widget_is_ancestor (widget: gen->display_composited, ancestor: child)) |
610 | continue; |
611 | |
612 | gtk_list_box_remove (box: list, child); |
613 | } |
614 | g_list_free (list: children); |
615 | |
616 | gtk_label_set_label (GTK_LABEL (gen->display_name), str: gdk_display_get_name (display)); |
617 | |
618 | gtk_widget_set_visible (widget: gen->display_rgba, |
619 | visible: gdk_display_is_rgba (display)); |
620 | gtk_widget_set_visible (widget: gen->display_composited, |
621 | visible: gdk_display_is_composited (display)); |
622 | } |
623 | |
624 | static void |
625 | add_monitor (GtkInspectorGeneral *gen, |
626 | GdkMonitor *monitor, |
627 | guint i) |
628 | { |
629 | GtkListBox *list; |
630 | char *value; |
631 | GdkRectangle rect; |
632 | int scale; |
633 | char *name; |
634 | char *scale_str = NULL; |
635 | const char *manufacturer; |
636 | const char *model; |
637 | |
638 | list = GTK_LIST_BOX (gen->monitor_box); |
639 | |
640 | name = g_strdup_printf (format: "Monitor %u" , i); |
641 | manufacturer = gdk_monitor_get_manufacturer (monitor); |
642 | model = gdk_monitor_get_model (monitor); |
643 | value = g_strdup_printf (format: "%s%s%s" , |
644 | manufacturer ? manufacturer : "" , |
645 | manufacturer || model ? " " : "" , |
646 | model ? model : "" ); |
647 | add_label_row (gen, list, name, value, indent: 0); |
648 | g_free (mem: value); |
649 | g_free (mem: name); |
650 | |
651 | add_label_row (gen, list, name: "Connector" , value: gdk_monitor_get_connector (monitor), indent: 10); |
652 | |
653 | gdk_monitor_get_geometry (monitor, geometry: &rect); |
654 | scale = gdk_monitor_get_scale_factor (monitor); |
655 | if (scale != 1) |
656 | scale_str = g_strdup_printf (format: " @ %d" , scale); |
657 | |
658 | value = g_strdup_printf (format: "%d × %d%s at %d, %d" , |
659 | rect.width, rect.height, |
660 | scale_str ? scale_str : "" , |
661 | rect.x, rect.y); |
662 | add_label_row (gen, list, name: "Geometry" , value, indent: 10); |
663 | g_free (mem: value); |
664 | g_free (mem: scale_str); |
665 | |
666 | value = g_strdup_printf (format: "%d × %d mm²" , |
667 | gdk_monitor_get_width_mm (monitor), |
668 | gdk_monitor_get_height_mm (monitor)); |
669 | add_label_row (gen, list, name: "Size" , value, indent: 10); |
670 | g_free (mem: value); |
671 | |
672 | if (gdk_monitor_get_refresh_rate (monitor) != 0) |
673 | { |
674 | value = g_strdup_printf (format: "%.2f Hz" , |
675 | 0.001 * gdk_monitor_get_refresh_rate (monitor)); |
676 | add_label_row (gen, list, name: "Refresh rate" , value, indent: 10); |
677 | g_free (mem: value); |
678 | } |
679 | |
680 | if (gdk_monitor_get_subpixel_layout (monitor) != GDK_SUBPIXEL_LAYOUT_UNKNOWN) |
681 | { |
682 | add_label_row (gen, list, name: "Subpixel layout" , |
683 | value: translate_subpixel_layout (subpixel: gdk_monitor_get_subpixel_layout (monitor)), |
684 | indent: 10); |
685 | } |
686 | } |
687 | |
688 | static void |
689 | populate_monitors (GdkDisplay *display, |
690 | GtkInspectorGeneral *gen) |
691 | { |
692 | GtkWidget *child; |
693 | GListModel *list; |
694 | |
695 | while ((child = gtk_widget_get_first_child (widget: gen->monitor_box))) |
696 | gtk_list_box_remove (GTK_LIST_BOX (gen->monitor_box), child); |
697 | |
698 | list = gdk_display_get_monitors (self: gen->display); |
699 | |
700 | for (guint i = 0; i < g_list_model_get_n_items (list); i++) |
701 | { |
702 | GdkMonitor *monitor = g_list_model_get_item (list, position: i); |
703 | add_monitor (gen, monitor, i); |
704 | g_object_unref (object: monitor); |
705 | } |
706 | } |
707 | |
708 | static void |
709 | populate_display_notify_cb (GdkDisplay *display, |
710 | GParamSpec *pspec, |
711 | GtkInspectorGeneral *gen) |
712 | { |
713 | populate_display (display, gen); |
714 | } |
715 | |
716 | static void |
717 | monitors_changed_cb (GListModel *monitors, |
718 | guint position, |
719 | guint removed, |
720 | guint added, |
721 | GtkInspectorGeneral *gen) |
722 | { |
723 | populate_monitors (display: gen->display, gen); |
724 | } |
725 | |
726 | static void |
727 | init_display (GtkInspectorGeneral *gen) |
728 | { |
729 | g_signal_connect (gen->display, "notify" , G_CALLBACK (populate_display_notify_cb), gen); |
730 | g_signal_connect (gdk_display_get_monitors (gen->display), "items-changed" , |
731 | G_CALLBACK (monitors_changed_cb), gen); |
732 | |
733 | populate_display (display: gen->display, gen); |
734 | populate_monitors (display: gen->display, gen); |
735 | } |
736 | |
737 | static void |
738 | init_pango (GtkInspectorGeneral *gen) |
739 | { |
740 | PangoFontMap *fontmap; |
741 | const char *type; |
742 | const char *name; |
743 | |
744 | fontmap = pango_cairo_font_map_get_default (); |
745 | type = G_OBJECT_TYPE_NAME (fontmap); |
746 | if (strcmp (s1: type, s2: "PangoCairoFcFontMap" ) == 0) |
747 | name = "fontconfig" ; |
748 | else if (strcmp (s1: type, s2: "PangoCairoCoreTextFontMap" ) == 0) |
749 | name = "coretext" ; |
750 | else if (strcmp (s1: type, s2: "PangoCairoWin32FontMap" ) == 0) |
751 | name = "win32" ; |
752 | else |
753 | name = type; |
754 | |
755 | gtk_label_set_label (GTK_LABEL (gen->pango_fontmap), str: name); |
756 | } |
757 | |
758 | static void |
759 | init_media (GtkInspectorGeneral *gen) |
760 | { |
761 | GIOExtension *e; |
762 | const char *name; |
763 | |
764 | e = gtk_media_file_get_extension (); |
765 | name = g_io_extension_get_name (extension: e); |
766 | gtk_label_set_label (GTK_LABEL (gen->media_backend), str: name); |
767 | } |
768 | |
769 | static void |
770 | im_module_changed (GtkSettings *settings, |
771 | GParamSpec *pspec, |
772 | GtkInspectorGeneral *gen) |
773 | { |
774 | if (!gen->display) |
775 | return; |
776 | |
777 | gtk_label_set_label (GTK_LABEL (gen->im_module), |
778 | str: _gtk_im_module_get_default_context_id (display: gen->display)); |
779 | } |
780 | |
781 | static void |
782 | init_im_module (GtkInspectorGeneral *gen) |
783 | { |
784 | GtkSettings *settings = gtk_settings_get_for_display (display: gen->display); |
785 | const char *default_context_id = _gtk_im_module_get_default_context_id (display: gen->display); |
786 | |
787 | gtk_label_set_label (GTK_LABEL (gen->im_module), str: default_context_id); |
788 | |
789 | if (g_getenv (variable: "GTK_IM_MODULE" ) != NULL) |
790 | { |
791 | /* This can't update if GTK_IM_MODULE envvar is set */ |
792 | gtk_widget_set_tooltip_text (widget: gen->im_module, |
793 | _("IM Context is hardcoded by GTK_IM_MODULE" )); |
794 | gtk_widget_set_sensitive (widget: gen->im_module, FALSE); |
795 | return; |
796 | } |
797 | |
798 | g_signal_connect_object (instance: settings, |
799 | detailed_signal: "notify::gtk-im-module" , |
800 | G_CALLBACK (im_module_changed), |
801 | gobject: gen, connect_flags: 0); |
802 | } |
803 | |
804 | |
805 | static void populate_seats (GtkInspectorGeneral *gen); |
806 | |
807 | static void |
808 | add_tool (GtkInspectorGeneral *gen, |
809 | GdkDeviceTool *tool) |
810 | { |
811 | GdkAxisFlags axes; |
812 | GString *str; |
813 | char *val; |
814 | int i; |
815 | GEnumClass *eclass; |
816 | GEnumValue *evalue; |
817 | GFlagsClass *fclass; |
818 | GFlagsValue *fvalue; |
819 | |
820 | val = g_strdup_printf (format: "Serial %" G_GUINT64_FORMAT, gdk_device_tool_get_serial (tool)); |
821 | add_label_row (gen, GTK_LIST_BOX (gen->device_box), name: "Tool" , value: val, indent: 10); |
822 | g_free (mem: val); |
823 | |
824 | eclass = g_type_class_ref (type: GDK_TYPE_DEVICE_TOOL_TYPE); |
825 | evalue = g_enum_get_value (enum_class: eclass, value: gdk_device_tool_get_tool_type (tool)); |
826 | add_label_row (gen, GTK_LIST_BOX (gen->device_box), name: "Type" , value: evalue->value_nick, indent: 20); |
827 | g_type_class_unref (g_class: eclass); |
828 | |
829 | fclass = g_type_class_ref (type: GDK_TYPE_AXIS_FLAGS); |
830 | str = g_string_new (init: "" ); |
831 | axes = gdk_device_tool_get_axes (tool); |
832 | for (i = GDK_AXIS_X; i < GDK_AXIS_LAST; i++) |
833 | { |
834 | if ((axes & (1 << i)) != 0) |
835 | { |
836 | fvalue = g_flags_get_first_value (flags_class: fclass, value: i); |
837 | if (str->len > 0) |
838 | g_string_append (string: str, val: ", " ); |
839 | g_string_append (string: str, val: fvalue->value_nick); |
840 | } |
841 | } |
842 | g_type_class_unref (g_class: fclass); |
843 | |
844 | if (str->len > 0) |
845 | add_label_row (gen, GTK_LIST_BOX (gen->device_box), name: "Axes" , value: str->str, indent: 20); |
846 | |
847 | g_string_free (string: str, TRUE); |
848 | } |
849 | |
850 | static void |
851 | add_device (GtkInspectorGeneral *gen, |
852 | GdkDevice *device) |
853 | { |
854 | const char *name; |
855 | guint n_touches; |
856 | char *text; |
857 | GEnumClass *class; |
858 | GEnumValue *value; |
859 | |
860 | name = gdk_device_get_name (device); |
861 | |
862 | class = g_type_class_ref (type: GDK_TYPE_INPUT_SOURCE); |
863 | value = g_enum_get_value (enum_class: class, value: gdk_device_get_source (device)); |
864 | |
865 | add_label_row (gen, GTK_LIST_BOX (gen->device_box), name, value: value->value_nick, indent: 10); |
866 | |
867 | g_object_get (object: device, first_property_name: "num-touches" , &n_touches, NULL); |
868 | if (n_touches > 0) |
869 | { |
870 | text = g_strdup_printf (format: "%d" , n_touches); |
871 | add_label_row (gen, GTK_LIST_BOX (gen->device_box), name: "Touches" , value: text, indent: 20); |
872 | g_free (mem: text); |
873 | } |
874 | |
875 | #ifdef GDK_WINDOWING_WAYLAND |
876 | if (GDK_IS_WAYLAND_DEVICE (device) && |
877 | gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) |
878 | { |
879 | struct xkb_keymap *keymap = gdk_wayland_device_get_xkb_keymap (device); |
880 | GString *s; |
881 | |
882 | s = g_string_new (init: "" ); |
883 | for (int i = 0; i < xkb_keymap_num_layouts (keymap); i++) |
884 | { |
885 | if (s->len > 0) |
886 | g_string_append (string: s, val: ", " ); |
887 | g_string_append (string: s, val: xkb_keymap_layout_get_name (keymap, idx: i)); |
888 | } |
889 | |
890 | add_label_row (gen, GTK_LIST_BOX (gen->device_box), name: "Layouts" , value: s->str, indent: 20); |
891 | g_string_free (string: s, TRUE); |
892 | } |
893 | #endif |
894 | |
895 | g_type_class_unref (g_class: class); |
896 | } |
897 | |
898 | static char * |
899 | get_seat_capabilities (GdkSeat *seat) |
900 | { |
901 | struct { |
902 | GdkSeatCapabilities cap; |
903 | const char *name; |
904 | } caps[] = { |
905 | { GDK_SEAT_CAPABILITY_POINTER, "Pointer" }, |
906 | { GDK_SEAT_CAPABILITY_TOUCH, "Touch" }, |
907 | { GDK_SEAT_CAPABILITY_TABLET_STYLUS, "Tablet" }, |
908 | { GDK_SEAT_CAPABILITY_KEYBOARD, "Keyboard" }, |
909 | { 0, NULL } |
910 | }; |
911 | GString *str; |
912 | GdkSeatCapabilities capabilities; |
913 | int i; |
914 | |
915 | str = g_string_new (init: "" ); |
916 | capabilities = gdk_seat_get_capabilities (seat); |
917 | for (i = 0; caps[i].cap != 0; i++) |
918 | { |
919 | if (capabilities & caps[i].cap) |
920 | { |
921 | if (str->len > 0) |
922 | g_string_append (string: str, val: ", " ); |
923 | g_string_append (string: str, val: caps[i].name); |
924 | } |
925 | } |
926 | |
927 | return g_string_free (string: str, FALSE); |
928 | } |
929 | |
930 | static void |
931 | add_seat (GtkInspectorGeneral *gen, |
932 | GdkSeat *seat, |
933 | int num) |
934 | { |
935 | char *text; |
936 | char *caps; |
937 | GList *list, *l; |
938 | |
939 | if (!g_object_get_data (G_OBJECT (seat), key: "inspector-connected" )) |
940 | { |
941 | g_object_set_data (G_OBJECT (seat), key: "inspector-connected" , GINT_TO_POINTER (1)); |
942 | g_signal_connect_swapped (seat, "device-added" , G_CALLBACK (populate_seats), gen); |
943 | g_signal_connect_swapped (seat, "device-removed" , G_CALLBACK (populate_seats), gen); |
944 | g_signal_connect_swapped (seat, "tool-added" , G_CALLBACK (populate_seats), gen); |
945 | g_signal_connect_swapped (seat, "tool-removed" , G_CALLBACK (populate_seats), gen); |
946 | } |
947 | |
948 | text = g_strdup_printf (format: "Seat %d" , num); |
949 | caps = get_seat_capabilities (seat); |
950 | |
951 | add_label_row (gen, GTK_LIST_BOX (gen->device_box), name: text, value: caps, indent: 0); |
952 | g_free (mem: text); |
953 | g_free (mem: caps); |
954 | |
955 | list = gdk_seat_get_devices (seat, capabilities: GDK_SEAT_CAPABILITY_ALL); |
956 | |
957 | for (l = list; l; l = l->next) |
958 | add_device (gen, GDK_DEVICE (l->data)); |
959 | |
960 | g_list_free (list); |
961 | |
962 | list = gdk_seat_get_tools (seat); |
963 | |
964 | for (l = list; l; l = l->next) |
965 | add_tool (gen, tool: l->data); |
966 | |
967 | g_list_free (list); |
968 | } |
969 | |
970 | static void |
971 | disconnect_seat (GtkInspectorGeneral *gen, |
972 | GdkSeat *seat) |
973 | { |
974 | g_signal_handlers_disconnect_by_func (seat, G_CALLBACK (populate_seats), gen); |
975 | } |
976 | |
977 | static void |
978 | populate_seats (GtkInspectorGeneral *gen) |
979 | { |
980 | GtkWidget *child; |
981 | GList *list, *l; |
982 | int i; |
983 | |
984 | while ((child = gtk_widget_get_first_child (widget: gen->device_box))) |
985 | gtk_list_box_remove (GTK_LIST_BOX (gen->device_box), child); |
986 | |
987 | list = gdk_display_list_seats (display: gen->display); |
988 | |
989 | for (l = list, i = 0; l; l = l->next, i++) |
990 | add_seat (gen, GDK_SEAT (l->data), num: i); |
991 | |
992 | g_list_free (list); |
993 | } |
994 | |
995 | static void |
996 | seat_added (GdkDisplay *display, |
997 | GdkSeat *seat, |
998 | GtkInspectorGeneral *gen) |
999 | { |
1000 | populate_seats (gen); |
1001 | } |
1002 | |
1003 | static void |
1004 | seat_removed (GdkDisplay *display, |
1005 | GdkSeat *seat, |
1006 | GtkInspectorGeneral *gen) |
1007 | { |
1008 | disconnect_seat (gen, seat); |
1009 | populate_seats (gen); |
1010 | } |
1011 | |
1012 | static void |
1013 | init_device (GtkInspectorGeneral *gen) |
1014 | { |
1015 | g_signal_connect (gen->display, "seat-added" , G_CALLBACK (seat_added), gen); |
1016 | g_signal_connect (gen->display, "seat-removed" , G_CALLBACK (seat_removed), gen); |
1017 | |
1018 | populate_seats (gen); |
1019 | } |
1020 | |
1021 | static void |
1022 | gtk_inspector_general_init (GtkInspectorGeneral *gen) |
1023 | { |
1024 | gtk_widget_init_template (GTK_WIDGET (gen)); |
1025 | } |
1026 | |
1027 | static gboolean |
1028 | keynav_failed (GtkWidget *widget, GtkDirectionType direction, GtkInspectorGeneral *gen) |
1029 | { |
1030 | GtkWidget *next; |
1031 | |
1032 | if (direction == GTK_DIR_DOWN && widget == gen->version_box) |
1033 | next = gen->env_box; |
1034 | else if (direction == GTK_DIR_DOWN && widget == gen->env_box) |
1035 | next = gen->display_box; |
1036 | else if (direction == GTK_DIR_DOWN && widget == gen->display_box) |
1037 | next = gen->monitor_box; |
1038 | else if (direction == GTK_DIR_DOWN && widget == gen->monitor_box) |
1039 | next = gen->gl_box; |
1040 | else if (direction == GTK_DIR_DOWN && widget == gen->gl_box) |
1041 | next = gen->vulkan_box; |
1042 | else if (direction == GTK_DIR_DOWN && widget == gen->vulkan_box) |
1043 | next = gen->device_box; |
1044 | else if (direction == GTK_DIR_UP && widget == gen->device_box) |
1045 | next = gen->vulkan_box; |
1046 | else if (direction == GTK_DIR_UP && widget == gen->vulkan_box) |
1047 | next = gen->gl_box; |
1048 | else if (direction == GTK_DIR_UP && widget == gen->gl_box) |
1049 | next = gen->monitor_box; |
1050 | else if (direction == GTK_DIR_UP && widget == gen->monitor_box) |
1051 | next = gen->display_box; |
1052 | else if (direction == GTK_DIR_UP && widget == gen->display_box) |
1053 | next = gen->env_box; |
1054 | else if (direction == GTK_DIR_UP && widget == gen->env_box) |
1055 | next = gen->version_box; |
1056 | else |
1057 | next = NULL; |
1058 | |
1059 | if (next) |
1060 | { |
1061 | gtk_widget_child_focus (widget: next, direction); |
1062 | return TRUE; |
1063 | } |
1064 | |
1065 | return FALSE; |
1066 | } |
1067 | |
1068 | static void |
1069 | gtk_inspector_general_constructed (GObject *object) |
1070 | { |
1071 | GtkInspectorGeneral *gen = GTK_INSPECTOR_GENERAL (object); |
1072 | |
1073 | G_OBJECT_CLASS (gtk_inspector_general_parent_class)->constructed (object); |
1074 | |
1075 | g_signal_connect (gen->version_box, "keynav-failed" , G_CALLBACK (keynav_failed), gen); |
1076 | g_signal_connect (gen->env_box, "keynav-failed" , G_CALLBACK (keynav_failed), gen); |
1077 | g_signal_connect (gen->display_box, "keynav-failed" , G_CALLBACK (keynav_failed), gen); |
1078 | g_signal_connect (gen->monitor_box, "keynav-failed" , G_CALLBACK (keynav_failed), gen); |
1079 | g_signal_connect (gen->gl_box, "keynav-failed" , G_CALLBACK (keynav_failed), gen); |
1080 | g_signal_connect (gen->vulkan_box, "keynav-failed" , G_CALLBACK (keynav_failed), gen); |
1081 | g_signal_connect (gen->device_box, "keynav-failed" , G_CALLBACK (keynav_failed), gen); |
1082 | } |
1083 | |
1084 | static void |
1085 | gtk_inspector_general_dispose (GObject *object) |
1086 | { |
1087 | GtkInspectorGeneral *gen = GTK_INSPECTOR_GENERAL (object); |
1088 | GList *list, *l; |
1089 | |
1090 | g_clear_pointer (&gen->swin, gtk_widget_unparent); |
1091 | |
1092 | g_signal_handlers_disconnect_by_func (gen->display, G_CALLBACK (seat_added), gen); |
1093 | g_signal_handlers_disconnect_by_func (gen->display, G_CALLBACK (seat_removed), gen); |
1094 | g_signal_handlers_disconnect_by_func (gen->display, G_CALLBACK (populate_display_notify_cb), gen); |
1095 | g_signal_handlers_disconnect_by_func (gdk_display_get_monitors (gen->display), G_CALLBACK (monitors_changed_cb), gen); |
1096 | |
1097 | list = gdk_display_list_seats (display: gen->display); |
1098 | for (l = list; l; l = l->next) |
1099 | disconnect_seat (gen, GDK_SEAT (l->data)); |
1100 | g_list_free (list); |
1101 | |
1102 | G_OBJECT_CLASS (gtk_inspector_general_parent_class)->dispose (object); |
1103 | } |
1104 | |
1105 | static void |
1106 | gtk_inspector_general_class_init (GtkInspectorGeneralClass *klass) |
1107 | { |
1108 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
1109 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
1110 | |
1111 | object_class->constructed = gtk_inspector_general_constructed; |
1112 | object_class->dispose = gtk_inspector_general_dispose; |
1113 | |
1114 | gtk_widget_class_set_template_from_resource (widget_class, resource_name: "/org/gtk/libgtk/inspector/general.ui" ); |
1115 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, swin); |
1116 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, box); |
1117 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, version_box); |
1118 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, env_box); |
1119 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, display_box); |
1120 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, monitor_box); |
1121 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_box); |
1122 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, vulkan_box); |
1123 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gtk_version); |
1124 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gdk_backend); |
1125 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gsk_renderer); |
1126 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, pango_fontmap); |
1127 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, media_backend); |
1128 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, im_module); |
1129 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_version); |
1130 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_error); |
1131 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_error_row); |
1132 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_vendor); |
1133 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_vendor_row); |
1134 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, vk_device); |
1135 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, vk_api_version); |
1136 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, vk_driver_version); |
1137 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, app_id_frame); |
1138 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, app_id); |
1139 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, resource_path); |
1140 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, prefix); |
1141 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, xdg_data_home); |
1142 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, xdg_data_dirs); |
1143 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gtk_path); |
1144 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gtk_exe_prefix); |
1145 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gtk_data_prefix); |
1146 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gsettings_schema_dir); |
1147 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, labels); |
1148 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, display_name); |
1149 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, display_composited); |
1150 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, display_rgba); |
1151 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, device_box); |
1152 | |
1153 | gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); |
1154 | } |
1155 | |
1156 | void |
1157 | gtk_inspector_general_set_display (GtkInspectorGeneral *gen, |
1158 | GdkDisplay *display) |
1159 | { |
1160 | gen->display = display; |
1161 | |
1162 | init_version (gen); |
1163 | init_env (gen); |
1164 | init_app_id (gen); |
1165 | init_display (gen); |
1166 | init_pango (gen); |
1167 | init_media (gen); |
1168 | init_gl (gen); |
1169 | init_vulkan (gen); |
1170 | init_device (gen); |
1171 | init_im_module (gen); |
1172 | } |
1173 | |
1174 | // vim: set et sw=2 ts=2: |
1175 | |