/** * Copyright (C) 2004 Billy Biggs . * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef ENABLE_NLS # define _(string) gettext (string) # include "gettext.h" #else # define _(string) string #endif #include "xwinview.h" struct xwinview_s { GtkTreeStore *store; GtkWidget *scrolled; }; enum { ID_COLUMN, NAME_COLUMN, X_COLUMN, Y_COLUMN, W_COLUMN, H_COLUMN, EVENTS_COLUMN, OVERRIDE_COLUMN, N_COLUMNS }; xwinview_t *xwinview_new( void ) { xwinview_t *wv = malloc( sizeof( xwinview_t ) ); GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkWidget *tree; wv->scrolled = gtk_scrolled_window_new( 0, 0 ); wv->store = gtk_tree_store_new( N_COLUMNS, G_TYPE_STRING, // id G_TYPE_STRING, // name G_TYPE_STRING, // x G_TYPE_STRING, // y G_TYPE_STRING, // w G_TYPE_STRING, // h G_TYPE_STRING, // events G_TYPE_STRING); // override tree = gtk_tree_view_new_with_model( GTK_TREE_MODEL( wv->store ) ); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Window"), renderer, "text", ID_COLUMN, 0 ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Name"), renderer, "text", NAME_COLUMN, 0 ); gtk_tree_view_column_set_min_width( column, 50 ); gtk_tree_view_column_set_max_width( column, 50 ); gtk_tree_view_column_set_resizable( column, TRUE ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Override"), renderer, "text", OVERRIDE_COLUMN, 0 ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("X"), renderer, "text", X_COLUMN, 0 ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Y"), renderer, "text", Y_COLUMN, 0 ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Width"), renderer, "text", W_COLUMN, 0 ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Height"), renderer, "text", H_COLUMN, 0 ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( _("Events"), renderer, "text", EVENTS_COLUMN, 0 ); gtk_tree_view_column_set_min_width( column, 100 ); gtk_tree_view_column_set_max_width( column, 100 ); gtk_tree_view_column_set_resizable( column, TRUE ); gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); gtk_container_add( GTK_CONTAINER( wv->scrolled ), tree ); return wv; } void xwinview_delete( xwinview_t *wv ) { free( wv ); } /** * This tries to print a pretty string describing the event mask. I * think it's useful, but flawed, as I don't think I necessarily lump * together the right events in each category, and some categories could * use better names. If you have suggestions, please let me know! */ static void print_event_mask( char *data, long mask ) { int seen = 0; *data = 0; if( mask & KeyPressMask || mask & KeyReleaseMask || mask & KeymapStateMask) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Key") ); } if( mask & ButtonPressMask || mask & ButtonReleaseMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Button") ); } if( mask & EnterWindowMask || mask & LeaveWindowMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Enter") ); } if( mask & PointerMotionMask || mask & PointerMotionHintMask || mask & Button1MotionMask || mask & Button2MotionMask || mask & Button3MotionMask || mask & Button4MotionMask || mask & Button5MotionMask || mask & ButtonMotionMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Mouse") ); } if( mask & ExposureMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Expose") ); } if( mask & VisibilityChangeMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Visibility") ); } if( mask & StructureNotifyMask || mask & ResizeRedirectMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Resize") ); } if( mask & SubstructureNotifyMask || mask & SubstructureRedirectMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Substructure") ); } if( mask & FocusChangeMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Focus") ); } if( mask & ColormapChangeMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Colormap") ); } if( mask & OwnerGrabButtonMask ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Grab") ); } } /** * Prints the name of the Window. I think this can be better, using * _NET_WM_NAME and the visible ones as appropriate. Ideally we should * follow some window manager's algorithm. ?? */ static void print_name( char *name, Display *dpy, Window win, Window root ) { XTextProperty nameprop; char *wname; if( XGetWMName( dpy, win, &nameprop ) ) { sprintf( name, "%s", nameprop.value ); XFree( nameprop.value ); } else if( XFetchName( dpy, win, &wname ) ) { sprintf( name, "%s", wname ); XFree( wname ); } else if( win == root ) { sprintf( name, "Root" ); } else { sprintf( name, " " ); } } void xwinview_clear( xwinview_t *wv, Display *dpy, Window root ) { gtk_tree_store_clear( wv->store ); } void xwinview_load( xwinview_t *wv, Display *dpy, Window win, Window root ) { XWindowAttributes attrs; GtkTreeIter iter; char id[ 30 ]; char name[ 500 ]; char xtext[ 30 ]; char ytext[ 30 ]; char wtext[ 30 ]; char htext[ 30 ]; char override[ 30 ]; char eventmask[ 255 ]; XGetWindowAttributes( dpy, win, &attrs ); sprintf( id, "0x%x", (unsigned int) win ); sprintf( xtext, "%d", attrs.x ); sprintf( ytext, "%d", attrs.y ); sprintf( wtext, "%d", attrs.width ); sprintf( htext, "%d", attrs.height ); print_event_mask( eventmask, attrs.all_event_masks ); print_name( name, dpy, win, root ); sprintf( override, "%s", attrs.override_redirect ? _("Yes") : "" ); gtk_tree_store_append( wv->store, &iter, 0 ); gtk_tree_store_set( wv->store, &iter, ID_COLUMN, id, NAME_COLUMN, name, X_COLUMN, xtext, Y_COLUMN, ytext, W_COLUMN, wtext, H_COLUMN, htext, EVENTS_COLUMN, eventmask, OVERRIDE_COLUMN, override, -1 ); } GtkWidget *xwinview_get_widget( xwinview_t *wv ) { return wv->scrolled; }