#!/usr/bin/env python
#
# petliwm.py -- Example PLWM window manager "configuration"
#
#    Copyright (C) 1999-2001  Peter Liljenberg <petli@ctrl-c.liu.se>
#
#    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


import sys
import os

###SETUP PATH
sys.path[1:1] = [os.path.join(sys.path[0], '..')]
###END SETUP PATH

import time

from Xlib import X

from plwm import wmanager, focus, keys, \
     deltamove, outline, \
     frame, color, font, views, \
     modewindow, modestatus, \
     mw_clock, mw_biff, \
     inspect

from plwm.cycle import CycleKeys
from plwm.moveresize import MoveResizeKeys
from plwm.cfilter import *

delta = deltamove.DeltaMove()

class MyClient(wmanager.Client,
               outline.XorOutlineClient,
               modestatus.ModeFocusedTitleClient):

    # Put a frame around all client windows
    window_proxy_class = frame.FrameProxy

    start_iconified_clients = name('WMManager')
    default_pointer_pos = {'Emacs': (-1, 0),
                           'XTerm': (-1, 0)}


class MyScreen(wmanager.Screen,
               color.Color,
               modewindow.ModeWindowScreen,
               modestatus.ModeStatus,
               modestatus.ModeMoveResize,
               views.XMW_ViewHandler,
               modestatus.ModeFocusedTitleScreen):

    view_always_visible_clients = Or(name('XClock'),
                                     name('XBiff'),
                                     name('XModeWindow'))

class WMConfig:
    def __wm_init__(self):
        # Install the basic key map
        BasicKeys(self)


class PLWM(wmanager.WindowManager,
           font.Font,
           focus.SloppyFocus,
           focus.MoveFocus,
           mw_clock.ModeWindowClock,
           mw_biff.ModeWindowBiff,
           inspect.InspectServer,
           WMConfig):

    client_class = MyClient
    screen_class = MyScreen


class BasicKeys(keys.KeyHandler):
    def F1(self, event):
        self.wm.current_screen.view_find_with_client(name('XTerm'))

    def S_F1(self, event):
        self.wm.system('xterm -geometry 80x50+200+100')

    def C_S_F1(self, event):
        self.wm.current_screen.view_new()
        self.wm.system('xterm -geometry 80x50+200+100')

    def F2(self, event):
        self.wm.current_screen.view_find_with_client(name('Emacs'))

    def S_F2(self, event):
        self.wm.system('emacs')

    def C_S_F2(self, event):
        self.wm.current_screen.view_new()
        self.wm.system('emacs')

    def F3(self, event):
        self.wm.current_screen.view_find_with_client(name('Netscape'))

    def S_F3(self, event):
        self.wm.system('netscape')

    def C_S_F3(self, event):
        self.wm.current_screen.view_new()
        self.wm.system('netscape')

    def F5(self, event):
        self.wm.current_screen.view_find_tag('F5')

    def S_F5(self, event):
        self.wm.current_screen.view_tag('F5')

    def F6(self, event):
        self.wm.current_screen.view_find_tag('F6')

    def S_F6(self, event):
        self.wm.current_screen.view_tag('F6')

    def F7(self, event):
        self.wm.current_screen.view_find_tag('F7')

    def S_F7(self, event):
        self.wm.current_screen.view_tag('F7')

    def F8(self, event):
        self.wm.current_screen.view_find_tag('F8')

    def S_F8(self, event):
        self.wm.current_screen.view_tag('F8')

    # Simulate mouse clicks
    def Any_F9(self, evt):
        self.wm.fake_button_click(1)

    def Any_F10(self, evt):
        self.wm.fake_button_click(2)

    def Any_F11(self, evt):
        self.wm.fake_button_click(3)


    def F12(self, evt):
        self.wm.inspect_toggle()

    def S_F12(self, evt):
        self.wm.inspect_toggle(force = 1)

    # Drop all keygrabs until Scroll_Lock is pressed again, to allow
    # clients to recieve keys used by plwm

    def S_Pause(self, evt):
        wmanager.debug('keys', 'dropping keygrabs temporarily')

        # First release all our grabs.  They will be reinstalled
        # when BypassHandler exits

        self._ungrab()
        BypassHandler(self)


    def KP_Begin(self, event):
        MyMoveResizeKeys(self, event)


    def C_Tab(self, event):
        CycleUMKeys(self, event)

    def KP_Insert(self, event):
        wmanager.debug('keys', 'Iconifying')
        if self.wm.current_client:
            self.wm.current_client.iconify()

    def KP_Subtract(self, event):
        wmanager.debug('keys', 'Prev view')
        self.wm.current_screen.view_prev()

    def KP_Add(self, event):
        wmanager.debug('keys', 'Next view')
        self.wm.current_screen.view_next()

    def C_KP_Add(self, event):
        wmanager.debug('keys', 'New view')
        self.wm.current_screen.view_new()

    def KP_Left(self, event):
        self.wm.display.warp_pointer(-delta.get(event.time), 0)

    def KP_Right(self, event):
        self.wm.display.warp_pointer(delta.get(event.time), 0)

    def KP_Up(self, event):
        self.wm.display.warp_pointer(0, -delta.get(event.time))

    def KP_Down(self, event):
        self.wm.display.warp_pointer(0, delta.get(event.time))

    def KP_Home(self, event):
        d = delta.get(event.time)
        self.wm.display.warp_pointer(-d, -d)

    def KP_End(self, event):
        d = delta.get(event.time)
        self.wm.display.warp_pointer(-d, d)

    def KP_Prior(self, event):
        d = delta.get(event.time)
        self.wm.display.warp_pointer(d, -d)

    def KP_Next(self, event):
        d = delta.get(event.time)
        self.wm.display.warp_pointer(d, d)

    def KP_Enter(self, event):
        if self.wm.current_client:
            self.wm.current_client.raiselower()

    # For laptop compitability
    KP_Divide = KP_Enter

    def C_KP_Subtract(self, event):
        self.wm.system('xlock -mode blank')

    def C_M_Escape(self, event):
        self.wm.quit()

    def C_KP_Delete(self, event):
        if self.wm.current_client:
            self.wm.current_client.delete(1)

    def C_S_KP_Delete(self, event):
        if self.wm.current_client:
            self.wm.current_client.destroy()

    def C_KP_Left(self, event):
        self.wm.move_focus(focus.MOVE_LEFT)

    def C_KP_Right(self, event):
        self.wm.move_focus(focus.MOVE_RIGHT)

    def C_KP_Up(self, event):
        self.wm.move_focus(focus.MOVE_UP)

    def C_KP_Down(self, event):
        self.wm.move_focus(focus.MOVE_DOWN)

    def C_less(self, event):
        self.wm.move_focus(focus.MOVE_LEFT)

    def C_S_less(self, event):
        self.wm.move_focus(focus.MOVE_RIGHT)


class BypassHandler(keys.KeyHandler):
    propagate_keys = 0

    def __init__(self, keyhandler):
        keys.KeyHandler.__init__(self, keyhandler.wm)
        self._keyhandler = keyhandler
        self._message = modewindow.Message(.1, modewindow.LEFT, 0, '[Bypassing]')
        self._screen = keyhandler.wm.current_screen
        self._screen.modewindow_add_message(self._message)

    def Pause(self, evt):
        wmanager.debug('keys', 'reinstalling keygrabs')

        self._screen.modewindow_remove_message(self._message)

        # Delete ourself, and reinstall the callee grabs
        self._cleanup()
        self._keyhandler._buildmap()

        # Remove it, just to be sure there are no circular references
        del self._keyhandler
        del self._screen

#
# Use the keymap for moving and resizing windows.
# Without any modifiers moves, with Shift enlarges, with Ctrl shrinks
# End with KP_5.  Abort with Escape or KP_Delete.
#

class MyMoveResizeKeys(MoveResizeKeys):
    KP_Left  = MoveResizeKeys._move_w
    KP_Right = MoveResizeKeys._move_e
    KP_Up    = MoveResizeKeys._move_n
    KP_Down  = MoveResizeKeys._move_s
    KP_Home  = MoveResizeKeys._move_nw
    KP_End   = MoveResizeKeys._move_sw
    KP_Prior = MoveResizeKeys._move_ne
    KP_Next  = MoveResizeKeys._move_se

    S_KP_Left  = MoveResizeKeys._enlarge_w
    S_KP_Right = MoveResizeKeys._enlarge_e
    S_KP_Up    = MoveResizeKeys._enlarge_n
    S_KP_Down  = MoveResizeKeys._enlarge_s
    S_KP_Home  = MoveResizeKeys._enlarge_nw
    S_KP_End   = MoveResizeKeys._enlarge_sw
    S_KP_Prior = MoveResizeKeys._enlarge_ne
    S_KP_Next  = MoveResizeKeys._enlarge_se

    C_KP_Left  = MoveResizeKeys._shrink_w
    C_KP_Right = MoveResizeKeys._shrink_e
    C_KP_Up    = MoveResizeKeys._shrink_n
    C_KP_Down  = MoveResizeKeys._shrink_s
    C_KP_Home  = MoveResizeKeys._shrink_nw
    C_KP_End   = MoveResizeKeys._shrink_sw
    C_KP_Prior = MoveResizeKeys._shrink_ne
    C_KP_Next  = MoveResizeKeys._shrink_se

    KP_Begin   = MoveResizeKeys._moveresize_end
    S_KP_Begin = MoveResizeKeys._moveresize_end
    C_KP_Begin = MoveResizeKeys._moveresize_end

    Escape    = MoveResizeKeys._moveresize_abort
    KP_Delete = MoveResizeKeys._moveresize_abort


class CycleUMKeys(CycleKeys):
    _cycle_filter = iconified

    Tab = CycleKeys._cycle_next
    C_Tab = CycleKeys._cycle_next
    S_Tab = CycleKeys._cycle_previous
    S_C_Tab = CycleKeys._cycle_previous

    Escape = CycleKeys._cycle_abort
    Return = CycleKeys._cycle_end


if __name__ == '__main__':
    wmanager.main(PLWM)
