/** * 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 #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 "ewmhview.h" struct ewmhview_s { GtkWidget *main; GtkWidget *name; GtkWidget *icon_name; GtkWidget *visible_name; GtkWidget *visible_icon_name; GtkWidget *state; GtkWidget *type; GtkWidget *machine; GtkWidget *command; GtkWidget *pid; GtkWidget *user_time; GtkWidget *desktop; GtkWidget *actions; GtkWidget *wm_name; GtkWidget *supported_states; GtkWidget *supported_actions; GtkWidget *num_desktops; GtkWidget *cur_desktop; GtkWidget *active_window; }; ewmhview_t *ewmhview_new( void ) { ewmhview_t *ev = malloc( sizeof( ewmhview_t ) ); GtkWidget *table; GtkWidget *frame; GtkWidget *vbox; GtkWidget *align; GtkWidget *label; int row = 0; if( !ev ) return 0; vbox = gtk_vbox_new( FALSE, 2 ); frame = gtk_frame_new( _("Window Hints") ); align = gtk_alignment_new( 0.5, 0.0, 0.95, 0.0 ); table = gtk_table_new( 10, 2, FALSE ); label = gtk_label_new( _("Name:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->name = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->name ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->name, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Icon Name:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->icon_name = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->icon_name ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->icon_name, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Visible Name:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->visible_name = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->visible_name ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->visible_name, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Visible Icon Name:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->visible_icon_name = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->visible_icon_name ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->visible_icon_name, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("State:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->state = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->state ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->state, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Type:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->type = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->type ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->type, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Actions:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->actions = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->actions ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->actions, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Client Machine:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->machine = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->machine ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->machine, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Command:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->command = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->command ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->command, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("PID:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->pid = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->pid ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->pid, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Desktop:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->desktop = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->desktop ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->desktop, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("User Time:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->user_time = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->user_time ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->user_time, 1, 2, row, row + 1 ); row++; gtk_container_add( GTK_CONTAINER( align ), table ); gtk_container_add( GTK_CONTAINER( frame ), align ); gtk_box_pack_start( GTK_BOX( vbox ), frame, TRUE, TRUE, 2 ); frame = gtk_frame_new( _("Global Hints") ); align = gtk_alignment_new( 0.5, 0.0, 0.95, 0.0 ); table = gtk_table_new( 6, 2, FALSE ); row = 0; label = gtk_label_new( _("Window Manager:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->wm_name = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->wm_name ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->wm_name, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Supported States:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->supported_states = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->supported_states ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->supported_states, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Supported Actions:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->supported_actions = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->supported_actions ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->supported_actions, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Number of Desktops:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->num_desktops = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->num_desktops ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->num_desktops, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Current Desktop:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->cur_desktop = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->cur_desktop ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->cur_desktop, 1, 2, row, row + 1 ); row++; label = gtk_label_new( _("Active Window:") ); gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 ); gtk_table_attach( GTK_TABLE( table ), label, 0, 1, row, row + 1, GTK_SHRINK, GTK_SHRINK, 2, 2 ); ev->active_window = gtk_entry_new(); gtk_entry_set_editable( GTK_ENTRY( ev->active_window ), FALSE ); gtk_table_attach_defaults( GTK_TABLE( table ), ev->active_window, 1, 2, row, row + 1 ); row++; gtk_container_add( GTK_CONTAINER( align ), table ); gtk_container_add( GTK_CONTAINER( frame ), align ); gtk_box_pack_start( GTK_BOX( vbox ), frame, TRUE, TRUE, 2 ); ev->main = vbox; return ev; } void ewmhview_delete( ewmhview_t *ev ) { free( ev ); } static Atom net_wm_name; static Atom net_wm_visible_name; static Atom net_wm_icon_name; static Atom net_wm_visible_icon_name; static Atom utf8_string; static Atom wm_state; static Atom net_wm_state; static Atom net_wm_state_modal; static Atom net_wm_state_sticky; static Atom net_wm_state_maximized_vert; static Atom net_wm_state_maximized_horz; static Atom net_wm_state_shaded; static Atom net_wm_state_skip_taskbar; static Atom net_wm_state_skip_pager; static Atom net_wm_state_hidden; static Atom net_wm_state_fullscreen; static Atom net_wm_state_above; static Atom net_wm_state_below; static Atom net_wm_window_type; static Atom net_wm_window_type_desktop; static Atom net_wm_window_type_dock; static Atom net_wm_window_type_toolbar; static Atom net_wm_window_type_menu; static Atom net_wm_window_type_utility; static Atom net_wm_window_type_splash; static Atom net_wm_window_type_dialog; static Atom net_wm_window_type_normal; static Atom net_wm_pid; static Atom net_wm_user_time; static Atom net_wm_allowed_actions; static Atom net_wm_action_move; static Atom net_wm_action_resize; static Atom net_wm_action_minimize; static Atom net_wm_action_shade; static Atom net_wm_action_stick; static Atom net_wm_action_maximize_horz; static Atom net_wm_action_maximize_vert; static Atom net_wm_action_fullscreen; static Atom net_wm_action_change_desktop; static Atom net_wm_action_close; static Atom net_wm_desktop; static Atom net_supporting_wm_check; static Atom net_supported; static Atom net_number_of_desktops; static Atom net_current_desktop; static Atom net_active_window; static Atom wm_client_machine; static Atom wm_command; static int atoms_loaded = 0; static char *wm_name; static int wm_name_checked = 0; /** * Cache every atom we need. This minimizes round trips to the server. * The number of atoms and their position is hardcoded, but it's small. * Making this look pretty I think would be too annoying to be worth it. */ static void load_atoms( Display *dpy ) { static char *atom_names[] = { "_NET_WM_NAME", "_NET_WM_VISIBLE_NAME", "_NET_WM_ICON_NAME", "_NET_WM_VISIBLE_ICON_NAME", "UTF8_STRING", "WM_STATE", "_NET_WM_STATE", "_NET_WM_STATE_MODAL", "_NET_WM_STATE_STICKY", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_SHADED", "_NET_WM_STATE_SKIP_TASKBAR", "_NET_WM_STATE_SKIP_PAGER", "_NET_WM_STATE_HIDDEN", "_NET_WM_STATE_FULLSCREEN", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_BELOW", "_NET_WM_WINDOW_TYPE", "_NET_WM_WINDOW_TYPE_DESKTOP", "_NET_WM_WINDOW_TYPE_DOCK", "_NET_WM_WINDOW_TYPE_TOOLBAR", "_NET_WM_WINDOW_TYPE_MENU", "_NET_WM_WINDOW_TYPE_UTILITY", "_NET_WM_WINDOW_TYPE_SPLASH", "_NET_WM_WINDOW_TYPE_DIALOG", "_NET_WM_WINDOW_TYPE_NORMAL", "_NET_WM_PID", "_NET_WM_USER_TIME", "_NET_WM_ALLOWED_ACTIONS", "_NET_WM_ACTION_MOVE", "_NET_WM_ACTION_RESIZE", "_NET_WM_ACTION_MINIMIZE", "_NET_WM_ACTION_SHADE", "_NET_WM_ACTION_STICK", "_NET_WM_ACTION_MAXIMIZE_HORZ", "_NET_WM_ACTION_MAXIMIZE_VERT", "_NET_WM_ACTION_FULLSCREEN", "_NET_WM_ACTION_CHANGE_DESKTOP", "_NET_WM_ACTION_CLOSE", "_NET_WM_DESKTOP", "_NET_SUPPORTING_WM_CHECK", "_NET_SUPPORTED", "_NET_NUMBER_OF_DESKTOPS", "_NET_CURRENT_DESKTOP", "_NET_ACTIVE_WINDOW", "WM_CLIENT_MACHINE", "WM_COMMAND" }; Atom atoms_return[ 48 ]; if( atoms_loaded ) return; XInternAtoms( dpy, atom_names, 48, False, atoms_return ); net_wm_name = atoms_return[ 0 ]; net_wm_visible_name = atoms_return[ 1 ]; net_wm_icon_name = atoms_return[ 2 ]; net_wm_visible_icon_name = atoms_return[ 3 ]; utf8_string = atoms_return[ 4 ]; wm_state = atoms_return[ 5 ]; net_wm_state = atoms_return[ 6 ]; net_wm_state_modal = atoms_return[ 7 ]; net_wm_state_sticky = atoms_return[ 8 ]; net_wm_state_maximized_vert = atoms_return[ 9 ]; net_wm_state_maximized_horz = atoms_return[ 10 ]; net_wm_state_shaded = atoms_return[ 11 ]; net_wm_state_skip_taskbar = atoms_return[ 12 ]; net_wm_state_skip_pager = atoms_return[ 13 ]; net_wm_state_hidden = atoms_return[ 14 ]; net_wm_state_fullscreen = atoms_return[ 15 ]; net_wm_state_above = atoms_return[ 16 ]; net_wm_state_below = atoms_return[ 17 ]; net_wm_window_type = atoms_return[ 18 ]; net_wm_window_type_desktop = atoms_return[ 19 ]; net_wm_window_type_dock = atoms_return[ 20 ]; net_wm_window_type_toolbar = atoms_return[ 21 ]; net_wm_window_type_menu = atoms_return[ 22 ]; net_wm_window_type_utility = atoms_return[ 23 ]; net_wm_window_type_splash = atoms_return[ 24 ]; net_wm_window_type_dialog = atoms_return[ 25 ]; net_wm_window_type_normal = atoms_return[ 26 ]; net_wm_pid = atoms_return[ 27 ]; net_wm_user_time = atoms_return[ 28 ]; net_wm_allowed_actions = atoms_return[ 29 ]; net_wm_action_move = atoms_return[ 30 ]; net_wm_action_resize = atoms_return[ 31 ]; net_wm_action_minimize = atoms_return[ 32 ]; net_wm_action_shade = atoms_return[ 33 ]; net_wm_action_stick = atoms_return[ 34 ]; net_wm_action_maximize_horz = atoms_return[ 35 ]; net_wm_action_maximize_vert = atoms_return[ 36 ]; net_wm_action_fullscreen = atoms_return[ 37 ]; net_wm_action_change_desktop = atoms_return[ 38 ]; net_wm_action_close = atoms_return[ 39 ]; net_wm_desktop = atoms_return[ 40 ]; net_supporting_wm_check = atoms_return[ 41 ]; net_supported = atoms_return[ 42 ]; net_number_of_desktops = atoms_return[ 43 ]; net_current_desktop = atoms_return[ 44 ]; net_active_window = atoms_return[ 45 ]; wm_client_machine = atoms_return[ 46 ]; wm_command = atoms_return[ 47 ]; atoms_loaded = 1; } /** * Returns the window name for an Extended Window Manager Hints (EWMH) * compliant window manager. Sets the name to "unknown" if no name is * set (non-compliant by the spec, but worth handling). */ static void get_window_manager_name( Display *dpy, Window wm_window, char **wm_name_return ) { Atom type_return; int format_return; unsigned long bytes_after_return; unsigned long nitems_return; unsigned char *prop_return = 0; if( XGetWindowProperty( dpy, wm_window, net_wm_name, 0, 4, False, XA_STRING, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) != Success ) { *wm_name_return = strdup( _("unknown") ); return; } if( type_return == None ) { *wm_name_return = strdup( _("unknown") ); XFree( prop_return ); return; } if( type_return != XA_STRING ) { XFree( prop_return ); if( type_return == utf8_string ) { if( XGetWindowProperty( dpy, wm_window, net_wm_name, 0, 4, False, utf8_string, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) != Success ) { *wm_name_return = strdup( _("unknown") ); return; } if( format_return == 8 ) { *wm_name_return = strdup( (char *) prop_return ); } XFree( prop_return ); } else { *wm_name_return = strdup( _("unknown") ); return; } } else { if( format_return == 8 ) { *wm_name_return = strdup( (char *) prop_return ); } XFree( prop_return ); } } /* Used for error handling. */ static unsigned long req_serial; static int (*prev_xerrhandler)( Display *dpy, XErrorEvent *ev ); static int xprop_errorhandler( Display *dpy, XErrorEvent *ev ) { if( ev->serial == req_serial ) { /* this is an error to the XGetWindowProperty request * most probable the window specified by the property * _NET_SUPPORTING_WM_CHECK on the root window no longer exists */ return 0; } else { /* if we get another error we should handle it, * so we give it to the previous errorhandler */ return prev_xerrhandler( dpy, ev ); } } /** * returns 1 if a window manager compliant to the * Extended Window Manager Hints (EWMH) spec is running. * (version 1.2) * Oterhwise returns 0. */ static int check_for_EWMH_wm( Display *dpy, char **wm_name_return ) { Atom type_return; int format_return; unsigned long nitems_return; unsigned long bytes_after_return; unsigned char *prop_return = 0; if( XGetWindowProperty( dpy, DefaultRootWindow( dpy ), net_supporting_wm_check, 0, 1, False, XA_WINDOW, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) != Success ) { return 0; } if( type_return == None ) { return 0; } if( type_return != XA_WINDOW ) { if( prop_return ) XFree( prop_return ); return 0; } if( format_return == 32 && nitems_return == 1 && bytes_after_return == 0 ) { Window win_id = *( (long *) prop_return ); int status; XFree( prop_return ); prop_return = 0; /* Make sure we don't have any unhandled errors. */ XSync( dpy, False ); /* Set error handler so we can check if XGetWindowProperty failed. */ prev_xerrhandler = XSetErrorHandler( xprop_errorhandler ); /* get the serial of the XGetWindowProperty request */ req_serial = NextRequest( dpy ); /* try to get property * this can fail if we have a property with the win_id on the * root window, but the win_id is no longer valid. * This is to check for a stale window manager */ status = XGetWindowProperty( dpy, win_id, net_supporting_wm_check, 0, 1, False, XA_WINDOW, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ); /* make sure XGetWindowProperty has been processed and any errors have been returned to us */ XSync( dpy, False ); /* revert to the previous xerrorhandler */ XSetErrorHandler( prev_xerrhandler ); if( status != Success || type_return == None ) { return 0; } if( type_return == XA_CARDINAL ) { /* Hack for old and busted metacity. */ /* Allow this atom to be a CARDINAL. */ XGetWindowProperty( dpy, win_id, net_supporting_wm_check, 0, 1, False, XA_CARDINAL, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ); } else if( type_return != XA_WINDOW ) { if( prop_return ) { XFree( prop_return ); } return 0; } if( format_return == 32 && nitems_return == 1 && bytes_after_return == 0 ) { if( win_id == *( (long *) prop_return ) ) { /* We have successfully detected a EWMH compliant Window Manager. */ XFree( prop_return ); /* Get the name of the wm */ get_window_manager_name( dpy, win_id, wm_name_return ); return 1; } XFree( prop_return ); return 0; } else if( prop_return ) { XFree( prop_return ); } } else if( prop_return ) { XFree( prop_return ); } return 0; } static int is_application_window( Display *dpy, Window win ) { Atom type_return; int format_return; unsigned long bytes_after_return; unsigned long nitems_return; unsigned char *prop_return = 0; if( XGetWindowProperty( dpy, win, wm_state, 0, 4, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) != Success ) { return 0; } if( nitems_return ) { XFree( prop_return ); } if( !type_return ) { return 0; } return 1; } void ewmhview_clear( ewmhview_t *ev, Display *dpy, Window root ) { Atom type_return; int format_return; unsigned long bytes_after_return; unsigned long nitems_return; unsigned char *prop_return = 0; load_atoms( dpy ); gtk_entry_set_text( GTK_ENTRY( ev->name ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->icon_name ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->visible_name ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->visible_icon_name ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->state ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->type ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->machine ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->command ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->pid ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->user_time ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->desktop ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->actions ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->cur_desktop ), "" ); gtk_entry_set_text( GTK_ENTRY( ev->active_window ), "" ); /* Query global properties. */ if( XGetWindowProperty( dpy, root, net_wm_desktop, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char text[ 256 ]; sprintf( text, "%d", *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->desktop ), text ); XFree( prop_return ); } if( XGetWindowProperty( dpy, root, net_current_desktop, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char text[ 256 ]; sprintf( text, "%d", *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->cur_desktop ), text ); XFree( prop_return ); } if( XGetWindowProperty( dpy, root, net_active_window, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char *dest_name; char text[ 256 ]; XFetchName( dpy, *((unsigned int *) prop_return), &dest_name ); sprintf( text, "%s [%x]", dest_name, *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->active_window ), text ); XFree( prop_return ); XFree( dest_name ); } if( XGetWindowProperty( dpy, root, net_supported, 0, 4096, False, XA_ATOM, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { unsigned char *cur_val = prop_return; char string[ 4096 ]; char *data = string; int seen = 0; *string = 0; while( nitems_return ) { Atom result = *((Atom *) cur_val); if( result == net_wm_state_modal ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Modal") ); } else if( result == net_wm_state_sticky ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Sticky") ); } else if( result == net_wm_state_maximized_vert ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("MaximizedVert") ); } else if( result == net_wm_state_maximized_horz ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("MaximizedHorz") ); } else if( result == net_wm_state_shaded ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Shaded") ); } else if( result == net_wm_state_skip_taskbar ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("SkipTaskbar") ); } else if( result == net_wm_state_skip_pager ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("SkipPager") ); } else if( result == net_wm_state_hidden ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Hidden") ); } else if( result == net_wm_state_fullscreen ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Fullscreen") ); } else if( result == net_wm_state_above ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Above") ); } else if( result == net_wm_state_below ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Below") ); } cur_val += sizeof( Atom ); nitems_return--; } gtk_entry_set_text( GTK_ENTRY( ev->supported_states ), string ); XFree( prop_return ); } if( XGetWindowProperty( dpy, root, net_supported, 0, 4096, False, XA_ATOM, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { unsigned char *cur_val = prop_return; char string[ 4096 ]; char *data = string; int seen = 0; *string = 0; while( nitems_return ) { Atom result = *((Atom *) cur_val); if( result == net_wm_action_move ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Move") ); } else if( result == net_wm_action_resize ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Resize") ); } else if( result == net_wm_action_minimize ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Minimize") ); } else if( result == net_wm_action_shade ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Shade") ); } else if( result == net_wm_action_stick ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Stick") ); } else if( result == net_wm_action_maximize_horz ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("MaximizeHorz") ); } else if( result == net_wm_action_maximize_vert ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("MaximizeVert") ); } else if( result == net_wm_action_fullscreen ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Fullscreen") ); } else if( result == net_wm_action_change_desktop ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("ChangeDesktop") ); } else if( result == net_wm_action_close ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Close") ); } cur_val += sizeof( Atom ); nitems_return--; } gtk_entry_set_text( GTK_ENTRY( ev->supported_actions ), string ); XFree( prop_return ); } if( XGetWindowProperty( dpy, root, net_number_of_desktops, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char text[ 256 ]; sprintf( text, "%d", *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->num_desktops ), text ); XFree( prop_return ); } } void ewmhview_load( ewmhview_t *ev, Display *dpy, Window win, Window root ) { Atom type_return; int format_return; unsigned long bytes_after_return; unsigned long nitems_return; unsigned char *prop_return = 0; XTextProperty textprop; char **argv; int argc; load_atoms( dpy ); if( !is_application_window( dpy, win ) ) { return; } if( !wm_name_checked ) { check_for_EWMH_wm( dpy, &wm_name ); gtk_entry_set_text( GTK_ENTRY( ev->wm_name ), wm_name ); wm_name_checked = 1; } if( XGetWindowProperty( dpy, win, net_wm_name, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { gtk_entry_set_text( GTK_ENTRY( ev->name ), (char *) prop_return ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_icon_name, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { gtk_entry_set_text( GTK_ENTRY( ev->icon_name ), (char *) prop_return ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_visible_name, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { gtk_entry_set_text( GTK_ENTRY( ev->visible_name ), (char *) prop_return ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_visible_icon_name, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { gtk_entry_set_text( GTK_ENTRY( ev->visible_icon_name ), (char *) prop_return ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_state, 0, 4096, False, XA_ATOM, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { unsigned char *cur_val = prop_return; char string[ 4096 ]; char *data = string; int seen = 0; *string = 0; while( nitems_return ) { Atom result = *((Atom *) cur_val); if( result == net_wm_state_modal ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Modal") ); } else if( result == net_wm_state_sticky ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Sticky") ); } else if( result == net_wm_state_maximized_vert ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("MaximizedVert") ); } else if( result == net_wm_state_maximized_horz ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("MaximizedHorz") ); } else if( result == net_wm_state_shaded ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Shaded") ); } else if( result == net_wm_state_skip_taskbar ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("SkipTaskbar") ); } else if( result == net_wm_state_skip_pager ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("SkipPager") ); } else if( result == net_wm_state_hidden ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Hidden") ); } else if( result == net_wm_state_fullscreen ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Fullscreen") ); } else if( result == net_wm_state_above ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Above") ); } else if( result == net_wm_state_below ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Below") ); } cur_val += sizeof( Atom ); nitems_return--; } gtk_entry_set_text( GTK_ENTRY( ev->state ), string ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_window_type, 0, 4096, False, XA_ATOM, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { unsigned char *cur_val = prop_return; char string[ 4096 ]; char *data = string; int seen = 0; *string = 0; while( nitems_return ) { Atom result = *((Atom *) cur_val); if( result == net_wm_window_type_desktop ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Desktop") ); } else if( result == net_wm_window_type_dock ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Dock") ); } else if( result == net_wm_window_type_toolbar ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Toolbar") ); } else if( result == net_wm_window_type_menu ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Menu") ); } else if( result == net_wm_window_type_utility ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Utility") ); } else if( result == net_wm_window_type_splash ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Splash") ); } else if( result == net_wm_window_type_dialog ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Dialog") ); } else if( result == net_wm_window_type_normal ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Normal") ); } cur_val += sizeof( Atom ); nitems_return--; } gtk_entry_set_text( GTK_ENTRY( ev->type ), string ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_allowed_actions, 0, 4096, False, XA_ATOM, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { unsigned char *cur_val = prop_return; char string[ 4096 ]; char *data = string; int seen = 0; *string = 0; while( nitems_return ) { Atom result = *((Atom *) cur_val); if( result == net_wm_action_move ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Move") ); } else if( result == net_wm_action_resize ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Resize") ); } else if( result == net_wm_action_minimize ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Minimize") ); } else if( result == net_wm_action_shade ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Shade") ); } else if( result == net_wm_action_stick ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Stick") ); } else if( result == net_wm_action_maximize_horz ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("MaximizeHorz") ); } else if( result == net_wm_action_maximize_vert ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("MaximizeVert") ); } else if( result == net_wm_action_fullscreen ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Fullscreen") ); } else if( result == net_wm_action_change_desktop ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("ChangeDesktop") ); } else if( result == net_wm_action_close ) { if( seen ) { data += sprintf( data, ", " ); } else { seen = 1; } data += sprintf( data, _("Close") ); } cur_val += sizeof( Atom ); nitems_return--; } gtk_entry_set_text( GTK_ENTRY( ev->actions ), string ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_pid, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char text[ 256 ]; sprintf( text, "%d", *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->pid ), text ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_user_time, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char text[ 256 ]; sprintf( text, "%d", *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->user_time ), text ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_wm_desktop, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char text[ 256 ]; sprintf( text, "%d", *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->desktop ), text ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_current_desktop, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char text[ 256 ]; sprintf( text, "%d", *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->cur_desktop ), text ); XFree( prop_return ); } if( XGetWindowProperty( dpy, win, net_active_window, 0, 4096, False, AnyPropertyType, &type_return, &format_return, &nitems_return, &bytes_after_return, &prop_return ) == Success && nitems_return ) { char *dest_name; char text[ 256 ]; XFetchName( dpy, *((unsigned int *) prop_return), &dest_name ); sprintf( text, "%s [%x]", dest_name, *((unsigned int *) prop_return) ); gtk_entry_set_text( GTK_ENTRY( ev->active_window ), text ); XFree( prop_return ); XFree( dest_name ); } if( XGetWMClientMachine( dpy, win, &textprop ) ) { gtk_entry_set_text( GTK_ENTRY( ev->machine ), textprop.value ); XFree( textprop.value ); } if( XGetCommand( dpy, win, &argv, &argc ) ) { char string[ 8192 ]; char *data = string; int i; for( i = 0; i < argc; i++ ) { data += sprintf( data, "%s ", argv[ i ] ); } gtk_entry_set_text( GTK_ENTRY( ev->command ), string ); XFreeStringList( argv ); } } GtkWidget *ewmhview_get_widget( ewmhview_t *ev ) { return ev->main; }