rendered paste body#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <glib.h>#include <glib/gstdio.h>#include <gtk/gtk.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/file.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>#include "eggtrayicon.h"//intl stuff#include<libintl.h>#include<locale.h>#define _(String) gettext (String)#define gettext_noop(String) String#define N_(String) gettext_noop (String)//better error handling#define manager_error(String) g_critical("%s: %s", String, g_strerror(errno))/* enums for the Beryl options */typedef enum { AutoBinding, StrictBinding, XGLBinding} BindingMode;typedef enum { AutoCOW, UseCOW, NoCOW} COWMode;typedef enum { AutoRendering, IndirectRendering, XGLRendering} RenderingMode;typedef enum { AutoPlatform, NvidiaPlatform, AIGLXPlatform, XGLPlatform} PlatformMode;typedef enum { AutoRenderPath, TFPRenderPath, CopyRenderPath} RenderPathMode;typedef enum { Profile1, Profile2, Profile3, Profile4, Profile5} ProfileMode;gchar * fnprofile;gchar * profilefile;gchar * profilefilecontent;gchar * profiles [] = { ".beryl/settings1.Profile", ".beryl/settings2.Profile", ".beryl/settings3.Profile", ".beryl/settings4.Profile", ".beryl/settings5.Profile"};Atom wmAtom;Atom PopupRunning;GMutex * mutx;EggTrayIcon * mainIcon;GtkWidget * menu;GtkTooltips * tips;/* options for Beryl command line */RenderPathMode renderPath = AutoRenderPath;PlatformMode platformMode = AutoPlatform;RenderingMode renderingMode = AutoRendering;COWMode cowMode = AutoCOW;BindingMode bindingMode = AutoBinding;gboolean noGLYield=FALSE;gboolean hasMouse=FALSE;gboolean berylLaunched=FALSE;gboolean decoratorLaunched=FALSE;gboolean reloadingBeryl=FALSE;gboolean reloadingDecorator=FALSE;gboolean XGL=FALSE;gboolean NV9XXX=FALSE;gboolean useFB=TRUE;gint WM=0;gint fallBackWM=0;gint DM=0;gint iconsize=24;gchar* displayname;typedef struct _DMInfo{ gchar * Name; gchar * Prog; GtkWidget * Item;} DMInfo;typedef struct _WMInfo{ gchar * Name; gchar * Prog; gchar * Opts; gchar * Grep; gint xXGL; // if nonzero, can't use on XGL gint Kill; // if nonzero, means has to be killall'd by its grep-name, and should NOT be xkill'd GtkWidget * Item; GtkWidget * FBItem;} WMInfo;typedef struct _XLSItem{ gchar * Command; Window w;} XLSItem;DMInfo DMs[] = { {N_("Standard Beryl Decorator (Emerald)"), "emerald" ,0}, {N_("Aquamarine (KDE Decorator)"), "aquamarine" ,0}, {N_("Heliodor (GNOME/Metacity Decorator)"), "heliodor" ,0}, {N_("Light Themable Decorator (yawd)"), "yawd" ,0}, {N_("GTK Window Decorator"), "gtk-window-decorator" ,0},};#define numDM (gint)(sizeof(DMs)/sizeof(DMInfo))WMInfo WMs[]={ {N_("Beryl"), 0, 0, 0 ,0,0,0,0}, {N_("Compiz"), "compiz", "--replace gconf", "compiz" ,0,0,0,0}, {N_("Compiz with COW"), "compiz", "--use-cow --replace gconf", "compiz" ,0,0,0,0}, {N_("Metacity (Gnome Window Manager)"), "metacity", "--replace", "metacity" ,0,0,0,0}, {N_("KWin (KDE Window Manager)"), "kwin", "--replace", "kwin" ,0,0,0,0}, {N_("xfwm4 (XFCE Window Manager)"), "xfwm4", "", "xfwm4" ,0,1,0,0}, {N_("WindowMaker"), "wmaker", "", "WindowMaker" ,0,0,0,0}, {N_("FluxBox"), "fluxbox", "", "fluxbox" ,1,1,0,0}, {N_("BlackBox"), "blackbox", "", "blackbox" ,0,1,0,0}, {N_("OpenBox"), "openbox", "", "openbox" ,0,0,0,0}, {N_("IceWM"), "icewm", "", "icewm" ,0,0,0,0}, {N_("Enlightenment"), "enlightenment", "", "enlightenment" ,0,1,0,0},};#define numWM (gint)(sizeof(WMs)/sizeof(WMInfo))GtkWidget * useFBItem;GtkWidget * FBSubItem;GtkWidget * DMSubItem;GtkWidget * reloadDecoratorItem;void launchWM();void startWM();void init_widgets();void startBeryl();void showMenu(guint,guint32);static Window Window_With_Name (Display * dpy, Window top, char *name);static voidusage (const char *programName){ printf (_("Usage: %s " "[-d] [--no-force-window-manager] [--no-force-decorator] " "[--help] [--version]" "\n"), programName);}static voidsignalHandler (int sig){ static int suspending = 0; switch (sig) { case SIGUSR1: //FIXME, here we should temporarily disable/hide the last "Quit" entry, //Could be missleading to the average user... showMenu(0,gtk_get_current_event_time()); break; case SIGUSR2: if (!suspending) { if (!WM) { WM=fallBackWM + 4; startWM(); suspending = 1; } } else { WM=0; reloadingBeryl=TRUE; startBeryl(); suspending = 0; } break; default: break; }}gchar* display_part(const gchar *p){ gchar *name = g_strdup(p); gchar *tmp; if ((tmp = g_strrstr(name,":"))) { *tmp++ = 0; tmp = g_strdup(tmp); g_free(name); name = tmp; } if ((tmp = g_strrstr(name,"."))) { *tmp = 0; } return name;}void beryl_manager_log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data){ g_log_default_handler (log_domain, log_level, message, user_data); if (log_level <= G_LOG_LEVEL_WARNING) return; if (isatty(0)) g_on_error_query (NULL); else abort();}GSList * parse_xlsclients(gchar * output){ GSList * ret = NULL; gchar * curpos; for(curpos=output;curpos && curpos[0];curpos=strstr(curpos,"\nWindow")) { XLSItem * i; gchar * p; gchar * q; curpos+=8; i=malloc(sizeof(XLSItem)); i->w=strtol(curpos,NULL,16); p=strstr(curpos,"Command: "); if (!p) { g_warning(_("Malformed xlsclients, no command?")); free(i); continue; } q=strchr(p,'\n'); if (!q) { g_warning(_("Malformed xlsclients, no command?")); free(i); continue; } q[0]='\0'; p=g_strdup(p+10); q[0]='\n'; //trim p down to its basename q=strchr(p,' '); if (q) q[0]='\0'; q=strrchr(p,'/'); if (!q) q=p; else q++; i->Command=g_strdup(q); g_free(p); ret=g_slist_prepend(ret,i); } return ret;}void load_settings(){ gchar * path = g_strconcat(g_get_home_dir(),"/.beryl-managerrc",NULL); GKeyFile * f = g_key_file_new(); if (g_key_file_load_from_file(f,path,0,NULL)) { GError * e = NULL; gint i; gboolean b; i=g_key_file_get_integer(f,"wm-settings","active_wm",&e); if (!e) WM=i; e=NULL; i=g_key_file_get_integer(f,"wm-settings","fallback_wm",&e); if (!e) fallBackWM=i; e=NULL; i=g_key_file_get_integer(f,"wm-settings","active_dm",&e); if (!e) DM=i; e=NULL; b=g_key_file_get_boolean(f,"wm-settings","use_fallback_wm",&e); if (!e) useFB=b; e=NULL; i=g_key_file_get_integer(f,"wm-settings","iconsize",&e); if (!e && ( i>=12 && i<=128) ) iconsize=i; e=NULL; i=g_key_file_get_integer(f,"beryl-settings","render_path",&e); if (!e) renderPath = (RenderPathMode) i; e = NULL; i=g_key_file_get_integer(f,"beryl-settings","cow_mode",&e); if (!e) cowMode = (COWMode) i; e = NULL; i=g_key_file_get_integer(f,"beryl-settings","rendering_mode",&e); if (!e) renderingMode = (RenderingMode) i; e = NULL; i=g_key_file_get_integer(f,"beryl-settings","platform",&e); if (!e) platformMode = (PlatformMode) i; e = NULL; i=g_key_file_get_integer(f,"beryl-settings","binding",&e); if (!e) bindingMode = (BindingMode) i; e = NULL; if (!XGL && NV9XXX) { b=g_key_file_get_boolean(f,"beryl-settings", "no_gl_yield",&e); if (!e) noGLYield=b; e=NULL; } else noGLYield=FALSE; } g_key_file_free(f); g_free(path);}void save_settings(){ gchar * path = g_strconcat(g_get_home_dir(),"/.beryl-managerrc",NULL); gchar * data; GKeyFile * f = g_key_file_new(); g_key_file_set_integer(f,"wm-settings","active_wm",WM); g_key_file_set_integer(f,"wm-settings","fallback_wm",fallBackWM); g_key_file_set_integer(f,"wm-settings","active_dm",DM); g_key_file_set_integer(f,"wm-settings","iconsize",iconsize); g_key_file_set_boolean(f,"wm-settings","use_fallback_wm",useFB); g_key_file_set_integer(f,"beryl-settings","render_path",renderPath); g_key_file_set_integer(f,"beryl-settings","cow_mode",cowMode); g_key_file_set_integer(f,"beryl-settings","rendering_mode",renderingMode); g_key_file_set_integer(f,"beryl-settings","platform",platformMode); g_key_file_set_integer(f,"beryl-settings","binding",bindingMode); if (!XGL && NV9XXX) g_key_file_set_boolean(f,"beryl-settings","no_gl_yield", noGLYield); data = g_key_file_to_data(f,NULL,NULL); g_file_set_contents(path,data,-1,NULL); g_key_file_free(f); g_free(path); g_free(data);}gboolean is_running(const gchar * command){ gchar* cmd = g_strconcat("pidof ", command,NULL); gchar* pret; gint i; if (g_spawn_command_line_sync(cmd, &pret, NULL,NULL,NULL)) { g_strchomp(pret); if (pret && *pret) { gchar **pidlist = g_strsplit(pret," ",0); i = 0; while (pidlist[i]) { if (atoi(pidlist[i])) { gchar *buffer; gsize len; gchar *file = g_strconcat("/proc/",pidlist[i],"/environ",NULL); if (g_file_get_contents(file,&buffer,&len,NULL)) { gchar * cp; for(cp=buffer;cp<(buffer+len);cp+=strlen(cp)+1) { if (strncmp(cp,"DISPLAY=",8)==0) { gchar * part = display_part(cp+8); if (strcmp(part,displayname)==0) { g_strfreev(pidlist); g_free(pret); g_free(file); g_free(buffer); g_free(cmd); g_free(part); return TRUE; } g_free(part); } } } g_free(buffer); g_free(file); } i++; } g_strfreev(pidlist); } g_free(pret); } g_free(cmd); return FALSE;}gboolean is_decor_running(){ if (DM>=numDM || DM<0) DM=0; return (is_running(DMs[DM].Prog));}void showMenu(guint button,guint32 time){ gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,time);}gboolean popupClient(GtkWidget * w, GdkEventClient * e, gpointer d){ static GdkAtom my_atom = GDK_NONE; if (my_atom == GDK_NONE) my_atom = gdk_atom_intern("beryl-manager-Popup",1); if (e->message_type==my_atom) { showMenu(0,gtk_get_current_event_time()); return TRUE; } return FALSE;}gboolean buttonUp(GtkWidget * w, GdkEventButton * e, gpointer d){ if (hasMouse) showMenu(e->button,e->time); return TRUE;}gboolean enterNotify(GtkWidget * w, GdkEventCrossing * e, gpointer d){ hasMouse=TRUE; return TRUE;}gboolean leaveNotify(GtkWidget * w, GdkEventCrossing * e, gpointer d){ hasMouse=FALSE; return TRUE;}gboolean destroyNotify(GtkWidget * w, GdkEventClient * e, gpointer d){ init_widgets(); return TRUE;}void startApp(GtkWidget * w, gchar * command){ g_spawn_command_line_async(command,NULL);}gboolean decoratorSignalled(gint signal){ g_warning(_("Decorator caught deadly signal %d"),signal); return FALSE; // terminate for now}gboolean berylSignalled(gint signal){ g_warning(_("Beryl caught deadly signal %d"),signal); return FALSE; // terminate for now}gpointer decorThread(gpointer d){ gint ex=0; gchar *s=NULL; if(decoratorLaunched && !reloadingDecorator) return NULL; decoratorLaunched = FALSE; s = g_strconcat(DMs[DM].Prog," --replace",NULL); do { if(g_spawn_command_line_sync(s,NULL,NULL,&ex,NULL)) { decoratorLaunched = TRUE; if(reloadingDecorator) reloadingDecorator = FALSE; } else { g_warning(_("Couldn't launch selected decorator:%s"),DMs[DM].Name); if(WIFEXITED(ex)) // returned something { g_warning(_("decorator %s returned unsuccessfully"),DMs[DM].Name); if(WEXITSTATUS(ex)) // returned something other than 0 { g_warning(_("decorator %s returned with non-zero status"),DMs[DM].Name); } } else if(WIFSIGNALED(ex)) { g_warning(_("decorator %s was killed by a signal"),DMs[DM].Name); if(!decoratorSignalled(WTERMSIG(ex))) { } } } }while(!decoratorLaunched); g_free(s); return NULL;}void killIfWM(XLSItem * i, Display * d){ gint j; for (j=1;j<numWM;j++) { if (!WMs[j].Kill) { if (strcmp(i->Command,WMs[j].Grep)==0) { g_message(_("Killing window %x for client %s."),(unsigned int)i->w,WMs[j].Name); XKillClient(d,i->w); } } }}void freeXLS(XLSItem * i, gpointer p){ g_free(i->Command); free(i);}void killWM(){ gint killed = 0; if (!g_mutex_trylock(mutx)) return; { Display * d = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); XLockDisplay(d); { gint i; for (i=1;i<numWM;i++) { if (WMs[i].Kill) { gchar * pret; gchar * cm = g_strconcat("pidof ",WMs[i].Grep,NULL); if (!g_spawn_command_line_sync(cm,&pret,NULL,NULL,NULL)) g_warning(_("No pidof, this may not work right.")); else { g_strchomp(pret); if (pret) { gchar * cret; if (strlen(pret)) { if (pret[strlen(pret)-1]=='\n') pret[strlen(pret)-1]='\0'; for (cret=pret-1;cret;cret=strchr(cret,' ')) { gchar * p; gchar * e; gchar * f; pid_t pid; gsize l; cret++; p=strchr(cret,' '); if (p) p[0]='\0'; f=g_strdup_printf("/proc/%s/environ",cret); pid=strtol(cret,NULL,10); if (p) p[0]=' '; if (g_file_get_contents(f,&e,&l,NULL)) { gchar * cp; for(cp=e;(cp-e)<l;cp+=strlen(cp)+1) { if (strncmp(cp,"DISPLAY=",8)==0) { //might be killable gchar * md = display_part(cp+8); if (strcmp(md,displayname)==0) { //on same display, go ahead kill if (kill(pid,SIGTERM)!=-1) killed++; } g_free(md); } } g_free(e); } else { g_warning("Couldn't open %s",f); } g_free(f); } } g_free(pret); } } g_free(cm); } } Window w=wmAtom?XGetSelectionOwner(d,wmAtom):None; if (w!=None) XKillClient(d,w); else if (killed) { gchar * cli; GSList * xls; g_warning(_("Couldn't find a Selection Owner, perhaps no WM running?\nOtherwise, manually kill your wm, and report the bug to the developers, it doesn't follow the standards.\nFalling back to looking for a defined WM in xlsclients.")); if (!g_spawn_command_line_sync("xlsclients -l",&cli,NULL,NULL,NULL)) { g_warning(_("No xlsclients, this may not work right.")); } else { if (!cli) manager_error(_("No output from xlsclients, bailing.")); xls=parse_xlsclients(cli); g_free(cli); g_slist_foreach(xls,(GFunc)killIfWM,d); g_slist_foreach(xls,(GFunc)freeXLS,NULL); g_slist_free(xls); } } XSync(d,FALSE); } XUnlockDisplay(d); } g_mutex_unlock(mutx);}void startWM(){ gchar * wm_command=g_strjoin(" ",WMs[WM].Prog,WMs[WM].Opts,NULL); berylLaunched=FALSE; killWM(); g_spawn_command_line_async(wm_command,NULL); g_free(wm_command);}#define BERYL_COMMAND_LINE_SIZE 150gpointer berylThread(gpointer d){ gint ex=0; gchar beryl_command[BERYL_COMMAND_LINE_SIZE]; if (XGL) g_strlcpy(beryl_command, "beryl-xgl", BERYL_COMMAND_LINE_SIZE); else g_strlcpy(beryl_command, "beryl", BERYL_COMMAND_LINE_SIZE); switch (renderPath) { case TFPRenderPath: g_strlcat(beryl_command, " --use-tfp", BERYL_COMMAND_LINE_SIZE);break; case CopyRenderPath: g_strlcat(beryl_command, " --use-copy", BERYL_COMMAND_LINE_SIZE);break; } switch (renderingMode) { case IndirectRendering: g_strlcat(beryl_command, " --indirect-rendering", BERYL_COMMAND_LINE_SIZE);break; case XGLRendering: g_strlcat(beryl_command, " --xgl-rendering", BERYL_COMMAND_LINE_SIZE);break; } switch (cowMode) { case UseCOW: g_strlcat(beryl_command, " --use-cow", BERYL_COMMAND_LINE_SIZE);break; case NoCOW: g_strlcat(beryl_command, " --no-cow", BERYL_COMMAND_LINE_SIZE);break; } switch (platformMode) { case AIGLXPlatform: g_strlcat(beryl_command, " --force-aiglx", BERYL_COMMAND_LINE_SIZE);break; case NvidiaPlatform: g_strlcat(beryl_command, " --force-nvidia", BERYL_COMMAND_LINE_SIZE);break; case XGLPlatform: g_strlcat(beryl_command, " --force-xgl", BERYL_COMMAND_LINE_SIZE);break; } switch (bindingMode) { case StrictBinding: g_strlcat(beryl_command, " --strict-binding", BERYL_COMMAND_LINE_SIZE);break; case XGLBinding: g_strlcat(beryl_command, " --xgl-binding", BERYL_COMMAND_LINE_SIZE);break; }void loadProfile (gint profileNumber){ profilefile=g_strconcat(g_get_home_dir(),"/",profiles[profileNumber],NULL); gchar *settingsfile=g_strconcat(g_get_home_dir(),"/.beryl/settings",NULL); gchar *touchprofile=g_strconcat("touch ", profilefile,NULL); gchar *linkprofile=g_strconcat("ln -fs ", profilefile," ",settingsfile,NULL); gchar *touchfnprofile=g_strconcat("touch ", fnprofile,NULL); g_spawn_command_line_sync(touchfnprofile,NULL,NULL,NULL,NULL); g_spawn_command_line_sync(touchprofile,NULL,NULL,NULL,NULL); g_spawn_command_line_sync(linkprofile,NULL,NULL,NULL,NULL); g_free(settingsfile); reloadsig();} switch (ProfileMode) { case Profile1: loadProfile(1);break; case Profile2: loadProfile(2);break;;break; case Profile3: loadProfile(3);break;;break; case Profile4: loadProfile(4);break;;break; case Profile5: loadProfile(5);break;;break; } if (noGLYield) g_strlcat(beryl_command, " --skip-gl-yield", BERYL_COMMAND_LINE_SIZE); berylLaunched=TRUE; while(berylLaunched) { killWM(); if (!g_spawn_command_line_sync(beryl_command,NULL,NULL,&ex,NULL)) { if (XGL) manager_error(_("can't execute beryl-xgl")); else manager_error(_("can't execute beryl")); } if (reloadingBeryl) { reloadingBeryl=FALSE; return NULL; } else if (WIFEXITED(ex)) // returned something { if (WEXITSTATUS(ex)) // returned something other than 0 { berylLaunched=FALSE; } } else if (WIFSIGNALED(ex)) // killed by a signal { if (!berylSignalled(WTERMSIG(ex))) { berylLaunched=FALSE; } } } //if this thread exits, and WM is still beryl, fall back into the fall back WM if (WM==0 && useFB) { WM=fallBackWM+1; gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(WMs[WM].Item),TRUE); //gtk_widget_set_sensitive(useFBItem,FALSE); gtk_widget_set_sensitive(DMSubItem,FALSE); gtk_widget_set_sensitive(reloadDecoratorItem,FALSE); //gtk_widget_set_sensitive(FBSubItem,FALSE); //for(ex=1;ex<numWM;ex++) //{ // gtk_widget_set_sensitive(WMs[ex].FBItem,FALSE); //} for(ex=0;ex<numDM;ex++) { gtk_widget_set_sensitive(DMs[ex].Item,FALSE); } launchWM(); } return NULL;}void reloadBeryl(){ if (berylLaunched) reloadingBeryl=TRUE; g_thread_create(berylThread,NULL,FALSE,NULL); // launch beryl if (!decoratorLaunched && !is_decor_running()) g_thread_create(decorThread,NULL,FALSE,NULL); // launch decorator}void startBeryl(){ if (!berylLaunched) g_thread_create(berylThread,NULL,FALSE,NULL); // launch beryl if (!decoratorLaunched && !is_decor_running()) g_thread_create(decorThread,NULL,FALSE,NULL); // launch decorator}void reloadDecorator(GtkWidget * w, gpointer p){ if (decoratorLaunched) reloadingDecorator=TRUE; g_thread_create(decorThread,NULL,FALSE,NULL); // launch decorator}void launchWM(){ save_settings(); if (WM==0) startBeryl(); else startWM();}void reloadWM(GtkWidget * w, gpointer p){ if (WM==0) reloadBeryl(); else startWM();}void setWM(GtkWidget * w, gpointer p){ gint i = GPOINTER_TO_INT(p); if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { gint j; if (i!=WM) { WM=i; launchWM(); } //gtk_widget_set_sensitive(useFBItem,i==0); gtk_widget_set_sensitive(reloadDecoratorItem,i<3); //gtk_widget_set_sensitive(FBSubItem,i==0 && useFB); gtk_widget_set_sensitive(DMSubItem,i<3); for(j=0;j<numDM;j++) { gtk_widget_set_sensitive(DMs[j].Item,i<3); } //for (j=1;j<numWM;j++) //{ // gtk_widget_set_sensitive(WMs[j].FBItem,i==0 && useFB); //} save_settings(); }}void setFallbackWM(GtkWidget * w, gpointer p){ gint i = GPOINTER_TO_INT(p); if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { fallBackWM=i; save_settings(); }}void toggleRenderingPath(GtkWidget *w, gpointer p){ RenderPathMode rPath = GPOINTER_TO_INT(p); if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { renderPath = rPath; save_settings(); reloadWM(w,p); }}void toggleCOW(GtkWidget *w, gpointer p){ COWMode cow = GPOINTER_TO_INT(p); if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { cowMode = cow; save_settings(); reloadWM(w,p); }}void togglePlatform(GtkWidget *w, gpointer p){ PlatformMode platform = GPOINTER_TO_INT(p); if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { platformMode = platform; save_settings(); reloadWM(w,p); }}void toggleBinding(GtkWidget *w, gpointer p){ BindingMode binding = GPOINTER_TO_INT(p); if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { bindingMode = binding; save_settings(); reloadWM(w,p); }}void toggleRendering(GtkWidget *w, gpointer p){ RenderingMode rendering = GPOINTER_TO_INT(p); if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { renderingMode = rendering; save_settings(); reloadWM(w,p); }}void toggleFB(GtkWidget * w, gpointer p){ gint i; useFB=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)); gtk_widget_set_sensitive(FBSubItem,useFB); for (i=1;i<numWM;i++) gtk_widget_set_sensitive(WMs[i].FBItem,useFB); save_settings();}void setDM(GtkWidget * w, gpointer p){ gint i = GPOINTER_TO_INT(p); if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))) { DM=i; save_settings(); reloadDecorator(w,p); }}GtkWidget * make_image(gchar * path){ GdkPixbuf * p; gint w,h; gtk_icon_size_lookup(GTK_ICON_SIZE_MENU,&w,&h); p = gdk_pixbuf_new_from_file_at_size(path,w,h,NULL); if (!p) return gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU); else return gtk_image_new_from_pixbuf(p);}void quitMe(GtkWidget * w, gpointer p){ gtk_main_quit();}gboolean is_wm_running(gint wm){ const gchar * nam; if (wm>0) { nam=WMs[wm].Grep; return is_running(nam); } else { return is_running("beryl") || is_running("beryl-xgl") || is_running("compiz"); }}gboolean detect_app(const gchar * app){ gint ex; gchar *f = g_strdup_printf("sh -c 'which %s > /dev/null 2>&1'",app); if (!g_spawn_command_line_sync(f,NULL,NULL,&ex,NULL)) manager_error(_("can't use this app, no which")); g_free(f); if (WIFEXITED(ex)) { if (WEXITSTATUS(ex)==0) return TRUE; } else manager_error(_("something went wrong with which")); return FALSE;}gboolean detect_wm(gint wm){ if (!XGL || !WMs[wm].xXGL) { if (detect_app(WMs[wm].Prog)) return TRUE; } if (wm == WM) WM=-1; if (wm == fallBackWM+1) fallBackWM=-1; return FALSE;}gboolean detect_dm(gint dm){ if (detect_app(DMs[dm].Prog)) return TRUE; if (dm == DM) DM=-1; return FALSE;}void setGLYield(GtkWidget * w, gpointer p){ noGLYield=gtk_check_menu_item_get_active( GTK_CHECK_MENU_ITEM(w)); save_settings(); if (WM==0) reloadBeryl();}GtkWidget* add_menu_group_item(GtkWidget *menu, GSList **group, const gchar *name, gboolean show, gboolean check, GCallback callback, gpointer data){ GtkWidget *mitem; mitem = gtk_radio_menu_item_new_with_label(*group, name); *group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem)); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), check); if (show) gtk_widget_show(mitem); else gtk_widget_hide(mitem); g_signal_connect(mitem, "toggled", callback, data); return mitem;}void init_menu(){ GtkWidget * submenu; GtkWidget * mitem; GtkWidget * smshell; GSList * renderPathGroup = NULL; GSList * cowGroup = NULL; GSList * platformGroup = NULL; GSList * bindingGroup = NULL; GSList * renderingGroup = NULL; GSList * wms = NULL; GSList * fbk = NULL; GSList * dms = NULL; gint i; menu = gtk_menu_new(); g_object_ref(menu); mitem = gtk_image_menu_item_new_with_label(_("Beryl Settings Manager")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem), make_image(PIXMAPS_DIR "/beryl-settings.svg")); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); g_signal_connect(mitem,"activate",G_CALLBACK(startApp),"beryl-settings"); mitem = gtk_image_menu_item_new_with_label(_("Emerald Theme Manager")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem), make_image(PIXMAPS_DIR "/emerald-theme-manager-icon.png")); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); g_signal_connect(mitem,"activate",G_CALLBACK(startApp),"emerald-theme-manager"); mitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); mitem = gtk_image_menu_item_new_with_label(_("Reload Window Manager")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem), gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU)); g_signal_connect(mitem,"activate",G_CALLBACK(reloadWM),NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); mitem = gtk_image_menu_item_new_with_label(_("Select Window Manager")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem), make_image(PIXMAPS_DIR "/wm-select.png")); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); smshell=gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); for (i=0;i<numWM;i++) { mitem = add_menu_group_item(smshell, &wms, gettext(WMs[i].Name), ((i==0) || detect_wm(i)), (i==WM), G_CALLBACK(setWM), GINT_TO_POINTER(i)); WMs[i].Item=mitem; } mitem = gtk_image_menu_item_new_with_label(_("Advanced Beryl options")); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); submenu=gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),submenu); mitem = gtk_image_menu_item_new_with_label(_("Rendering path")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu),mitem); gtk_widget_show(mitem); smshell = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); add_menu_group_item(smshell, &renderPathGroup, _("Automatic"), TRUE, (renderPath == AutoRenderPath), G_CALLBACK(toggleRenderingPath), GINT_TO_POINTER(AutoRenderPath)); add_menu_group_item(smshell, &renderPathGroup, _("Texture From Pixmap"), TRUE, (renderPath == TFPRenderPath), G_CALLBACK(toggleRenderingPath), GINT_TO_POINTER(TFPRenderPath)); add_menu_group_item(smshell, &renderPathGroup, _("Copy"), TRUE, (renderPath == CopyRenderPath), G_CALLBACK(toggleRenderingPath), GINT_TO_POINTER(CopyRenderPath)); mitem = gtk_image_menu_item_new_with_label(_("Composite Overlay Window")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu),mitem); gtk_widget_show(mitem); smshell = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); add_menu_group_item(smshell, &cowGroup, _("Automatic"), TRUE, (cowMode == AutoCOW), G_CALLBACK(toggleCOW), GINT_TO_POINTER(AutoCOW)); add_menu_group_item(smshell, &cowGroup, _("Use COW"), TRUE, (cowMode == UseCOW), G_CALLBACK(toggleCOW), GINT_TO_POINTER(UseCOW)); add_menu_group_item(smshell, &cowGroup, _("Don't use COW"), TRUE, (cowMode == NoCOW), G_CALLBACK(toggleCOW), GINT_TO_POINTER(NoCOW)); mitem = gtk_image_menu_item_new_with_label(_("Rendering platform")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu),mitem); gtk_widget_show(mitem); smshell = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); add_menu_group_item(smshell, &platformGroup, _("Automatic"), TRUE, (platformMode == AutoPlatform), G_CALLBACK(togglePlatform), GINT_TO_POINTER(AutoPlatform)); add_menu_group_item(smshell, &platformGroup, _("Force Nvidia"), TRUE, (platformMode == NvidiaPlatform), G_CALLBACK(togglePlatform), GINT_TO_POINTER(NvidiaPlatform)); add_menu_group_item(smshell, &platformGroup, _("Force AIGLX"), TRUE, (platformMode == AIGLXPlatform), G_CALLBACK(togglePlatform), GINT_TO_POINTER(AIGLXPlatform)); add_menu_group_item(smshell, &platformGroup, _("Force XGL"), TRUE, (platformMode == XGLPlatform), G_CALLBACK(togglePlatform), GINT_TO_POINTER(XGLPlatform)); mitem = gtk_image_menu_item_new_with_label(_("Binding")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu),mitem); gtk_widget_show(mitem); smshell = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); add_menu_group_item(smshell, &bindingGroup, _("Automatic"), TRUE, (bindingMode == AutoBinding), G_CALLBACK(toggleBinding), GINT_TO_POINTER(AutoBinding)); add_menu_group_item(smshell, &bindingGroup, _("Strict Binding"), TRUE, (bindingMode == StrictBinding), G_CALLBACK(toggleBinding), GINT_TO_POINTER(StrictBinding)); add_menu_group_item(smshell, &bindingGroup, _("XGL Binding"), TRUE, (bindingMode == XGLBinding), G_CALLBACK(toggleBinding), GINT_TO_POINTER(XGLBinding)); mitem = gtk_image_menu_item_new_with_label(_("Rendering")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu),mitem); gtk_widget_show(mitem); smshell = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); add_menu_group_item(smshell, &renderingGroup, _("Automatic"), TRUE, (renderingMode == AutoRendering), G_CALLBACK(toggleRendering), GINT_TO_POINTER(AutoRendering)); add_menu_group_item(smshell, &renderingGroup, _("Indirect Rendering"), TRUE, (renderingMode == IndirectRendering), G_CALLBACK(toggleRendering), GINT_TO_POINTER(IndirectRendering)); add_menu_group_item(smshell, &renderingGroup, _("XGL Rendering"), TRUE, (renderingMode == XGLRendering), G_CALLBACK(toggleRendering), GINT_TO_POINTER(XGLRendering)); if (!XGL && NV9XXX) { mitem = gtk_check_menu_item_new_with_label(_( "Disable GL Yield setting\n" "Use this to fix some redraw bugs")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu),mitem); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(mitem),noGLYield); gtk_widget_show(mitem); g_signal_connect(mitem,"toggled",G_CALLBACK(setGLYield),NULL); } mitem = gtk_image_menu_item_new_with_label(_("Beryl Profiles")); gtk_menu_shell_append(GTK_MENU_SHELL(submenu),mitem); gtk_widget_show(mitem); smshell = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); add_menu_group_item(smshell, &profileGroup, _("Profile 1"), TRUE, (renderingMode == AutoRendering), G_CALLBACK(toggleRendering), GINT_TO_POINTER(AutoRendering)); mitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); mitem = gtk_image_menu_item_new_with_label(_("Reload Window Decorator")); reloadDecoratorItem = mitem; gtk_widget_set_sensitive(reloadDecoratorItem,WM<3); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem), gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU)); g_signal_connect(mitem,"activate",G_CALLBACK(reloadDecorator),NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); mitem = gtk_image_menu_item_new_with_label(_("Select Window Decorator")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem), make_image(PIXMAPS_DIR "/wd-select.png")); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); smshell=gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); DMSubItem=mitem; gtk_widget_set_sensitive(GTK_WIDGET(DMSubItem),WM<3); for (i=0;i<numDM;i++) { mitem = gtk_radio_menu_item_new_with_label(dms,gettext(DMs[i].Name)); dms=gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem)); if (i==DM) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem),TRUE); gtk_menu_shell_append(GTK_MENU_SHELL(smshell),mitem); if (detect_dm(i)) gtk_widget_show(mitem); else gtk_widget_hide(mitem); g_signal_connect(mitem,"toggled",G_CALLBACK(setDM),GINT_TO_POINTER(i)); DMs[i].Item=mitem; } mitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); mitem = gtk_check_menu_item_new_with_label(_("Launch Fall-back Window\nManager if beryl crashes")); useFBItem = mitem; gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem),useFB); g_signal_connect(mitem,"toggled",G_CALLBACK(toggleFB),NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); mitem = gtk_image_menu_item_new_with_label(_("Select Fall-back Window Manager")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mitem), make_image(PIXMAPS_DIR "/fall-back-wm-select.png")); FBSubItem=mitem; gtk_widget_set_sensitive(FBSubItem,useFB); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); smshell=gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem),smshell); for (i=3;i<numWM;i++) { mitem = gtk_radio_menu_item_new_with_label(fbk,gettext(WMs[i].Name)); fbk=gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(mitem)); if ((i-3)==fallBackWM) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem),TRUE); gtk_widget_set_sensitive(mitem,useFB); gtk_menu_shell_append(GTK_MENU_SHELL(smshell),mitem); if (detect_wm(i)) gtk_widget_show(mitem); else gtk_widget_hide(mitem); WMs[i].FBItem=mitem; g_signal_connect(mitem,"toggled",G_CALLBACK(setFallbackWM),GINT_TO_POINTER(i-3)); } mitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem); mitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,NULL); g_signal_connect(mitem,"activate",G_CALLBACK(quitMe),NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu),mitem); gtk_widget_show(mitem);}void init_widgets(){ GtkWidget * icon; GtkWidget * evbox; GdkPixbuf * pbuf; tips = gtk_tooltips_new(); mainIcon = egg_tray_icon_new(_("Beryl Manager")); evbox = gtk_event_box_new(); gtk_event_box_set_visible_window(GTK_EVENT_BOX(evbox),FALSE); gtk_tooltips_set_tip(tips,evbox,_("Beryl Manager"),_("Manage various things related to Beryl")); pbuf = gdk_pixbuf_new_from_file_at_size(DATADIR "/icons/hicolor/scalable/apps/beryl-manager.svg",iconsize,iconsize,NULL); if (!pbuf) pbuf = gdk_pixbuf_new_from_file(DATADIR "/icons/hicolor/24x24/apps/beryl-manager.png",NULL); if (!pbuf) pbuf = gdk_pixbuf_new_from_file(PIXMAPS_DIR "/beryl-manager.png",NULL); if (!pbuf) icon = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE,GTK_ICON_SIZE_SMALL_TOOLBAR); else { g_object_ref(G_OBJECT(pbuf)); icon = gtk_image_new_from_pixbuf(pbuf); } gtk_container_add(GTK_CONTAINER(mainIcon),evbox); gtk_container_add(GTK_CONTAINER(evbox),icon); g_signal_connect(evbox,"button-release-event",G_CALLBACK(buttonUp),NULL); g_signal_connect(evbox,"enter-notify-event",G_CALLBACK(enterNotify),NULL); g_signal_connect(evbox,"leave-notify-event",G_CALLBACK(leaveNotify),NULL); g_signal_connect(evbox,"destroy",G_CALLBACK(destroyNotify),NULL); g_signal_connect(mainIcon,"client-event",G_CALLBACK(popupClient),NULL); gtk_widget_show_all(GTK_WIDGET(mainIcon));}void detect_nvidia(){ //find out if we have XGL gint ex=0; if (!g_spawn_command_line_sync("sh -c 'glxinfo | grep -i NVIDIA > /dev/null'", NULL,NULL,&ex,NULL)) manager_error(_("can't use this app, no glxinfo or no grep")); if (WIFEXITED(ex)) { if (WEXITSTATUS(ex)==0) NV9XXX=TRUE; else NV9XXX=FALSE; } else manager_error(_("something went wrong with glxinfo or grep"));}void detect_xgl(){ //find out if we have XGL gint ex=0; if (!g_spawn_command_line_sync("sh -c 'xvinfo | grep -i Xgl > /dev/null'", NULL,NULL,&ex,NULL)) manager_error(_("can't use this app, no xvinfo or no grep")); if (WIFEXITED(ex)) { if (WEXITSTATUS(ex)==0) XGL=TRUE; else XGL=FALSE; } else manager_error(_("something went wrong with xvinfo or grep"));}int main(int argc, char ** argv){ gint i, found; gchar *buffer; gboolean daemon_mode = TRUE; Display * d; gboolean force_window_manager = TRUE; gboolean force_decorator = TRUE; Window running_window; //Intialise error handler g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING | G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL, beryl_manager_log_handler, NULL); //set the locale stuff setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); //parse command line arguments for (i=1;i<argc;i++) { if (strcmp(argv[i],"--help")==0) { usage(argv[0]); return 0; } else if (strcmp(argv[i],"--version")==0) { printf (PACKAGE_STRING "\n"); return 0; } else if (strcmp(argv[i],"-d")==0) { daemon_mode = FALSE; } else if (strcmp(argv[i],"--no-force-window-manager")==0) { force_window_manager = FALSE; } else if (strcmp(argv[i],"--no-force-decorator")==0) { force_decorator = FALSE; } else { usage(argv[0]); return 1; } } //detach from console or not if (daemon_mode) { daemon(1,1); close(0); } if (!XInitThreads()) { g_warning(_("Can't init XLib thread support")); return 3; } d = XOpenDisplay(NULL); if ((running_window = Window_With_Name(d, DefaultRootWindow(d), // GDK_WINDOW_XID( // gdk_get_default_root_window() // ), "Beryl Manager"))) // "Event Tester"))) { XEvent clientEvent; gboolean missed = FALSE; PopupRunning = XInternAtom(d,"beryl-manager-Popup",0); clientEvent.xclient.type = ClientMessage; clientEvent.xclient.window = running_window; clientEvent.xclient.message_type = PopupRunning; clientEvent.xclient.format = 32; clientEvent.xclient.display = d; clientEvent.xclient.data.l[0] = 0; clientEvent.xclient.data.l[1] = 0; clientEvent.xclient.data.l[2] = 0; clientEvent.xclient.data.l[3] = 0; clientEvent.xclient.data.l[4] = 0; // gdk_error_trap_push (); missed = XSendEvent(d,running_window, False, NoEventMask, &clientEvent); XSync (d, False); // gdk_error_trap_pop (); return 0; } XCloseDisplay(d); // Some warning about changed behaviour for the unaware user /* if (!force_window_manager && !force_decorator) { if (!strcmp (PACKAGE_VERSION, "0.1.1")) { fprintf(stderr, "beryl-manager doesn't autostart window-manager/decorator\n" "any more. Please consult: man beryl-manager\n\n"); } } */ //taken out because starting beryl is -the- reason for beryl-manager's existence. gtk_init(&argc,&argv); d = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); buffer = g_strdup(DisplayString(gdk_x11_display_get_xdisplay(gdk_display_get_default()))); if (buffer) { displayname = display_part(buffer); g_free(buffer); } if (!g_thread_supported()) g_thread_init(NULL); gdk_threads_init (); gdk_threads_enter (); mutx=g_mutex_new(); // Check for the windows manager buffer = g_strconcat("WM_S",displayname,NULL); wmAtom = XInternAtom(d,buffer,0); g_free (buffer); detect_xgl(); if (!XGL) detect_nvidia(); load_settings(); init_widgets(); init_menu(); if (WM<0 || WM>=(numWM)) WM=-1; if (WM==-1) { //set WM to beryl for now gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(WMs[0].Item),TRUE); } if (fallBackWM<0 || fallBackWM > (numWM-1)) fallBackWM=-1; if (fallBackWM==-1) { //we have to find a fall back WM that exists gint i; for (i=1;i<numWM;i++) { if (detect_wm(i)) { gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(WMs[i].FBItem),TRUE); fallBackWM=i-3; break; } } } if (fallBackWM==-1) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(useFBItem),FALSE); if (DM<0 || DM >= numDM) DM=-1; if (DM==-1) { //we have to find a DM that exists gint i; for (i=0;i<numDM;i++) { if (detect_dm(i)) { gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(DMs[i].Item),TRUE); DM=i; break; } } } if (DM==-1) manager_error("No Display Manager Found!"); save_settings(); found = False; for (i=0;i<numDM && !found;i++) { if (is_running(DMs[i].Prog)) found = True; } if (!found || (force_decorator && !is_decor_running())) { g_thread_create(decorThread,NULL,FALSE,NULL); // launch decorator } if (!force_window_manager) { found = False; for (i=0;i<numWM && !found;i++) if (is_wm_running(i)) found = True; if (!found) launchWM(); } else if (!is_wm_running(WM)) { launchWM(); } signal (SIGUSR1, signalHandler); signal (SIGUSR2, signalHandler); gtk_main(); gdk_threads_leave (); g_free(displayname); return 0;}/* - - - - - - - - -* [These functions are from the file "dsimple.c" used with xwininfo.]** Written by Mark Lillibridge. Last updated 7/1/87*** Window_With_Name: routine to locate a window with a given name on a display.* If no window with the given name is found, 0 is returned.* If more than one window has the given name, the first* one found will be returned. Only top and its subwindows* are looked at. Normally, top should be the Root Window.*/static WindowWindow_With_Name (Display * dpy, Window top, char *name){ Window *children, dummy; unsigned int nchildren; unsigned i; Window w = 0; char *window_name; if (XFetchName (dpy, top, &window_name) && !strcmp (window_name, name)) { XFree(window_name); return (top); } XFree(window_name); if (!XQueryTree (dpy, top, &dummy, &dummy, &children, &nchildren)) return (0); for (i = 0; i < nchildren; i++) { w = Window_With_Name (dpy, children[i], name); if (w) break; } if (children) XFree ((char *) children); return (w);}