#!/usr/bin/python
# $Id: plpwm.py,v 1.16 2002/02/18 04:27:48 mwm Exp $
#
# plpwm.py -- Exemple PLWM window manager configuration with panes.
#
# Copyright (C) 2001 Mike Meyer <mwm@mired.org>
#
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""plpwm.py - Pointer Less Paned Window Manager
Example PLWM window manager configuration with panes."""
import sys, os
###SETUP PATH
sys.path[1:1] = [os.path.join(sys.path[0], '..')]
import plwm.xlibpath
###END SETUP PATH
from Xlib import X, XK
from plwm import wmanager, keys, inspect, \
border, color, font, menu, panes, cfilter, input, message
border.BorderClient.border_default_width = 5
class MyMenuHandler(menu.MenuCharHandler):
Any_Escape = C_g = menu.MenuKeyHandler._abort
Any_Return = menu.MenuKeyHandler._do
Any_space = Any_Down = C_n = menu.MenuKeyHandler._down
Any_BackSpace = Any_Up = C_p = menu.MenuKeyHandler._up
class MyEditHandler(input.InputKeyHandler):
Any_Escape = C_g = input.InputKeyHandler._abort
Any_Return = input.InputKeyHandler._done
Any_BackSpace = C_h = input.InputKeyHandler._delback
C_d = input.InputKeyHandler._delforw
C_b = input.InputKeyHandler._back
C_f = input.InputKeyHandler._forw
C_k = input.InputKeyHandler._deltoend
C_a = input.InputKeyHandler._begin
C_e = input.InputKeyHandler._end
C_y = input.InputKeyHandler._paste
class MyClient(wmanager.Client, border.BorderClient, panes.panesClient):
"Put the clients in panes, with a border."
class MyScreen(wmanager.Screen,
color.Color,
message.screenMessage,
panes.panesScreen,
menu.screenMenu):
"And panes on the screen, and I'm going to want some menus."
menu_handler = MyMenuHandler
allow_raise_requests = 0
class WMConfig:
def __wm_init__(my):
"install the panes key map"
PaneKeys(my)
class PLPWM(wmanager.WindowManager,
font.Font,
panes.panesManager,
inspect.InspectServer,
WMConfig):
"Set up my window manager."
client_class = MyClient
screen_class = MyScreen
class PaneKeys(keys.KeyHandler):
"The pane control keys."
# Commands for navigating and manipulating panes
def M1_Escape(my, event): my.wm.quit()
def C_0(my, event):
"Go to the pane numbered by the keycode."
my.wm.panes_goto(my.wm.display.keycode_to_keysym(event.detail, 0) - XK.XK_0)
C_1 = C_2 = C_3 = C_4 = C_5 = C_6 = C_7 = C_8 = C_9 = C_0
def M1_Tab(my, event): my.wm.panes_next()
def S_M1_Tab(my, event): my.wm.panes_prev()
def M1_1(my, event):
my.wm.panes_list[my.wm.panes_current].maximize()
def M1_2(my, event):
split_pane(my.wm.display.keycode_to_keysym(event.detail, 0) - XK.XK_0,
my.wm.panes_list[my.wm.panes_current].horizontal_split)
M1_3 = M1_4 = M1_5 = M1_6 = M1_7 = M1_8 = M1_9 = M1_2
def S_M1_2(my, event):
split_pane(my.wm.display.keycode_to_keysym(event.detail, 0) - XK.XK_0,
my.wm.panes_list[my.wm.panes_current].vertical_split)
S_M1_3 = S_M1_4 = S_M1_5 = S_M1_6 = S_M1_7 = S_M1_8 = S_M1_9 = S_M1_2
# Keystrokes for launching applications
def M1_exclam(my, event):
runcommand(my.wm.panes_list[my.wm.panes_current])
def M1_m(my, event):
appmenu(my.wm.panes_list[my.wm.panes_current],
{'words': 'applix -wp',
'sql': 'applix -db',
'sheet': 'applix -ss',
'fxtv': 'fxtv',
'w3m': 'w3m',
'skipstone': 'skipstone'})
def M1_b(my, event): getapp(my.wm.panes_list[my.wm.panes_current], "w3m")
def M1_c(my, event): my.wm.system("xterm -ls &")
def M1_e(my, event):
my.wm.panes_goto(0) # always run emacs in pane 0.
getapp(my.wm.panes_list[my.wm.panes_current], "emacs", "xemacs")
def M1_i(my, event):
getapp(my.wm.panes_list[my.wm.panes_current],
"/home/mwm/axhome/axMail/Inbox.sp", "applix -inbox")
def M1_j(my, event):
getapp(my.wm.panes_list[my.wm.panes_current], "J-Pilot", "jpilot")
def M1_s(my, event):
getapp(my.wm.panes_list[my.wm.panes_current], "SkipStone", "skipstone")
# Keystrokes for window manager operations
def M1_quoteright(my, event):
pullwindow(my.wm.panes_list[my.wm.panes_current])
def M1_quotedbl(my, event):
gotowindow(my.wm.panes_list[my.wm.panes_current])
def M1_Return(my, event):
my.wm.panes_list[my.wm.panes_current].next_window()
def S_M1_Return(my, event):
my.wm.panes_list[my.wm.panes_current].prev_window()
def M1_k(my, event):
my.wm.panes_list[my.wm.panes_current].window.delete(1)
def S_M1_k(my, event):
my.wm.panes_list[my.wm.panes_current].window.destroy()
def M1_r(my, event):
my.wm.panes_list[my.wm.panes_current].force_window()
def M1_u(my, event):
windowmenu(my.wm.panes_list[my.wm.panes_current],
lambda w: not (w.panes_pane and w.panes_pane.window == w))
def M1_x(my, event):
ExtendedPaneKeys(my.wm, event.time)
# Aliases for some of the keystrokes
M1_space = M1_Return
S_M1_space = S_M1_Return
class ExtendedPaneKeys(keys.KeyGrabKeyboard):
"Extended command, with a timeout."
def M1_b(my, event):
windowmenu(my.wm.panes_list[my.wm.panes_current])
my._cleanup()
def M1_f(my, event):
width, height = my.wm.current_screen.message_make("Current pane %d" \
% my.wm.panes_current)
pane = my.wm.panes_list[my.wm.panes_current]
my.wm.current_screen.message_display((pane.width - width) / 2 + pane.x,
(pane.height - height) / 2 + pane.y)
my._cleanup()
def M1_i(my, event):
my.wm.inspect_enable()
my.wm.system('xterm -title Inspector -e inspect_plwm &')
my._cleanup()
def M1_m(my, event):
appmenu(my.wm.panes_list[my.wm.panes_current],
{'mixer': 'xgmixer',
'console': 'xconsole -daemon',
'gkrellm': 'gkrellm'})
my._cleanup()
def M1_p(my, event):
panesmenu(my.wm.current_screen)
my._cleanup()
def M1_r(my, event):
restore(my.wm)
my._cleanup()
def M1_s(my, event):
my.wm.panes_save()
my._cleanup()
def M1_u(my, event):
windowmenu(my.wm.panes_list[my.wm.panes_current], cfilter.iconified)
my._cleanup()
def M1_w(my, event):
pane = my.wm.panes_list[my.wm.panes_current]
windowmenu(pane, panes.panefilter(pane))
my._cleanup()
def M1_x(my, event):
my.wm.panes_list[my.wm.panes_current].iconify_window()
my._cleanup()
Any_g = Any_Escape = keys.KeyGrabKeyboard._timeout
class appmenu:
"Creates a menu of applications to run in a pane."
def __init__(my, pane, apps):
"Create and run the applications menu from the keys."
labels = apps.keys()
labels.sort()
width, height = pane.screen.menu_make(labels)
my.system = pane.screen.system
my.apps = apps
pane.screen.menu_run((pane.width - width) / 2 + pane.x,
(pane.height - height) / 2 + pane.y,
my)
def __call__(my, choice):
"Call the system function on the value of the given choice."
my.system(my.apps[choice] + " &")
class windowmenu:
"Create a menu of windows to add to a pane."
def __init__(my, pane, filter = cfilter.true, list = None):
labels = []
clients = {}
i = 'a'
for c in list or pane.screen.query_clients(filter, 1):
l = "%c: %s" % (i, c.get_title())
labels.append(l)
clients[l] = c
i = chr(ord(i) + 1)
if labels:
width, height = pane.screen.menu_make(labels, align = 'left')
my.add = pane.add_window
my.clients = clients
pane.screen.menu_run((pane.width - width) / 2 + pane.x,
(pane.height - height) / 2 + pane.y,
my)
else:
width, height = pane.screen.message_make("No windows")
pane.screen.message_display((pane.width - width) / 2 + pane.x,
(pane.height - height) / 2 + pane.y)
def __call__(my, choice):
"Add the selected window to the pane."
my.add(my.clients[choice])
class panesmenu:
"Create a menu of all the panes."
def __init__(my, screen):
wm = screen.wm
labels = []
panes = {}
for i in range(len(wm.panes_list)):
w = wm.panes_list[i].window
if w: l = "%d: %s" % (i, w.get_title())
else: l = "%d: <EMPTY>" % i
labels.append(l)
panes[l] = i
width, height = screen.menu_make(labels, align = 'left')
my.goto = wm.panes_goto
my.panes = panes
screen.menu_run((screen.root_width - width) / 2,
(screen.root_height - height) / 2, my)
def __call__(my, choice):
"Activate the selected pane."
my.goto(my.panes[choice])
class runcommand:
"Read a string from the user, and run it."
def __init__(my, pane):
my.system = pane.screen.system
window = input.inputWindow("! ", pane.screen, length = 50)
window.read(my, MyEditHandler, pane.x, pane.y)
def __call__(my, string):
my.system(string + " &")
class pullwindow:
"Read a window's name, and pull it to the current pane."
def __init__(my, pane):
my.pane = pane
window = input.inputWindow("pull ", pane.screen)
window.read(my, MyEditHandler, pane.x, pane.y)
def __call__(my, name):
clients = my.pane.screen.query_clients(cfilter.re_title(name + ".*"), 1)
if len(clients) == 1: my.pane.add_window(clients[0])
elif clients: windowmenu(my.pane, list = clients)
else:
width, height = my.pane.screen.message_make("No windows")
my.pane.screen.message_display(my.pane.x, my.pane.y)
class gotowindow:
"Emulate the rp 'goto' command."
def __init__(my, pane):
my.pane = pane
window = input.inputWindow("goto ", pane.screen)
window.read(my, MyEditHandler)
def __call__(my, name):
clients = my.pane.screen.query_clients(cfilter.re_title(name + ".*"), 1)
if clients:
window = clients[0]
if window.panes_pane.window and window.panes_pane.window == window:
my.pane.wm.panes_activate(window.panes_pane)
else:
my.pane.add_window(window)
else:
width, height = my.pane.screen.message_make("No windows")
my.pane.screen.message_display(0, 0)
def getapp(pane, name, command = None):
"Find a window starting with name, and run command if it doesn't exist."
clients = pane.screen.query_clients(cfilter.re_title(name + ".*"), 1)
if len(clients) > 1: windowmenu(pane, list = clients)
elif clients: pane.add_window(clients[0])
else: pane.screen.system((command or name) + " &")
def restore(wm):
"Build my standard work environment."
pane = wm.panes_list[wm.panes_current]
pane.maximize()
# Disconnect all windows from panes to avoid displaying everything
# that's about to happen. wm.panes_restore() will put things back.
for c in wm.query_clients():
c.panes_pane = None
pane.window = None
pane.vertical_split()
wm.panes_number(0)
wm.panes_goto(1)
pane.horizontal_split(.0625)
pane.vertical_split(.75)
wm.panes_number(1)
pane = wm.panes_list[1]
pane.horizontal_split(94. / 225.)
wm.panes_number(3)
pane.horizontal_split()
wm.panes_number(2)
pane = wm.panes_list[4]
pane.horizontal_split(16. / 45.)
pane.horizontal_split(24. / 29.)
wm.panes_goto(4)
wm.panes_restore()
def split_pane(count, splitter):
"Split current pane into 2-9 equal-sized panes."
while count > 1:
splitter(1. / count)
count -= 1
if __name__ == '__main__':
wmanager.main(PLPWM)
syntax highlighted by Code2HTML, v. 0.9.1