#!/usr/bin/env python
######################################################################
######################################################################
# Fluxspace idesk support module
######################################################################
######################################################################
import os
import os.path
import sys
import os.path
from glob import glob
from fluxspace.config import Config
ideskCmd = 'idesk'
idesktops = os.path.expanduser('~/.fluxbox/idesktops')
idesktop = os.path.expanduser('~/.idesktop')
desktopFmt = 'desktop%d'
iconFmt = '''\
table Icon
Caption: %s
Command: "%s"
Icon: %s
X: %d
Y: %d
end'''
# Get offsets from configuration
offsetx = offsety = 0
fluxspaceConfig = Config()
fluxspaceConfig.Load()
config = fluxspaceConfig.ModuleConfig('idesk')
if config.getAttribute('offsetx'):
offsetx = int(config.getAttribute('offsetx'))
if config.getAttribute('offsety'):
offsety = int(config.getAttribute('offsety'))
class IdeskDesktopsDirectoryUnavailable(Exception):
pass
class IdeskDesktopDirectoryUnavailable(Exception):
pass
######################################################################
def SetDesktop(helper, n = -1, link = 1):
######################################################################
if n >= 0:
dir = os.path.join(idesktops, desktopFmt % n)
else:
dir = idesktops
if os.path.exists(dir):
if not os.path.isdir(dir):
helper.Message(2, 'Desktop directory "%s" already exists as a non-directory' % dir)
raise IdeskDesktopsDirectoryUnavailable()
else:
helper.Message(0, 'Creating desktop directory "%s"...' % dir)
os.makedirs(dir)
# Only link if it's a specific desktop and the caller requests it
if n >= 0 and link:
helper.Trace('Linking desktop %d...' % n)
if os.path.exists(idesktop):
if not os.path.islink(idesktop):
helper.Message(2, 'idesk directory "%s" already exists as a non-directory' % idesktop)
raise IdeskDesktopDirectoryUnavailable()
os.unlink(idesktop)
os.symlink(dir, idesktop)
return dir
######################################################################
class CellSpec:
######################################################################
def __init__(self, width, height):
self.width = width
self.height = height
self.midx = width / 2
self.midy = width / 2
######################################################################
class Desktop:
######################################################################
def __init__(self, helper, workspace):
global offsetx, offsety
self.helper = helper
self.width = 640
self.height = 480
self.offsetx = offsetx
self.offsety = offsety
self.GetScreenDimensions()
self.Reset(workspace)
def Reset(self, workspace):
self.cellSpec = CellSpec(100, 100)
self.cells = {} # map cell grid usage hashed on (x,y) pairs
self.workspace = workspace
self.dir = SetDesktop(self.helper, self.workspace, 0)
self.MapIcons()
def OffsetIcons(self, offsetx, offsety):
self.offsetx = offsetx
self.offsety = offsety
# Deduce the width and height using xwininfo on the root window
def GetScreenDimensions(self):
for line in os.popen('xwininfo -root').readlines():
try:
(tag, val) = line.split()[:2]
if tag.lower() == 'width:':
self.width = int(val)
if tag.lower() == 'height:':
self.height = int(val)
except ValueError:
pass
def Key(self, x, y):
return (int(x-self.offsetx/self.cellSpec.width),
int(y-self.offsety/self.cellSpec.height))
def Mark(self, x, y):
key = self.Key(x,y)
if not self.cells.has_key(key):
self.cells[key] = 0
self.cells[key] += 1
def IsMarked(self, x, y):
key = self.Key(x,y)
return (self.cells.has_key(key) and self.cells[key] > 0)
def FindCell(self):
for x in range(self.cellSpec.midx+self.offsetx, self.width, self.cellSpec.width):
for y in range(self.cellSpec.midy+self.offsety, self.height, self.cellSpec.height):
if not self.IsMarked(x, y):
return (x, y)
return (self.cellSpec.midx+self.offsetx, self.cellSpec.midy+self.offsety)
# Mark the cells occupied by other icons as used
def MapIcons(self):
for lnk in glob(os.path.join(self.dir, '*.lnk')):
(x, y) = (0, 0)
lnkf = open(lnk)
for line in lnkf.readlines():
try:
(tag, val) = line.split()[:2]
if tag.lower() == 'x:':
x = int(val)
if tag.lower() == 'y:':
y = int(val)
except ValueError:
pass
lnkf.close()
self.Mark(x, y)
def AddIcon(self, caption, command, iconPath, x = -1, y = -1):
# Find a reasonable position based on the other desktop icons
if x < 0 or y < 0:
(x, y) = self.FindCell()
# Determine a unique idesk icon file name
name = os.path.split(command.split()[0])[1]
path = os.path.join(self.dir, '%s.lnk' % name)
i = 0
while os.path.exists(path):
i += 1
path = os.path.join(self.dir, '%s%d.lnk' % (name, i))
# Write the idesk icon file
lnkf = open(path, 'w')
lnkf.write(iconFmt % (caption, command, iconPath, x, y))
lnkf.close()
self.Mark(x, y)
return (x, y)
# Mirror a directory containing Rox AppDirs on a desktop
def SyncAppDirs(self, directory, clean = 1):
if clean:
lnks = glob(os.path.join(self.dir, '*.lnk'))
for lnk in lnks:
try:
os.remove(lnk)
except OSError:
pass
self.Reset(self.workspace)
for f in glob(os.path.join(directory, '*')):
apprun = os.path.join(f, 'AppRun')
if os.path.isdir(f) and os.access(apprun, os.X_OK):
caption = os.path.split(f)[1]
command = apprun
iconPath = os.path.join(f, '.DirIcon')
self.AddIcon(caption, command, iconPath)
syntax highlighted by Code2HTML, v. 0.9.1