1 #!/usr/bin/env python 2 3 """ 4 Simple desktop integration for Python. This module provides desktop environment 5 detection and resource opening support for a selection of common and 6 standardised desktop environments. 7 8 Copyright (C) 2005 Paul Boddie <paul@boddie.org.uk> 9 10 This library is free software; you can redistribute it and/or 11 modify it under the terms of the GNU Lesser General Public 12 License as published by the Free Software Foundation; either 13 version 2.1 of the License, or (at your option) any later version. 14 15 This library is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 Lesser General Public License for more details. 19 20 You should have received a copy of the GNU Lesser General Public 21 License along with this library; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 23 24 -------- 25 26 Desktop Detection 27 ----------------- 28 29 To detect a specific desktop environment, use the get_desktop function. 30 To detect whether the desktop environment is standardised (according to the 31 proposed DESKTOP_LAUNCH standard), use the is_standard function. 32 33 Opening URLs 34 ------------ 35 36 To open a URL in the current desktop environment, relying on the automatic 37 detection of that environment, use the desktop.open function as follows: 38 39 desktop.open("http://www.python.org") 40 41 To override the detected desktop, specify the desktop parameter to the open 42 function as follows: 43 44 desktop.open("http://www.python.org", "KDE") # Insists on KDE 45 desktop.open("http://www.python.org", "GNOME") # Insists on GNOME 46 47 Without overriding using the desktop parameter, the open function will attempt 48 to use the "standard" desktop opening mechanism which is controlled by the 49 DESKTOP_LAUNCH environment variable as described below. 50 51 The DESKTOP_LAUNCH Environment Variable 52 --------------------------------------- 53 54 The DESKTOP_LAUNCH environment variable must be shell-quoted where appropriate, 55 as shown in some of the following examples: 56 57 DESKTOP_LAUNCH="kdialog --msgbox" Should present any opened URLs in 58 their entirety in a KDE message box. 59 (Command "kdialog" plus parameter.) 60 DESKTOP_LAUNCH="my\ opener" Should run the "my opener" program to 61 open URLs. 62 (Command "my opener", no parameters.) 63 DESKTOP_LAUNCH="my\ opener --url" Should run the "my opener" program to 64 open URLs. 65 (Command "my opener" plus parameter.) 66 67 Details of the DESKTOP_LAUNCH environment variable convention can be found here: 68 http://lists.freedesktop.org/archives/xdg/2004-August/004489.html 69 """ 70 71 __version__ = "0.2.2" 72 73 import os 74 import sys 75 import subprocess 76 import commands 77 78 def get_desktop(): 79 80 """ 81 Detect the current desktop environment, returning the name of the 82 environment. If no environment could be detected, None is returned. 83 """ 84 85 if os.environ.has_key("KDE_FULL_SESSION") or \ 86 os.environ.has_key("KDE_MULTIHEAD"): 87 return "KDE" 88 elif os.environ.has_key("GNOME_DESKTOP_SESSION_ID") or \ 89 os.environ.has_key("GNOME_KEYRING_SOCKET"): 90 return "GNOME" 91 elif sys.platform == "darwin": 92 return "Mac OS X" 93 elif hasattr(os, "startfile"): 94 return "Windows" 95 else: 96 return None 97 98 def is_standard(): 99 100 """ 101 Return whether the current desktop supports standardised application 102 launching. 103 """ 104 105 return os.environ.has_key("DESKTOP_LAUNCH") 106 107 def _wait(pid, block): 108 109 """ 110 Perform a blocking Wait for the given process identifier, 'pid', if the 111 'block' flag is set to a true value. Return the process identifier. 112 """ 113 114 if block: 115 os.waitpid(pid, os.P_WAIT) 116 return pid 117 118 def open(url, desktop=None, wait=0): 119 120 """ 121 Open the 'url' in the current desktop's preferred file browser. If the 122 optional 'desktop' parameter is specified then attempt to use that 123 particular desktop environment's mechanisms to open the 'url' instead of 124 guessing or detecting which environment is being used. 125 126 Suggested values for 'desktop' are "standard", "KDE", "GNOME", "Mac OS X", 127 "Windows" where "standard" employs a DESKTOP_LAUNCH environment variable to 128 open the specified 'url'. DESKTOP_LAUNCH should be a command, possibly 129 followed by arguments, and must have any special characters shell-escaped. 130 131 The process identifier of the "opener" (ie. viewer, editor, browser or 132 program) associated with the 'url' is returned by this function. If the 133 process identifier cannot be determined, None is returned. 134 135 An optional 'wait' parameter is also available for advanced usage and, if 136 'wait' is set to a true value, this function will wait for the launching 137 mechanism to complete before returning (as opposed to immediately returning 138 as is the default behaviour). 139 """ 140 141 # Attempt to detect a desktop environment. 142 143 detected = get_desktop() 144 145 # Start with desktops whose existence can be easily tested. 146 147 if (desktop is None or desktop == "standard") and is_standard(): 148 arg = "".join([os.environ["DESKTOP_LAUNCH"], commands.mkarg(url)]) 149 return _wait(subprocess.Popen(arg, shell=1).pid, wait) 150 151 elif (desktop is None or desktop == "Windows") and detected == "Windows": 152 # NOTE: This returns None in current implementations. 153 return os.startfile(url) 154 155 # Test for desktops where the overriding is not verified. 156 157 elif (desktop or detected) == "KDE": 158 cmd = ["kfmclient", "exec", url] 159 160 elif (desktop or detected) == "GNOME": 161 cmd = ["gnome-open", url] 162 163 elif (desktop or detected) == "Mac OS X": 164 cmd = ["open", url] 165 166 # Finish with an error where no suitable desktop was identified. 167 168 else: 169 raise OSError, "Desktop not supported (neither DESKTOP_LAUNCH nor os.startfile could be used)" 170 171 return _wait(subprocess.Popen(cmd).pid, wait) 172 173 # vim: tabstop=4 expandtab shiftwidth=4