1 /**
2 * Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <X11/Xutil.h>
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31 #ifdef ENABLE_NLS
32 # define _(string) gettext (string)
33 # include "gettext.h"
34 #else
35 # define _(string) string
36 #endif
37 #include <X11/extensions/XRes.h>
38 #include "xresview.h"
39
40 static Atom wm_state;
41 static Atom res_pixmap;
42 static Atom res_window;
43 static Atom res_gc;
44 static Atom res_font;
45 static Atom res_glyphset;
46 static Atom res_picture;
47 static Atom res_cursor;
48 static Atom res_colormap_entry;
49 static Atom res_passive_grab;
50 static int atoms_loaded = 0;
51
52 /**
53 * Cache every atom we need. This minimizes round trips to the server.
54 * The number of atoms and their position is hardcoded, but it's small.
55 * Making this look pretty I think would be too annoying to be worth it.
56 */
load_atoms(Display * dpy)57 static void load_atoms( Display *dpy )
58 {
59 static char *atom_names[] = {
60 "WM_STATE",
61 "PIXMAP",
62 "WINDOW",
63 "GC",
64 "FONT",
65 "PICTURE",
66 "CURSOR",
67 "GLYPHSET",
68 "COLORMAP_ENTRY",
69 "PASSIVE_GRAB"
70 };
71 Atom atoms_return[ 10 ];
72
73 if( atoms_loaded ) return;
74
75 XInternAtoms( dpy, atom_names, 10, False, atoms_return );
76 wm_state = atoms_return[ 0 ];
77 res_pixmap = atoms_return[ 1 ];
78 res_window = atoms_return[ 2 ];
79 res_gc = atoms_return[ 3 ];
80 res_font = atoms_return[ 4 ];
81 res_picture = atoms_return[ 5 ];
82 res_cursor = atoms_return[ 6 ];
83 res_glyphset = atoms_return[ 7 ];
84 res_colormap_entry = atoms_return[ 8 ];
85 res_passive_grab = atoms_return[ 9 ];
86 atoms_loaded = 1;
87 }
88
89 struct xresview_s
90 {
91 GtkWidget *scrolled;
92 GtkWidget *main;
93 GtkWidget *name;
94 GtkWidget *pixmap_bytes;
95 GtkWidget *pixmaps;
96 GtkWidget *windows;
97 GtkWidget *glyphsets;
98 GtkWidget *gcs;
99 GtkWidget *fonts;
100 GtkWidget *pictures;
101 GtkWidget *pgrabs;
102 GtkWidget *colormaps;
103 GtkWidget *cursors;
104 XResClient *clients;
105 int numclients;
106 };
107
xresview_new(void)108 xresview_t *xresview_new( void )
109 {
110 xresview_t *rv = malloc( sizeof( xresview_t ) );
111 GtkWidget *vbox;
112 GtkWidget *table;
113 GtkWidget *label;
114 GtkWidget *align;
115 int row = 0;
116
117 rv->clients = 0;
118
119 vbox = gtk_vbox_new( FALSE, 2 );
120 align = gtk_alignment_new( 0.5, 0.0, 0.95, 0.0 );
121 table = gtk_table_new( 1, 2, FALSE );
122 gtk_container_add( GTK_CONTAINER( align ), table );
123 gtk_box_pack_start( GTK_BOX( vbox ), align, TRUE, TRUE, 2 );
124
125 /*
126 label = gtk_label_new( "Name:" );
127 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
128 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
129 rv->name = gtk_entry_new();
130 gtk_entry_set_editable( GTK_ENTRY( rv->name ), FALSE );
131 gtk_table_attach_defaults( GTK_TABLE( table ), rv->name, 1, 2, row, row + 1 );
132 row++;
133 */
134
135 label = gtk_label_new( _("Pixmaps:") );
136 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
137 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
138 rv->pixmaps = gtk_entry_new();
139 gtk_entry_set_editable( GTK_ENTRY( rv->pixmaps ), FALSE );
140 gtk_table_attach_defaults( GTK_TABLE( table ), rv->pixmaps, 1, 2, row, row + 1 );
141 row++;
142
143 label = gtk_label_new( _("Pixmap Bytes:") );
144 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
145 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
146 rv->pixmap_bytes = gtk_entry_new();
147 gtk_entry_set_editable( GTK_ENTRY( rv->pixmap_bytes ), FALSE );
148 gtk_table_attach_defaults( GTK_TABLE( table ), rv->pixmap_bytes, 1, 2, row, row + 1 );
149 row++;
150
151 label = gtk_label_new( _("Windows:") );
152 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
153 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
154 rv->windows = gtk_entry_new();
155 gtk_entry_set_editable( GTK_ENTRY( rv->windows ), FALSE );
156 gtk_table_attach_defaults( GTK_TABLE( table ), rv->windows, 1, 2, row, row + 1 );
157 row++;
158
159 label = gtk_label_new( _("Cursors:") );
160 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
161 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
162 rv->cursors = gtk_entry_new();
163 gtk_entry_set_editable( GTK_ENTRY( rv->cursors ), FALSE );
164 gtk_table_attach_defaults( GTK_TABLE( table ), rv->cursors, 1, 2, row, row + 1 );
165 row++;
166
167 label = gtk_label_new( _("Graphics Contexts:") );
168 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
169 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
170 rv->gcs = gtk_entry_new();
171 gtk_entry_set_editable( GTK_ENTRY( rv->gcs ), FALSE );
172 gtk_table_attach_defaults( GTK_TABLE( table ), rv->gcs, 1, 2, row, row + 1 );
173 row++;
174
175 label = gtk_label_new( _("Fonts:") );
176 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
177 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
178 rv->fonts = gtk_entry_new();
179 gtk_entry_set_editable( GTK_ENTRY( rv->fonts ), FALSE );
180 gtk_table_attach_defaults( GTK_TABLE( table ), rv->fonts, 1, 2, row, row + 1 );
181 row++;
182
183 label = gtk_label_new( _("Pictures:") );
184 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
185 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
186 rv->pictures = gtk_entry_new();
187 gtk_entry_set_editable( GTK_ENTRY( rv->pictures ), FALSE );
188 gtk_table_attach_defaults( GTK_TABLE( table ), rv->pictures, 1, 2, row, row + 1 );
189 row++;
190
191 label = gtk_label_new( _("Glyphsets:") );
192 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
193 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
194 rv->glyphsets = gtk_entry_new();
195 gtk_entry_set_editable( GTK_ENTRY( rv->glyphsets ), FALSE );
196 gtk_table_attach_defaults( GTK_TABLE( table ), rv->glyphsets, 1, 2, row, row + 1 );
197 row++;
198
199 label = gtk_label_new( _("Colormap Entries:") );
200 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
201 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
202 rv->colormaps = gtk_entry_new();
203 gtk_entry_set_editable( GTK_ENTRY( rv->colormaps ), FALSE );
204 gtk_table_attach_defaults( GTK_TABLE( table ), rv->colormaps, 1, 2, row, row + 1 );
205 row++;
206
207 label = gtk_label_new( _("Passive Grabs:") );
208 gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
209 gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 );
210 rv->pgrabs = gtk_entry_new();
211 gtk_entry_set_editable( GTK_ENTRY( rv->pgrabs ), FALSE );
212 gtk_table_attach_defaults( GTK_TABLE( table ), rv->pgrabs, 1, 2, row, row + 1 );
213 row++;
214
215 rv->main = vbox;
216 return rv;
217 }
218
xresview_delete(xresview_t * rv)219 void xresview_delete( xresview_t *rv )
220 {
221 free( rv );
222 }
223
xresview_clear(xresview_t * rv,Display * dpy,Window root)224 void xresview_clear( xresview_t *rv, Display *dpy, Window root )
225 {
226 gtk_entry_set_text( GTK_ENTRY( rv->pixmaps ), "" );
227 gtk_entry_set_text( GTK_ENTRY( rv->pixmap_bytes ), "" );
228 gtk_entry_set_text( GTK_ENTRY( rv->windows ), "" );
229 gtk_entry_set_text( GTK_ENTRY( rv->gcs ), "" );
230 gtk_entry_set_text( GTK_ENTRY( rv->fonts ), "" );
231 gtk_entry_set_text( GTK_ENTRY( rv->pictures ), "" );
232 gtk_entry_set_text( GTK_ENTRY( rv->glyphsets ), "" );
233 gtk_entry_set_text( GTK_ENTRY( rv->cursors ), "" );
234 gtk_entry_set_text( GTK_ENTRY( rv->colormaps ), "" );
235 gtk_entry_set_text( GTK_ENTRY( rv->pgrabs ), "" );
236 if( rv->clients ) {
237 XFree( rv->clients );
238 }
239 XResQueryClients( dpy, &rv->numclients, &rv->clients );
240 }
241
is_application_window(Display * dpy,Window win)242 static int is_application_window( Display *dpy, Window win )
243 {
244 Atom type_return;
245 int format_return;
246 unsigned long bytes_after_return;
247 unsigned long nitems_return;
248 unsigned char *prop_return = 0;
249
250 if( XGetWindowProperty( dpy, win, wm_state, 0,
251 4, False, AnyPropertyType,
252 &type_return, &format_return,
253 &nitems_return, &bytes_after_return,
254 &prop_return ) != Success ) {
255 return 0;
256 }
257 if( nitems_return ) {
258 XFree( prop_return );
259 }
260 if( !type_return ) {
261 return 0;
262 }
263
264 return 1;
265 }
266
xresview_load(xresview_t * rv,Display * dpy,Window win,Window root)267 void xresview_load( xresview_t *rv, Display *dpy, Window win, Window root )
268 {
269 Atom type_return;
270 int format_return;
271 unsigned long bytes_after_return;
272 unsigned long nitems_return;
273 unsigned char *prop_return = 0;
274 int i;
275
276 load_atoms( dpy );
277
278 if( !is_application_window( dpy, win ) ) {
279 return;
280 }
281
282 for( i = 0; i < rv->numclients; i++ ) {
283 unsigned int match_xid;
284
285 match_xid = (rv->clients[ i ].resource_base & ~rv->clients[ i ].resource_mask);
286 if( (win & ~rv->clients[ i ].resource_mask) == match_xid ) {
287 XResType *types;
288 char text[ 256 ];
289 unsigned long bytes;
290 int numtypes;
291 int j;
292
293 XResQueryClientPixmapBytes( dpy, win, &bytes );
294 sprintf( text, "%ld", bytes );
295 gtk_entry_set_text( GTK_ENTRY( rv->pixmap_bytes ), text );
296
297 XResQueryClientResources( dpy, win, &numtypes, &types );
298 for( j = 0; j < numtypes; j++ ) {
299 if( types[ j ].resource_type == res_pixmap ) {
300 sprintf( text, "%u", types[ j ].count );
301 gtk_entry_set_text( GTK_ENTRY( rv->pixmaps ), text );
302 } else if( types[ j ].resource_type == res_window ) {
303 sprintf( text, "%u", types[ j ].count );
304 gtk_entry_set_text( GTK_ENTRY( rv->windows ), text );
305 } else if( types[ j ].resource_type == res_gc ) {
306 sprintf( text, "%u", types[ j ].count );
307 gtk_entry_set_text( GTK_ENTRY( rv->gcs ), text );
308 } else if( types[ j ].resource_type == res_font ) {
309 sprintf( text, "%u", types[ j ].count );
310 gtk_entry_set_text( GTK_ENTRY( rv->fonts ), text );
311 } else if( types[ j ].resource_type == res_picture ) {
312 sprintf( text, "%u", types[ j ].count );
313 gtk_entry_set_text( GTK_ENTRY( rv->pictures ), text );
314 } else if( types[ j ].resource_type == res_glyphset ) {
315 sprintf( text, "%u", types[ j ].count );
316 gtk_entry_set_text( GTK_ENTRY( rv->glyphsets ), text );
317 } else if( types[ j ].resource_type == res_colormap_entry ) {
318 sprintf( text, "%u", types[ j ].count );
319 gtk_entry_set_text( GTK_ENTRY( rv->colormaps ), text );
320 } else if( types[ j ].resource_type == res_passive_grab ) {
321 sprintf( text, "%u", types[ j ].count );
322 gtk_entry_set_text( GTK_ENTRY( rv->pgrabs ), text );
323 } else if( types[ j ].resource_type == res_cursor ) {
324 sprintf( text, "%u", types[ j ].count );
325 gtk_entry_set_text( GTK_ENTRY( rv->cursors ), text );
326 }
327 }
328 if( numtypes ) {
329 XFree( types );
330 }
331
332 return;
333 }
334 }
335 }
336
xresview_get_widget(xresview_t * rv)337 GtkWidget *xresview_get_widget( xresview_t *rv )
338 {
339 return rv->main;
340 }
341
342