summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-13 03:34:10 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-13 03:34:10 +0000
commit6a8e496233a6f6d632bdc7551a5fbda3543c27bb (patch)
tree28479fd17cf5a19838108ab4a17b6f3fb1e5cd88
downloadfusion-icon-6a8e4962.tar.gz
fusion-icon-6a8e4962.zip
Added KDE3 version of fusion-icon for Compiz
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/fusion-icon@1102634 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
-rw-r--r--COPYING340
-rw-r--r--FusionIcon/__init__.py1
-rw-r--r--FusionIcon/data.py116
-rw-r--r--FusionIcon/environment.py146
-rw-r--r--FusionIcon/execute.py58
-rw-r--r--FusionIcon/interface.py89
-rw-r--r--FusionIcon/interface_gtk/__init__.py3
-rw-r--r--FusionIcon/interface_gtk/main.py214
-rw-r--r--FusionIcon/interface_qt4/__init__.py3
-rw-r--r--FusionIcon/interface_qt4/main.py80
-rw-r--r--FusionIcon/parser.py57
-rw-r--r--FusionIcon/start.py68
-rw-r--r--FusionIcon/util.py419
-rw-r--r--Makefile16
-rw-r--r--PKG-INFO10
-rw-r--r--VERSION1
-rwxr-xr-xfusion-icon61
-rw-r--r--fusion-icon.desktop11
-rw-r--r--images/22x22/fusion-icon.pngbin0 -> 1095 bytes
-rw-r--r--images/24x24/fusion-icon.pngbin0 -> 1818 bytes
-rw-r--r--images/32x32/fusion-icon.pngbin0 -> 1612 bytes
-rw-r--r--images/48x48/fusion-icon.pngbin0 -> 2458 bytes
-rw-r--r--images/scalable/fusion-icon.svg561
-rw-r--r--setup.py118
24 files changed, 2372 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..623b625
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/FusionIcon/__init__.py b/FusionIcon/__init__.py
new file mode 100644
index 0000000..f685b36
--- /dev/null
+++ b/FusionIcon/__init__.py
@@ -0,0 +1 @@
+# Fusion Icon
diff --git a/FusionIcon/data.py b/FusionIcon/data.py
new file mode 100644
index 0000000..639b46c
--- /dev/null
+++ b/FusionIcon/data.py
@@ -0,0 +1,116 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Publaic License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): crdlb
+# Copyright 2007 Christopher Williams <christopherw@verizon.net>
+
+import os
+
+mesa_libgl_locations = (
+ # ubuntu
+ '/usr/lib/fglrx/libGL.so.1.2.xlibmesa',
+ '/usr/lib/nvidia/libGL.so.1.2.xlibmesa',
+ # gentoo
+ '/usr/lib/opengl/xorg-x11/lib/libGL.so.1.2',
+ # archlinux
+ '/opt/mesa-xgl/lib/libGL.so.1.2',
+ '/lib/mesa/libGL.so.1.2',
+ # debian
+ '/usr/lib/fglrx/diversions/libGL.so.1.2',
+ '/usr/share/nvidia-glx/diversions/libGL.so.1.2',
+)
+
+compiz_args = ['--replace', '--sm-disable', '--ignore-desktop-hints', 'ccp']
+
+config_home = os.environ.get('XDG_CONFIG_HOME',
+ os.path.join(os.environ['HOME'], '.config'))
+
+config_folder = os.path.join(config_home, 'compiz')
+
+config_file = os.path.join(config_folder, 'fusion-icon')
+
+# Key:
+# identifier (for wms, this is what gets written to the config file)
+# Value:
+# O - base command (for wms and decorators), config file option name
+# 1 - full command, actual compiz argument
+# 2 - display name
+# 3 - desktop environment for which it should be the fallback/default
+# 4 - list of extra properties:
+# noreplace: lacks working --replace switch
+# 5 - Extra command to run before killing
+
+apps = {
+ 'ccsm':
+ ('ccsm', ['ccsm'],
+ 'Settings Manager'),
+ 'emerald theme manager':
+ ('emerald-theme-manager', ['emerald-theme-manager'],
+ 'Emerald Theme Manager'),
+}
+
+wms = {
+ 'metacity':
+ ('metacity', ['metacity', '--replace'],
+ 'Metacity', 'gnome', None, None,),
+
+ 'kwin':
+ ('kwin', ['kwin', '--replace'],
+ 'KWin', 'kde', None, ['dcop', 'kwin', 'KWinInterface', 'stopKompmgr']),
+
+ 'xfwm4':
+ ('xfwm4', ['xfwm4'],
+ 'Xfwm4', 'xfce', ['noreplace'], ['killall', 'xfwm4']),
+
+ 'openbox':
+ ('openbox', ['openbox', '--replace'],
+ 'Openbox', None, None, None),
+
+ 'blackbox':
+ ('blackbox', ['blackbox', '--replace'],
+ 'Blackbox', None, None, None),
+
+ 'fvwm':
+ ('fvwm', ['fvwm', '--replace'],
+ 'FVWM', None, None, None),
+
+ 'icewm':
+ ('icewm', ['icewm', '--replace'],
+ 'IceWM', None, None, None),
+
+}
+
+decorators = {
+ 'emerald':
+ ('emerald', 'emerald --replace',
+ 'Emerald', None),
+
+ 'gwd':
+ ('gtk-window-decorator', 'gtk-window-decorator --replace',
+ 'GTK Window Decorator', 'gnome'),
+
+ 'kwd':
+ ('kde-window-decorator', 'kde-window-decorator --replace',
+ 'KDE Window Decorator', 'kde'),
+}
+
+options = {
+ 'indirect rendering':
+ (None, '--indirect-rendering', 'Indirect Rendering'),
+
+ 'loose binding':
+ (None, '--loose-binding', 'Loose Binding'),
+}
+
diff --git a/FusionIcon/environment.py b/FusionIcon/environment.py
new file mode 100644
index 0000000..9423098
--- /dev/null
+++ b/FusionIcon/environment.py
@@ -0,0 +1,146 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): crdlb, nesl247
+#
+# Copyright 2007 Christopher Williams <christopherw@verizon.net>
+
+import os
+from execute import run
+
+tfp = 'GLX_EXT_texture_from_pixmap'
+GDSID = 'GNOME_DESKTOP_SESSION_ID'
+
+class Environment:
+
+ '''Detects properties of the enviroment, and provides a set() method that uses this information to export environment variables needed to start compiz.'''
+
+
+ def __init__(self):
+
+ '''desktop: current desktop enviroment used to choose interface, fallback wm, and default decorator
+
+failsafe: boolean, True if in a failsafe session, currently only supports gnome failsafe mode.
+
+glxinfo: output of glxinfo command
+
+indirect_glxinfo: output of glxinfo with LIBGL_ALWAYS_INDIRECT
+
+xvinfo: output of xvinfo
+
+glx_vendor: 'client glx vendor:' usually one of SGI (for mesa-based drivers), NVIDIA Corporation, or ATI.
+
+tfp: 'direct' if texture_from_pixmap is present with direct rendering (implying presence with indirect as well), 'indirect' if only present with indirect context, False if not present at all
+
+Xgl: True in Xgl'''
+
+ # Check gnome- and kde-specific vars, then try generic 'DESKTOP_SESSION'
+ if GDSID in os.environ:
+ self.desktop = 'gnome'
+
+ elif 'KDE_FULL_SESSION' in os.environ:
+ self.desktop = 'kde'
+
+ else:
+ self.desktop = os.environ.get('DESKTOP_SESSION', 'unknown')
+
+ self.failsafe = False
+ if self.desktop == 'gnome' and GDSID in os.environ and os.environ[GDSID] == 'failsafe':
+ self.failsafe = True
+
+ if self.failsafe:
+ failsafe_str = 'failsafe '
+ else:
+ failsafe_str = ''
+
+ print ' * Detected Session: %s%s' %(failsafe_str, self.desktop)
+
+
+ ## Save the output of glxinfo and xvinfo for later use:
+
+ # don't try to run glxinfo unless it's installed
+ if run(['which', 'glxinfo'], 'call', quiet=True) == 0:
+ self.glxinfo = run('glxinfo', 'output')
+ else:
+ raise SystemExit, ' * Error: glxinfo not installed!'
+
+ # make a temp environment
+ indirect_environ = os.environ.copy()
+ indirect_environ['LIBGL_ALWAYS_INDIRECT'] = '1'
+ self.indirect_glxinfo = run('glxinfo', 'output', env=indirect_environ)
+
+ if run(['which', 'xvinfo'], 'call', quiet=True) == 0:
+ self.xvinfo = run('xvinfo', 'output')
+ else:
+ raise SystemExit, ' * Error: xvinfo not installed!'
+
+ line = [l for l in self.glxinfo.splitlines() if 'client glx vendor string:' in l]
+ if line:
+ self.glx_vendor = ' '.join(line[0].split()[4:])
+ else:
+ self.glx_vendor = ''
+
+ ## Texture From Pixmap / Indirect
+ self.tfp = False
+ if self.glxinfo.count(tfp) < 3:
+ if self.indirect_glxinfo.count(tfp) == 3:
+ self.tfp = 'indirect'
+ else:
+ self.tfp = 'direct'
+
+ ## Xgl
+ if 'Xgl' in self.xvinfo:
+ self.Xgl = True
+
+ else:
+ self.Xgl = False
+
+ def set(self):
+
+ '''Trigger all environment checks'''
+
+ # Check for Intel and export INTEL_BATCH
+ if 'Intel' in self.glxinfo:
+ print ' * Intel detected, exporting: INTEL_BATCH=1'
+ os.environ['INTEL_BATCH'] = '1'
+
+ # Check TFP and export LIBGL_ALWAYS_INDIRECT if needed
+ if self.tfp != 'direct':
+ print ' * No %s with direct rendering context' %tfp
+ if self.tfp == 'indirect':
+ print ' ... present with indirect rendering, exporting: LIBGL_ALWAYS_INDIRECT=1'
+ os.environ['LIBGL_ALWAYS_INDIRECT'] = '1'
+ else:
+ print ' ... nor with indirect rendering, this isn\'t going to work!'
+
+ # If using Xgl with a proprietary driver, exports LD_PRELOAD=<mesa libGL>
+ if self.Xgl and self.glx_vendor != 'SGI':
+ print ' * Non-mesa driver on Xgl detected'
+ from data import mesa_libgl_locations
+ location = [l for l in mesa_libgl_locations if os.path.exists(l)]
+ if location:
+ print ' ... exporting: LD_PRELOAD=%s' %location[0]
+ os.environ['LD_PRELOAD'] = location[0]
+ else:
+ # kindly let the user know... but don't abort (maybe it will work :> )
+ print ' ... no mesa libGL found for preloading, this may not work!'
+
+ # Check for nvidia on Xorg
+ if not self.Xgl and self.glx_vendor == 'NVIDIA Corporation':
+ print ' * NVIDIA on Xorg detected, exporting: __GL_YIELD=NOTHING'
+ os.environ['__GL_YIELD'] = 'NOTHING'
+
+env = Environment()
+
diff --git a/FusionIcon/execute.py b/FusionIcon/execute.py
new file mode 100644
index 0000000..5615cd1
--- /dev/null
+++ b/FusionIcon/execute.py
@@ -0,0 +1,58 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): crdlb, nesl247
+#
+# Copyright 2007 Christopher Williams <christopherw@verizon.net>
+
+import subprocess, signal, os
+
+# avoid zombies
+signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+
+def run(command, mode='spawn', quiet=False, env=None):
+ 'Simple wrapper for the subprocess module. Supported modes: spawn, call, and output'
+
+ if mode == 'spawn':
+ if not quiet:
+ popen_object = subprocess.Popen(command)
+ else:
+ popen_object = subprocess.Popen(command, stdout=open(os.devnull, 'w'))
+
+ return popen_object
+
+ elif mode == 'call':
+ # restore normal child handling
+ signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+ if not quiet:
+ exitcode = subprocess.call(command, stderr=subprocess.PIPE)
+ else:
+ exitcode = subprocess.call(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ # turn zombie protection back on
+ signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+
+ return exitcode
+
+ elif mode == 'output':
+ signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+ if not env:
+ output = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=open(os.devnull, 'w')).communicate()[0]
+ else:
+ output = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=open(os.devnull, 'w'), env=env).communicate()[0]
+
+ signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+
+ return output
diff --git a/FusionIcon/interface.py b/FusionIcon/interface.py
new file mode 100644
index 0000000..450a7f9
--- /dev/null
+++ b/FusionIcon/interface.py
@@ -0,0 +1,89 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): crdlb, nesl247
+#
+# Copyright 2007 Christopher Williams <christopherw@verizon.net>
+
+import sys
+from util import env
+import start
+
+interfaces={
+ 'gtk': 'GTK',
+ 'qt4': 'Qt4',
+ 'qt3': 'Qt3',
+}
+
+def import_interface(interface):
+ try:
+ if interface in interfaces:
+ print ' * Using the', interfaces[interface], 'Interface'
+ __import__('FusionIcon.interface_%s' %interface)
+
+ else:
+ print ' *** Error: "%s" interface is invalid, this should not happen' %interface
+ raise SystemExit
+
+ except ImportError, e:
+ if [i for i in interfaces if 'interface_%s' %i in str(e)]:
+ print ' * Interface not installed'
+ else:
+ print ' *', e
+
+ #doesn't work so remove it from the dict
+ del interfaces[interface]
+ if interfaces:
+ print ' ... Trying another interface'
+ choose_interface()
+ else:
+ print ' *** Error: All interfaces failed, aborting!'
+ raise SystemExit
+
+def choose_interface(try_first=None):
+
+ chosen_interface = None
+
+ # handle explicit choice first
+ if try_first:
+ if try_first in interfaces:
+ chosen_interface = try_first
+ else:
+ raise SystemExit, ' *** Error: No such interface: %s' %try_first
+ else:
+
+# gtk for everybody for now
+ # use qt for kde; gtk for everything else:
+# if 'qt4' in interfaces and env.desktop == 'kde':
+# chosen_interface = 'qt4'
+
+# elif 'qt3' in interfaces and env.desktop == 'kde':
+# chosen_interface = 'qt3'
+
+ if 'gtk' in interfaces:
+ chosen_interface = 'gtk'
+
+ # try qt* for non-kde:
+ elif 'qt4' in interfaces:
+ chosen_interface = 'qt4'
+ elif 'qt3' in interfaces:
+ chosen_interface = 'qt3'
+
+ # interfaces is empty
+ else:
+ raise SystemExit, ' *** no available interfaces, this should not happen'
+
+ import_interface(chosen_interface)
+
diff --git a/FusionIcon/interface_gtk/__init__.py b/FusionIcon/interface_gtk/__init__.py
new file mode 100644
index 0000000..82a12c4
--- /dev/null
+++ b/FusionIcon/interface_gtk/__init__.py
@@ -0,0 +1,3 @@
+# Fusion Icon
+
+import main
diff --git a/FusionIcon/interface_gtk/main.py b/FusionIcon/interface_gtk/main.py
new file mode 100644
index 0000000..6cf1f5a
--- /dev/null
+++ b/FusionIcon/interface_gtk/main.py
@@ -0,0 +1,214 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Based on compiz-icon, Copyright 2007 Felix Bellanger <keeguon@gmail.com>
+#
+# Author(s): crdlb
+# Copyright 2007 Christopher Williams <christopherw@verizon.net>
+
+import os
+import gtk
+if gtk.pygtk_version < (2,10,0):
+ # raise an ImportError here to trigger the Except statement in interface.py
+ raise ImportError, 'PyGtk 2.10.0 or later required'
+
+import time
+from FusionIcon.start import wms, apps, options, decorators, init
+
+class TrayMenu(gtk.Menu):
+
+ def __init__(self):
+ gtk.Menu.__init__(self)
+
+ #CCSM
+ if 'ccsm' in apps:
+ item = ApplicationItem('ccsm')
+ item.set_image(gtk.image_new_from_stock('gtk-preferences', gtk.ICON_SIZE_MENU))
+ self.append(item)
+
+ #Emerald Theme Manager
+ if 'emerald theme manager' in apps:
+ item = ApplicationItem('emerald theme manager')
+ item.set_image(gtk.image_new_from_icon_name('emerald-theme-manager-icon', gtk.ICON_SIZE_MENU))
+ self.append(item)
+
+ if 'ccsm' in apps or 'emerald theme manager' in apps:
+ item = gtk.SeparatorMenuItem()
+ self.append(item)
+
+ #Reload
+ item = gtk.ImageMenuItem('Reload Window Manager')
+ item.connect('activate', self.reload_activate)
+ item.set_image(gtk.image_new_from_stock('gtk-refresh', gtk.ICON_SIZE_MENU))
+ if not wms:
+ item.set_sensitive(False)
+ self.append(item)
+
+ #Window Manager
+ item = gtk.ImageMenuItem('Select Window Manager')
+ item.set_image(gtk.image_new_from_stock('gtk-index', gtk.ICON_SIZE_MENU))
+ submenu = WindowManagerMenu()
+ item.set_submenu(submenu)
+ if not wms:
+ item.set_sensitive(False)
+ self.append(item)
+
+ #Compiz Options
+ item = gtk.ImageMenuItem('Compiz Options')
+ item.set_image(gtk.image_new_from_stock('gtk-properties', gtk.ICON_SIZE_MENU))
+ submenu = CompizOptionMenu()
+ item.set_submenu(submenu)
+ if not options:
+ item.set_sensitive(False)
+ self.append(item)
+
+ #Window Decorator
+ item = gtk.ImageMenuItem('Select Window Decorator')
+ item.set_image(gtk.image_new_from_stock('gtk-select-color', gtk.ICON_SIZE_MENU))
+ submenu = CompizDecoratorMenu()
+ item.set_submenu(submenu)
+ if not decorators:
+ item.set_sensitive(False)
+ self.append(item)
+
+ item = gtk.SeparatorMenuItem()
+ self.append(item)
+
+ item = gtk.ImageMenuItem(stock_id=gtk.STOCK_QUIT)
+ item.connect('activate', self.quit_activate)
+ self.append(item)
+
+ def show_menu(self, widget, button, time):
+ self.show_all()
+ self.popup(None, None, gtk.status_icon_position_menu, button, time, icon)
+
+ def reload_activate(self, widget):
+ wms.restart()
+
+ def quit_activate(self, widget):
+ gtk.main_quit()
+
+class ApplicationItem(gtk.ImageMenuItem):
+
+ def __init__(self, app):
+ gtk.ImageMenuItem.__init__(self, apps[app].label)
+
+ self.app = app
+ if app not in apps:
+ self.set_sensitive(False)
+ self.connect('activate', self.activate)
+
+ def activate(self, widget):
+ apps[self.app].launch()
+
+class WindowManagerItem(gtk.RadioMenuItem):
+
+ def __init__(self, wm, first_item=None):
+ gtk.RadioMenuItem.__init__(self, label=' %s' %wms[wm].label)
+
+ self.wm = wm
+ if first_item:
+ self.set_group(first_item)
+ if wms.active == wm:
+ self.set_active(True)
+ self.connect('activate', self.activate)
+
+ def activate(self, widget):
+ if widget.get_active():
+ wms.active = self.wm
+ wms.start()
+
+class WindowManagerMenu(gtk.Menu):
+
+ def __init__(self):
+ gtk.Menu.__init__(self)
+
+ first = True
+ for wm in wms.ordered_list:
+ if first:
+ first_item = WindowManagerItem(wm)
+ self.append(first_item)
+ first = False
+ else:
+ item = WindowManagerItem(wm, first_item)
+ self.append(item)
+
+class CompizOptionItem(gtk.CheckMenuItem):
+
+ def __init__(self, option):
+ gtk.CheckMenuItem.__init__(self, label=' %s' %options[option].label)
+
+ self.option = option
+ self.set_active(options[option].enabled)
+ if not options[option].sensitive:
+ self.set_sensitive(False)
+ self.connect('activate', self.activate)
+
+ def activate(self, widget):
+ options[self.option].enabled = widget.get_active()
+ if wms.active == 'compiz':
+ wms.start()
+
+class CompizOptionMenu(gtk.Menu):
+
+ def __init__(self):
+ gtk.Menu.__init__(self)
+
+ for option in options:
+ item = CompizOptionItem(option)
+ self.append(item)
+
+class CompizDecoratorItem(gtk.RadioMenuItem):
+
+ def __init__(self, decorator, first_item=None):
+ gtk.RadioMenuItem.__init__(self, label=' %s' %decorators[decorator].label)
+
+ self.decorator = decorator
+ if first_item:
+ self.set_group(first_item)
+ if decorators.active == decorator:
+ self.set_active(True)
+ self.connect('activate', self.activate)
+
+ def activate(self, widget):
+ if widget.get_active():
+ decorators[self.decorator].kill_others()
+ time.sleep(0.5)
+ decorators.active = self.decorator
+
+class CompizDecoratorMenu(gtk.Menu):
+
+ def __init__(self):
+ gtk.Menu.__init__(self)
+
+ first = True
+ for decorator in decorators:
+ if first:
+ first_item = CompizDecoratorItem(decorator)
+ self.append(first_item)
+ first = False
+ else:
+ item = CompizDecoratorItem(decorator, first_item)
+ self.append(item)
+
+icon = gtk.status_icon_new_from_icon_name('fusion-icon')
+icon.set_tooltip('Compiz Fusion Icon')
+menu = TrayMenu()
+icon.connect('popup-menu', menu.show_menu)
+
+# active wm (possibly) starts here
+init()
+gtk.main()
+
diff --git a/FusionIcon/interface_qt4/__init__.py b/FusionIcon/interface_qt4/__init__.py
new file mode 100644
index 0000000..82a12c4
--- /dev/null
+++ b/FusionIcon/interface_qt4/__init__.py
@@ -0,0 +1,3 @@
+# Fusion Icon
+
+import main
diff --git a/FusionIcon/interface_qt4/main.py b/FusionIcon/interface_qt4/main.py
new file mode 100644
index 0000000..91fb63f
--- /dev/null
+++ b/FusionIcon/interface_qt4/main.py
@@ -0,0 +1,80 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Author(s): xsacha
+
+import sys, os, time
+from PyQt4 import QtGui, QtCore
+from FusionIcon.start import wms, apps, options, decorators, init
+
+class Build(QtGui.QApplication):
+ def reload_wm(self):
+ wms.restart()
+ def toggleWM(self, wm):
+ if wms.active != wm:
+ wms.active = wm
+ wms.start()
+ def toggleOP(self, option):
+ options[option].enabled = not options[option].enabled
+ if wms.active == 'compiz':
+ wms.start()
+ def toggleWD(self, decorator):
+ decorators[decorator].kill_others()
+ time.sleep(0.5)
+ decorators.active = decorator
+ def __init__(self, parent=None):
+ QtCore.QObject.__init__(self, parent)
+ # Qt sucks (I'm aware this breaks if prefix != /usr...)
+ self.Tray = QtGui.QSystemTrayIcon(QtGui.QIcon('/usr/share/icons/hicolor/22x22/apps/fusion-icon.png'))
+ self.Tray.setToolTip('Compiz Fusion Icon')
+ self.Tray.managerMenu = QtGui.QMenu()
+ self.Tray.optionsMenu = QtGui.QMenu()
+ self.Tray.decoratorMenu = QtGui.QMenu()
+ self.groupManager = QtGui.QActionGroup(self.Tray.managerMenu)
+ self.groupDecorator = QtGui.QActionGroup(self.Tray.decoratorMenu)
+ for wm in wms.ordered_list:
+ actionWM = self.groupManager.addAction(self.Tray.managerMenu.addAction(wms[wm].label, lambda val=wm : self.toggleWM(val)))
+ actionWM.setCheckable(True)
+ if wms.active == wm:
+ actionWM.setChecked(True)
+ for option in options:
+ actionOP = self.Tray.optionsMenu.addAction(options[option].label, lambda val=option: self.toggleOP(val))
+ actionOP.setCheckable(True)
+ if not options[option].sensitive:
+ actionOP.setEnabled(False)
+ actionOP.setChecked(options[option].enabled)
+ for decorator in decorators:
+ actionWD = self.groupDecorator.addAction(self.Tray.decoratorMenu.addAction(decorators[decorator].label, lambda val=decorator: self.toggleWD(val)))
+ actionWD.setCheckable(True)
+ if decorators.active == decorator:
+ actionWD.setChecked(True)
+ self.Tray.menu = QtGui.QMenu()
+ if 'ccsm' in apps:
+ self.Tray.menu.addAction(apps['ccsm'].label, lambda: run(['ccsm']))
+ if 'emerald theme manager' in apps:
+ self.Tray.menu.addAction(apps['emerald theme manager'].label, lambda: run(apps['emerald theme manager'].command))
+ if 'ccsm' in apps or 'emerald theme manager' in apps:
+ self.Tray.menu.addSeparator()
+ self.Tray.menu.addAction("Reload Window Manager", self.reload_wm)
+ self.Tray.menu.addAction("Select Window Manager").setMenu(self.Tray.managerMenu)
+ self.Tray.menu.addAction("Compiz Options").setMenu(self.Tray.optionsMenu)
+ self.Tray.menu.addAction("Select Window Decorator").setMenu(self.Tray.decoratorMenu)
+ self.Tray.menu.addSeparator()
+ self.Tray.menu.addAction("Quit", self.quit)
+ self.Tray.setContextMenu(self.Tray.menu)
+ self.Tray.show()
+ init()
+Build(sys.argv).exec_()
+
diff --git a/FusionIcon/parser.py b/FusionIcon/parser.py
new file mode 100644
index 0000000..9b58145
--- /dev/null
+++ b/FusionIcon/parser.py
@@ -0,0 +1,57 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): crdlb
+# Copyright 2007 Christopher Williams <christopherw@verizon.net>
+
+from optparse import OptionParser, OptionGroup
+
+parser = OptionParser(usage='usage: %prog [options|action]', version='%prog-0.0.0')
+
+parser.add_option('--reset', action='store_true', dest='reset',
+ help='remove configuration file and exit')
+
+parser.add_option('-s', '--sleep', type='int', dest='seconds',
+ help='Sleep before launching')
+
+parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
+ help='Print extra output')
+
+interface_group = OptionGroup(parser, 'Interface Options')
+
+interface_group.add_option('-i', '--interface', dest='interface',
+ help='Try a certain interface first')
+
+interface_group.add_option('-u', '--no-interface', action='store_true', dest='no_interface',
+ help='Do not use any interface')
+
+parser.add_option_group(interface_group)
+
+startup_group = OptionGroup(parser, 'Startup Options')
+
+startup_group.add_option('-f', '--force-compiz', action='store_true', dest='force_compiz',
+ help='Start compiz regardless of environment or configuration')
+
+startup_group.add_option('-n', '--no-start', action='store_true', dest='no_start',
+ help='Run, but do not start a window manager')
+
+parser.add_option_group(startup_group)
+
+options, args = parser.parse_args()
+
+# fusion-icon accepts no arguments
+if args:
+ parser.error('no such argument: %s' %args[0])
+
diff --git a/FusionIcon/start.py b/FusionIcon/start.py
new file mode 100644
index 0000000..7dafdad
--- /dev/null
+++ b/FusionIcon/start.py
@@ -0,0 +1,68 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): crdlb, nesl247
+#
+# Copyright 2007 Christopher Williams <christopherw@verizon.net>
+
+from parser import options as parser_options
+from util import env, config, apps, options, wms, decorators
+
+def init():
+ 'Final start function, should be called once when fusion-icon starts'
+
+ if not parser_options.no_start:
+ # Do not restart the wm if it's already running
+ if wms.active == wms.active == wms.old != 'compiz':
+ #always restart compiz since we can't know compiz was started correctly
+ print ' * %s is already running' %wms[wms.active].label
+ else:
+ print ' * Starting %s' %wms[wms.active].label
+ wms.start()
+
+config.check()
+
+# Make some changes
+
+if not parser_options.force_compiz:
+ if wms.active not in wms:
+ print ' * "%s" not installed' %wms.active
+ if wms.fallback:
+ print ' ... setting to fallback...'
+ else:
+ print ' ... No fallback window manager chosen'
+ wms.active = wms.fallback
+# if in a failsafe session, don't start with compiz (provides an easy way to make sure metacity starts for gnome users if compiz breaks)
+ if wms.active == 'compiz' and env.failsafe:
+ if wms.fallback:
+ print ' * Failsafe session, setting to fallback...'
+ else:
+ print ' ... No fallback window manager chosen'
+
+ wms.active = wms.fallback
+
+elif 'compiz' in wms:
+ wms.active = 'compiz'
+
+else:
+ raise SystemExit, ' *** Error: "--force-compiz" used and compiz not installed!'
+
+# Set True if using Xorg AIGLX since the '--indirect-rendering' option has no effect in that situation.
+env.set()
+if env.tfp == 'indirect' and 'indirect rendering' in options:
+ options['indirect rendering'].sensitive = False
+ if not options['indirect rendering'].enabled:
+ options['indirect rendering'].enabled = True
+
diff --git a/FusionIcon/util.py b/FusionIcon/util.py
new file mode 100644
index 0000000..d121334
--- /dev/null
+++ b/FusionIcon/util.py
@@ -0,0 +1,419 @@
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Based on compiz-icon, Copyright 2007 Felix Bellanger <keeguon@gmail.com>
+#
+# Author(s): crdlb
+# Copyright 2007 Christopher Williams <christopherw@verizon.net>
+
+import os, compizconfig, ConfigParser, time
+import data as _data
+from parser import options as parser_options
+from environment import env
+from execute import run
+import subprocess, signal
+
+def is_running(app):
+ 'Use pgrep to determine if an app is running'
+
+ if run(['pgrep', app], 'call', quiet=True) == 0:
+ return True
+
+
+class Application(object):
+
+ def __init__(self, name, apps, installed):
+
+ self.name = name
+ self.apps = apps
+
+ self.base = installed.apps[name][0]
+ self.command = installed.apps[name][1]
+ self.label = installed.apps[name][2]
+
+ def launch(self):
+ print ' * Launching %s' %self.label
+ run(self.command)
+
+class Applications(dict):
+
+ def __init__(self, installed):
+ for app in installed.apps:
+ self[app] = Application(app, self, installed)
+
+class CompizOption(object):
+
+ def __init__(self, name, options, installed, config):
+
+ self.options = options
+ self.config = config
+
+ self.name = name
+ self.switch = installed.options[name][1]
+ self.label = installed.options[name][2]
+ self.sensitive = True
+
+ def __get(self):
+ return self.config.getboolean('compiz options', self.name)
+
+ def __set(self, value):
+ print ' * Setting option %s to %s' %(self.label, value)
+ self.config.set('compiz options', self.name, str(bool(value)).lower())
+ self.config.write(open(self.config.config_file, 'w'))
+
+ enabled = property(__get, __set)
+
+class CompizOptions(dict):
+
+ def __init__(self, installed, config):
+ for option in installed.options:
+ self[option] = CompizOption(option, self, installed, config)
+
+class WindowManager(object):
+
+ def __init__(self, name, wms, installed):
+
+ self.wms = wms
+ self.name = name
+ self.base = installed.wms[name][0]
+ self.command = installed.wms[name][1]
+ self.label = installed.wms[name][2]
+ self.desktop = installed.wms[name][3]
+ if installed.wms[name][4]:
+ self.flags = installed.wms[name][4]
+ else:
+ self.flags = []
+ self.killcmd = installed.wms[name][5]
+
+class WindowManagers(dict):
+
+ def __init__(self, installed, config):
+
+ self.config = config
+
+ for wm in installed.wms:
+ self[wm] = WindowManager(wm, self, installed)
+
+ self.fallback = None
+ wm = [w for w in self if self[w].desktop == env.desktop]
+ if wm:
+ self.fallback = wm[0]
+
+ elif self:
+ self.fallback = self.keys()[0]
+
+ self.__set_old()
+
+ self.ordered_list = []
+ for wm in ('compiz', self.fallback):
+ if wm in self:
+ self.ordered_list.append(wm)
+ self.ordered_list.extend([wm for wm in self if wm not in self.ordered_list])
+
+ def __get(self):
+ return self.config.get('window manager', 'active wm')
+
+ def __set(self, value):
+
+ if value in wms:
+ print ' * Setting window manager to', wms[value].label
+ elif not value:
+ print ' * Setting window manager to empty value'
+
+ self.config.set('window manager', 'active wm', str(value))
+ self.config.write(open(self.config.config_file, 'w'))
+
+ def __set_old(self):
+
+ self.old = None
+ running_wm = [wm for wm in self if is_running(wm)]
+ if running_wm:
+ # not perfect, but good enough
+ self.old = running_wm[0]
+
+ def start(self):
+ 'Start the active window manager'
+
+ self.__set_old()
+
+ if self.active == 'compiz' and self.old and self[self.old].killcmd:
+ run(self[self.old].killcmd, 'call')
+ time.sleep(1)
+
+ if self.active and self.old and 'noreplace' in self[self.active].flags:
+ run(['killall', self[self.old].base], 'call')
+ time.sleep(1)
+
+ if self.active == 'compiz':
+ # use a copy, not the original
+ compiz_command = self['compiz'].command[:]
+ for option in options:
+ if options[option].enabled:
+ compiz_command.append(options[option].switch)
+
+ kill_list = ['killall']
+ for decorator in decorators:
+ kill_list.append(decorators[decorator].base)
+ run(kill_list, 'call')
+
+ time.sleep(0.5)
+
+ # do it
+ print ' ... executing:', ' '.join(compiz_command)
+ run(compiz_command, quiet=False)
+
+ elif self.active:
+ run(self[self.active].command)
+
+ else:
+ print ' * No active WM set; not going to do anything.'
+
+ def restart(self):
+ if wms.active:
+ print ' * Reloading %s' %wms.active
+ self.start()
+
+ else:
+ print ' * Not reloading, no active window manager set'
+
+ active = property(__get, __set)
+
+class CompizDecorator(object):
+
+ def __init__(self, name, decorators, installed):
+
+ self.decorators = decorators
+ self.name = name
+ self.base = installed.decorators[name][0]
+ self.command = installed.decorators[name][1]
+ self.label = installed.decorators[name][2]
+ self.desktop = installed.decorators[name][3]
+
+ def kill_others(self):
+ killall = ['killall']
+ for decorator in [x for x in self.decorators if x != self.name]:
+ killall.append(self.decorators[decorator].base)
+ run(killall, 'call')
+
+class CompizDecorators(dict):
+
+ def __init__(self, installed):
+
+ # Open CompizConfig context
+ if parser_options.verbose:
+ print ' * Opening CompizConfig context'
+
+ try:
+ context = compizconfig.Context( \
+ plugins=['decoration'], basic_metadata=True)
+
+ except:
+ context = compizconfig.Context()
+
+ self.command = context.Plugins['decoration'].Display['command']
+
+ for decorator in installed.decorators:
+ self[decorator] = CompizDecorator(decorator, self, installed)
+
+ self.default = None
+ decorator = [d for d in self if self[d].desktop == env.desktop]
+ if decorator:
+ self.default = decorator[0]
+
+ elif 'emerald' in self:
+ self.default = 'emerald'
+
+ elif self:
+ self.default = self.keys()[0]
+
+ def __set(self, decorator):
+ if decorator in self:
+ self.command.Plugin.Context.ProcessEvents()
+ print ' * Setting decorator to %s ("%s")' \
+ %(self[decorator].label, self[decorator].command)
+ self.command.Value = self[decorator].command
+ self.command.Plugin.Context.Write()
+ elif not decorator:
+ print ' * Not setting decorator to none'
+
+ def __get(self):
+ _decorator = [d for d in self if self.command.Value == self[d].command]
+ if _decorator:
+ decorator = _decorator[0]
+ else:
+ print ' * Decorator "%s" is invalid.' %self.command.Value
+ self.active = self.default
+ decorator = self.command.Value
+ return decorator
+
+ active = property(__get, __set)
+
+class Installed(object):
+
+ def __init__(self, data):
+ print ' * Searching for installed applications...'
+
+ ### Compiz Detection
+ bins = {}
+ for name in ('compiz', 'compiz.real'):
+ bin = run(['which', name], 'output')
+ if bin:
+ bins[name] = bin
+
+ if 'compiz' in bins and 'compiz.real' in bins:
+ if bins['compiz'].split(os.sep)[:-1] == bins['compiz.real'].split(os.sep)[:-1]:
+ compiz = 'compiz.real'
+ else:
+ compiz = 'compiz'
+
+ elif 'compiz.real' in bins:
+ compiz = 'compiz.real'
+
+ elif 'compiz' in bins:
+ compiz = 'compiz'
+
+ else:
+ compiz = None
+
+ output = ''
+
+ for name in bins:
+ if len(bins) > 1 and name == compiz:
+ selected = ' <*>'
+ else:
+ selected = ''
+ output += ' -- %s%s' %(bins[name], selected)
+
+ ### Everything Else
+ self.wms = data.wms.copy()
+ for wm in data.wms:
+ which = run(['which', data.wms[wm][0]], 'output')
+ if which:
+ output += ' -- %s' %which
+ else:
+ del self.wms[wm]
+
+ if compiz:
+ data.compiz_args.insert(0, compiz)
+ self.wms['compiz'] = (compiz, data.compiz_args, 'Compiz', None, None, None)
+
+ self.decorators = data.decorators.copy()
+ for decorator in data.decorators:
+ which = run(['which', data.decorators[decorator][0]], 'output')
+ if which:
+ output += ' -- %s' %which
+ else:
+ del self.decorators[decorator]
+
+ self.apps = data.apps.copy()
+ for app in data.apps:
+ which = run(['which', data.apps[app][0]], 'output')
+ if which:
+ output += ' -- %s' %which
+ else:
+ del self.apps[app]
+
+ if parser_options.verbose:
+ print output.rstrip()
+
+ compiz_optionlist = []
+
+ self.options = data.options.copy()
+
+ if compiz:
+ compiz_help = run([compiz, '--help'], 'output')
+ for item in compiz_help.split():
+ item = item[1:].replace(']', '')
+ if item.startswith('--'):
+ compiz_optionlist.append(item)
+
+ for option in data.options:
+ if data.options[option][1] not in compiz_optionlist:
+ del self.options[option]
+
+class Configuration(ConfigParser.ConfigParser):
+
+ def __init__(self, data):
+
+ ConfigParser.ConfigParser.__init__(self)
+ self.config_folder = data.config_folder
+ self.config_file = data.config_file
+
+ def check(self):
+
+ # Configuration file setup
+ if not os.path.exists(self.config_folder):
+ if parser_options.verbose:
+ print ' * Creating configuration folder...'
+ os.makedirs(self.config_folder)
+
+ if not os.path.exists(self.config_file):
+ if parser_options.verbose:
+ print ' * Creating configuration file...'
+ self.create_config_file()
+
+ try:
+ # Read the file
+ self.read(self.config_file)
+ # Validate the file by trying to read all values
+ for option in options:
+ value = options[option].enabled
+ value = wms.active
+
+ except:
+ # back it up and make a new one
+ print ' * Configuration file (%s) invalid' %self.config_file
+ self.reset_config_file()
+ print ' * Generating new configuration file'
+ self.create_config_file()
+
+ def create_config_file(self):
+ 'Set default values for configuration file'
+
+ def prune(section, optlist):
+ for option in [o for o in self.options(section) if o not in optlist]:
+ self.remove_option(section, option)
+
+ for section in ('compiz options', 'window manager'):
+ if not self.has_section(section):
+ self.add_section(section)
+
+ for option in options:
+ self.set('compiz options', option, 'false')
+ self.set('window manager', 'active wm', 'compiz')
+
+ prune('compiz options', options)
+ prune('window manager', ['active wm'])
+ self.write(open(self.config_file, 'w'))
+
+ def reset_config_file(self):
+ 'Backup configuration file'
+
+ if os.path.exists(self.config_file):
+ config_backup = '%s.backup.%s' \
+ %(self.config_file, time.strftime('%Y%m%d%H%M%S'))
+ os.rename(self.config_file, config_backup)
+ print ' ... backed up to:', config_backup
+ else:
+ print ' ... no configuration file found'
+
+# Instantiate...
+_installed = Installed(_data)
+config = Configuration(_data)
+apps = Applications(_installed)
+options = CompizOptions(_installed, config)
+wms = WindowManagers(_installed, config)
+decorators = CompizDecorators(_installed)
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f499069
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+PREFIX = '/usr'
+DESTDIR = '/'
+#interfaces = 'gtk qt4'
+
+all:
+ @python setup.py build
+
+install:
+ @python setup.py install --prefix=${PREFIX} --root=${DESTDIR}
+
+uninstall:
+ @python setup.py uninstall
+
+clean:
+ rm -rf build/
+
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..3db20c7
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: fusion-icon
+Version: 0.0.0-git
+Summary: User-friendly tray icon for launching and managing Compiz Fusion
+Home-page: http://opencompositing.org
+Author: Christopher Williams
+Author-email: christopherw@verizon.net
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..cb36c66
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.0.0-git
diff --git a/fusion-icon b/fusion-icon
new file mode 100755
index 0000000..62c43d8
--- /dev/null
+++ b/fusion-icon
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# This file is part of Fusion-icon.
+
+# Fusion-icon is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Fusion-icon is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os, sys, time
+sys.path.append("/opt/kde3/lib/python2.6/dist-packages")
+sys.path.append("/opt/kde3/lib/python2.6/site-packages")
+
+try:
+ import FusionIcon
+
+except ImportError:
+ raise SystemExit(' * Error: the "FusionIcon" module is missing. If you did not install fusion-icon to /usr, you may need to add the appropriate site-packages directory to your PYTHONPATH')
+
+# parse command line
+from FusionIcon.parser import options
+
+if options.reset:
+ try:
+ from FusionIcon.data import config_file
+ print ' * Configuration file (%s) being reset' %config_file
+
+ if os.path.exists(config_file):
+ config_backup = '%s.backup.%s' %(config_file, time.strftime('%Y%m%d%H%M%S'))
+ os.rename(config_file, config_backup)
+ print ' ... backed up to:', config_backup
+
+ else:
+ print ' ... no configuration file found'
+
+ except:
+ print ' *** Error: configuration reset failed:'
+ raise SystemExit
+
+ sys.exit()
+
+if options.seconds and 0 < options.seconds <= 60:
+ print ' * Sleeping for %s seconds' %options.seconds
+ time.sleep(options.seconds)
+
+if options.no_interface:
+ # a skeleton interface
+ from FusionIcon.start import init
+ init()
+
+else:
+ from FusionIcon.interface import choose_interface
+ choose_interface(try_first=options.interface)
+
diff --git a/fusion-icon.desktop b/fusion-icon.desktop
new file mode 100644
index 0000000..18f35ee
--- /dev/null
+++ b/fusion-icon.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Version=1.0
+Name=Compiz Fusion Icon
+Comment=Start and manage Compiz Fusion
+Comment[ca]=Inicieu i gestioneu el Compiz Fusion
+Comment[es]=Inicia y gestiona Compiz Fusion
+Exec=fusion-icon --no-start
+Icon=fusion-icon
+Terminal=false
+Type=Application
+Categories=System;
diff --git a/images/22x22/fusion-icon.png b/images/22x22/fusion-icon.png
new file mode 100644
index 0000000..38df5fe
--- /dev/null
+++ b/images/22x22/fusion-icon.png
Binary files differ
diff --git a/images/24x24/fusion-icon.png b/images/24x24/fusion-icon.png
new file mode 100644
index 0000000..b9f96fd
--- /dev/null
+++ b/images/24x24/fusion-icon.png
Binary files differ
diff --git a/images/32x32/fusion-icon.png b/images/32x32/fusion-icon.png
new file mode 100644
index 0000000..768dfc6
--- /dev/null
+++ b/images/32x32/fusion-icon.png
Binary files differ
diff --git a/images/48x48/fusion-icon.png b/images/48x48/fusion-icon.png
new file mode 100644
index 0000000..3186fae
--- /dev/null
+++ b/images/48x48/fusion-icon.png
Binary files differ
diff --git a/images/scalable/fusion-icon.svg b/images/scalable/fusion-icon.svg
new file mode 100644
index 0000000..8aa53c1
--- /dev/null
+++ b/images/scalable/fusion-icon.svg
@@ -0,0 +1,561 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="256"
+ height="256"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45pre1"
+ version="1.0"
+ sodipodi:docbase="/home/jimmac/gfx/ximian/art/icons/tango-clipart"
+ sodipodi:docname="compiz.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true">
+ <defs
+ id="defs4">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient6434">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop6436" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop6438" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient6423">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop6425" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop6427" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient6307">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop6309" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop6311" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5831">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop5833" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop5835" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5715">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop5717" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop5719" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5707">
+ <stop
+ id="stop5709"
+ offset="0"
+ style="stop-color:#a0cef7;stop-opacity:1;" />
+ <stop
+ id="stop5711"
+ offset="1"
+ style="stop-color:#4d8ed4;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5683">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop5685" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop5687" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5673">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop5675" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop5677" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5663">
+ <stop
+ style="stop-color:#008ad0;stop-opacity:1;"
+ offset="0"
+ id="stop5665" />
+ <stop
+ style="stop-color:#006da5;stop-opacity:1;"
+ offset="1"
+ id="stop5667" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5599">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop5601" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop5603" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5565">
+ <stop
+ style="stop-color:#78d5fa;stop-opacity:1;"
+ offset="0"
+ id="stop5567" />
+ <stop
+ style="stop-color:#067cc1;stop-opacity:1"
+ offset="1"
+ id="stop5569" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5565"
+ id="linearGradient5571"
+ x1="108.82744"
+ y1="46.107311"
+ x2="108.82744"
+ y2="219.76578"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9374502,0,0,0.9374502,9.1002045,8.6374604)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5663"
+ id="linearGradient5669"
+ x1="193.02477"
+ y1="-46.499828"
+ x2="252.60443"
+ y2="175.85454"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9374502,0,0,0.9374502,9.1002045,8.6374604)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5673"
+ id="linearGradient5679"
+ x1="182.5"
+ y1="28.5"
+ x2="183.16669"
+ y2="236.96877"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9374502,0,0,0.9374502,9.1002045,8.6374604)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5707"
+ id="linearGradient5705"
+ gradientUnits="userSpaceOnUse"
+ x1="181.70184"
+ y1="129.75"
+ x2="186.35007"
+ y2="129.75"
+ gradientTransform="matrix(0.9540689,0,0,0.9540689,6.9937797,7.4186295)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5715"
+ id="linearGradient5721"
+ x1="65.75"
+ y1="145"
+ x2="64"
+ y2="198.25"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,0)" />
+ <filter
+ inkscape:collect="always"
+ id="filter5751">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.57"
+ id="feGaussianBlur5753" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter5825">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.9314286"
+ id="feGaussianBlur5827" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5831"
+ id="linearGradient5837"
+ x1="56"
+ y1="66.5"
+ x2="48.75"
+ y2="155"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ id="filter5899">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.59642857"
+ id="feGaussianBlur5901" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5599"
+ id="linearGradient5951"
+ gradientUnits="userSpaceOnUse"
+ x1="41"
+ y1="200"
+ x2="-27"
+ y2="117"
+ gradientTransform="translate(0,-2)" />
+ <filter
+ inkscape:collect="always"
+ x="-0.03128234"
+ width="1.0625647"
+ y="-0.14446753"
+ height="1.2889351"
+ id="filter6281">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.9728571"
+ id="feGaussianBlur6283" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ x="-0.053171913"
+ width="1.1063438"
+ y="-0.22092555"
+ height="1.4418511"
+ id="filter6295">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="7.8428571"
+ id="feGaussianBlur6297" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5599"
+ id="linearGradient6299"
+ gradientUnits="userSpaceOnUse"
+ x1="41"
+ y1="200"
+ x2="-27"
+ y2="117"
+ gradientTransform="translate(0,-2)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5683"
+ id="linearGradient6301"
+ gradientUnits="userSpaceOnUse"
+ x1="141.06781"
+ y1="68.616699"
+ x2="147.07822"
+ y2="239.73654"
+ gradientTransform="matrix(0.9374502,0,0,0.9374502,9.1002045,8.6374604)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6307"
+ id="linearGradient6313"
+ x1="202.5"
+ y1="212.5"
+ x2="197"
+ y2="190.5"
+ gradientUnits="userSpaceOnUse" />
+ <filter
+ inkscape:collect="always"
+ x="-0.15025974"
+ width="1.3005195"
+ y="-0.14692063"
+ height="1.2938413"
+ id="filter6367">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.3057143"
+ id="feGaussianBlur6369" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6307"
+ id="linearGradient6373"
+ gradientUnits="userSpaceOnUse"
+ x1="195.75"
+ y1="216"
+ x2="197"
+ y2="190.5"
+ gradientTransform="translate(1,0)" />
+ <filter
+ inkscape:collect="always"
+ id="filter6401">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.3265654"
+ id="feGaussianBlur6403" />
+ </filter>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6423"
+ id="radialGradient6429"
+ cx="182"
+ cy="37"
+ fx="182"
+ fy="37"
+ r="14"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0714286,0,0,1.0714286,-13,-2.6428571)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6434"
+ id="linearGradient6440"
+ x1="114.69536"
+ y1="152.77162"
+ x2="119.14867"
+ y2="210.77162"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,0)" />
+ <filter
+ inkscape:collect="always"
+ id="filter5657">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.7413321"
+ id="feGaussianBlur5659" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5599"
+ id="linearGradient5661"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2)"
+ x1="41"
+ y1="200"
+ x2="-27"
+ y2="117" />
+ <filter
+ inkscape:collect="always"
+ id="filter5695">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.89"
+ id="feGaussianBlur5697" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5715"
+ id="linearGradient4660"
+ gradientUnits="userSpaceOnUse"
+ x1="65.75"
+ y1="145"
+ x2="64"
+ y2="198.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6307"
+ id="linearGradient4662"
+ gradientUnits="userSpaceOnUse"
+ x1="195.75"
+ y1="216"
+ x2="197"
+ y2="190.5"
+ gradientTransform="translate(1,0)" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#a0a0a0"
+ borderopacity="1"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="164.53436"
+ inkscape:cy="99.75054"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ width="256px"
+ height="256px"
+ inkscape:window-width="872"
+ inkscape:window-height="767"
+ inkscape:window-x="220"
+ inkscape:window-y="197" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Compiz Logo (fancy)</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:description>Based on logo design by Srdjan Prodanovic (some1else) - http://forum.go-compiz.org/viewtopic.php?p=1839</dc:description>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/2.5/" />
+ <dc:coverage>compiz logo bling</dc:coverage>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/2.5/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ transform="matrix(0.8619785,0,0,0.8619785,21.599567,24.675196)"
+ style="opacity:0.54285709;fill:url(#linearGradient5661);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5657)"
+ d="M 3.8337389e-16,212 L 187,239 L 251.73311,207.26689 L 62,186 L 3.8337389e-16,212 z "
+ id="path5635"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:0.23999999;fill:url(#linearGradient5951);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6295)"
+ d="M -18,212 L 193,250 L 260.99915,204.13345 L 64,179 L -18,212 z "
+ id="path6285"
+ sodipodi:nodetypes="ccccc"
+ transform="matrix(0.905192,0,0,0.9374502,17.519558,8.6374604)" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path5921"
+ d="M 3.8337389e-16,212 L 187,239 L 251.73311,207.26689 L 62,186 L 3.8337389e-16,212 z "
+ style="opacity:0.26857144;fill:url(#linearGradient6299);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6281)"
+ transform="matrix(0.9374502,0,0,0.9374502,9.1002045,8.6374604)" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path5703"
+ d="M 183.97355,33.17849 L 232.15404,57.030212 L 232.15404,205.86496 L 183.97355,229.23965 L 24.627435,206.342 L 26.058539,55.59911 L 183.97355,33.17849 z "
+ style="fill:url(#linearGradient5705);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="opacity:0.82857145;fill:url(#linearGradient6440);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter6401)"
+ d="M 181.28188,34.948615 L 226.14866,58.654942 L 226.14866,201.34242 L 181.28188,220.59462 L 27.695363,197.79655 L 29.057742,57.292562 L 181.28188,34.948615 z "
+ id="path4594"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ id="path5755"
+ d="M 29,61 L 29,201 L 101,212 L 69,139 L 41,180 L 41,70 L 130,133 L 82,134 L 138,218 L 186,224 L 186,39 L 29,61 z "
+ style="opacity:0.50857143;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5825)"
+ sodipodi:nodetypes="cccccccccccc"
+ transform="matrix(0.9374502,0,0,0.9374502,9.1002045,8.6374604)" />
+ <path
+ style="fill:url(#linearGradient5571);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 30.661558,60.197219 L 30.661558,198.93984 L 101.90777,209.25179 L 71.909365,136.13068 L 45.660761,174.56614 L 45.660761,71.446621 L 129.09382,130.50598 L 84.096217,131.44343 L 136.59343,214.8765 L 181.59103,220.5012 L 181.59103,39.573316 L 30.661558,60.197219 z "
+ id="path4590" />
+ <path
+ style="fill:url(#linearGradient5669);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 181.59103,39.573316 L 181.59103,220.96992 L 226.11992,200.34602 L 226.11992,61.134669 L 181.59103,39.573316 z "
+ id="path4592" />
+ <path
+ style="opacity:0.84571425;fill:url(#linearGradient5679);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 183.55976,33.85479 L 170.27908,36.22969 C 170.27908,36.22969 179.12885,36.100393 179.24741,38.635865 L 181.59103,228.09502 L 182.82667,219.99768 L 183.99721,48.401503 C 183.99721,45.957596 191.34063,38.135865 191.34063,38.135865 L 183.55976,33.85479 z "
+ id="path5671"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="opacity:0.14857142;fill:url(#linearGradient6301);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 30.198549,60.802943 L 32.016582,148.8795 C 32.016582,148.8795 45.647495,146.78239 45.647495,146.78239 C 45.647495,146.78239 46.536427,72.091544 46.536427,72.091544 C 46.536427,72.091544 126.18247,129.86456 126.18247,129.86456 C 126.18247,129.86456 86.096028,132.71792 86.096028,132.71792 C 86.096028,132.71792 90.935899,142.05444 90.935899,142.05444 C 90.935899,142.05444 180.12256,132.34659 180.12256,132.34659 L 179.57342,40.802891 L 30.198549,60.802943 z "
+ id="path5681"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="opacity:0.33714288;fill:url(#linearGradient4660);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5751)"
+ d="M 66.75,137.25 L 97.75,213.25 L 66,140 L 40.75,176.5 L 66.75,137.25 z "
+ id="path5713"
+ transform="matrix(0.9374502,0,0,0.9374502,9.1002045,8.6374604)" />
+ <path
+ style="opacity:0.06285712;fill:url(#linearGradient5837);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5899)"
+ d="M 37.75,176.5 L 39.125,67 L 129.25,130 L 36.875,62.875 L 37.75,176.5 z "
+ id="path5829"
+ sodipodi:nodetypes="ccccc"
+ transform="matrix(0.9374502,0,0,0.9374502,9.1002045,8.6374604)" />
+ <path
+ style="opacity:0.33714288;color:#000000;fill:url(#linearGradient5721);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.93745017px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter5751);enable-background:accumulate"
+ d="M 85.75,132 L 131,131.25 L 88.25,133.5 L 97.25,150 L 85.75,132 z "
+ id="path6303" />
+ <path
+ style="opacity:0.24571431;fill:url(#linearGradient6313);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5695)"
+ d="M 183.0625,219.5 L 182.5625,188 L 216.25,177.25 L 216.25,203.75 L 183.0625,219.5 z "
+ id="path6305"
+ transform="matrix(1.4545455,0,0,1.4545455,-84.045455,-89.545455)"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:0.30857143;color:#000000;fill:url(#linearGradient4662);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter6367);enable-background:accumulate"
+ d="M 181,198 C 181,199.5 181.25,220.5 181.25,220.5 L 137.5,215 L 122,191.25 L 181,198 z "
+ id="path6371" />
+ <path
+ style="opacity:0.30857143;color:#000000;fill:url(#linearGradient6373);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter6367);enable-background:accumulate"
+ d="M 101.75,209.5 L 30.25,199 L 30.75,178.75 L 92,186.25 L 101.75,209.5 z "
+ id="path6375" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;color:#000000;fill:url(#radialGradient6429);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path6405"
+ sodipodi:cx="182"
+ sodipodi:cy="37"
+ sodipodi:rx="14"
+ sodipodi:ry="14"
+ d="M 196 37 A 14 14 0 1 1 168,37 A 14 14 0 1 1 196 37 z" />
+ <path
+ transform="matrix(0.4642857,0,0,0.4642857,97.5,19.821429)"
+ d="M 196 37 A 14 14 0 1 1 168,37 A 14 14 0 1 1 196 37 z"
+ sodipodi:ry="14"
+ sodipodi:rx="14"
+ sodipodi:cy="37"
+ sodipodi:cx="182"
+ id="path6431"
+ style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
+</svg>
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..eb79004
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+
+import sys, os
+from stat import *
+from distutils.core import setup
+from distutils.command.install import install as _install
+
+INSTALLED_FILES = '.installed_files'
+
+#stolen from ccsm
+class install (_install):
+
+ def run (self):
+
+ _install.run(self)
+ outputs = self.get_outputs()
+ data = '\n'.join(outputs)
+ try:
+ f = open(INSTALLED_FILES, 'w')
+ except:
+ self.warn ('Could not write installed files list %s' %INSTALLED_FILES)
+ return
+
+ f.write(data)
+ f.close()
+
+class uninstall(_install):
+
+ def run(self):
+ try:
+ files = file(INSTALLED_FILES, 'r').readlines()
+ except:
+ self.warn('Could not read installed files list %s' %INSTALLED_FILES)
+ return
+
+ for f in files:
+ print 'Uninstalling %s' %f.strip()
+ try:
+ os.unlink(f.strip())
+ except:
+ self.warn('Could not remove file %s' %f)
+ os.remove(INSTALLED_FILES)
+
+version = open('VERSION', 'r').read().strip()
+
+packages = ['FusionIcon']
+
+available_interfaces = {
+ 'gtk': 'FusionIcon.interface_gtk',
+ 'qt4': 'FusionIcon.interface_qt4',
+# 'qt3': 'FusionIcon.interface_qt3',
+}
+
+#if 'interfaces' in os.environ:
+# for interface in os.environ['interfaces'].split():
+# if interface in available_interfaces:
+# packages.append(available_interfaces[interface])
+#else:
+
+packages.extend(available_interfaces.values())
+
+
+data_files = [
+ ('share/icons/hicolor/22x22/apps',['images/22x22/fusion-icon.png']),
+ ('share/icons/hicolor/24x24/apps',['images/24x24/fusion-icon.png']),
+ ('share/icons/hicolor/48x48/apps',['images/48x48/fusion-icon.png']),
+ ('share/icons/hicolor/scalable/apps',['images/scalable/fusion-icon.svg']),
+ ('share/applications',['fusion-icon.desktop']),
+]
+
+
+setup(
+ name='fusion-icon',
+ version=version,
+ description='User-friendly tray icon for launching and managing Compiz Fusion',
+ author='Christopher Williams',
+ author_email='christopherw@verizon.net',
+ url='http://opencompositing.org',
+ packages=packages,
+ scripts=['fusion-icon'],
+ data_files=data_files,
+ cmdclass={
+ 'uninstall': uninstall,
+ 'install': install},
+)
+
+#Stolen from ccsm's setup.py
+if sys.argv[1] == 'install':
+
+ prefix = None
+
+ if len (sys.argv) > 2:
+ i = 0
+ for o in sys.argv:
+ if o.startswith ("--prefix"):
+ if o == "--prefix":
+ if len (sys.argv) >= i:
+ prefix = sys.argv[i + 1]
+ sys.argv.remove (prefix)
+ elif o.startswith ("--prefix=") and len (o[9:]):
+ prefix = o[9:]
+ sys.argv.remove (o)
+ break
+ i += 1
+
+ if not prefix:
+ prefix = '/usr'
+
+ gtk_update_icon_cache = '''gtk-update-icon-cache -f -t \
+%s/share/icons/hicolor''' % prefix
+ root_specified = [s for s in sys.argv if s.startswith('--root')]
+ if not root_specified or root_specified[0] == '--root=/':
+ print 'Updating Gtk icon cache.'
+ os.system(gtk_update_icon_cache)
+ else:
+ print '''*** Icon cache not updated. After install, run this:
+*** %s''' % gtk_update_icon_cache
+