;;; DEPENDENCIES

(require 'iswitch-window-with-class)
(require 'focus-by-direction)
(require 'get-window-by-class-re)
(require 'gnome)

(remove-hook 'after-initialization-hook pager)

;;; DEFINITIONS

(defun main-screen-p ()
  "Returns true if this sawfish instance is running on the main screen of display :0"
  (or (= display-name ":0.0")
      (= display-name ":0")))

(defmacro main-screen-only (#!rest exprs)
  "Evaluate exprs, but only if running on the main screen of display :0"
  `(cond ((main-screen-p) ,@exprs)))

;;; NEW COMMANDS

(defun toggle-window-always-on-top (w)
  "Toggle the depth of the window between 0 (default) and 1 (always on top)."
  (window-put w 'depth
	      (if (> (window-get w 'depth) 0) 0 1)))

(defun window-is-on-top (w)
  "Returns true if the window w is on top, false otherwise."
  (> (window-get w 'depth) 0))

(defun window-depth-string (w)
  (let ((d (window-get w 'depth)))
    (if (= d 0) "" (format nil "[depth: %d]" d))))

(defun center-window (w)
  "Position the window in the center of the current head"
  (interactive "%W")
  (if (windowp w)
      (let ((d (window-frame-dimensions w))
	    (s (head-dimensions (current-head)))
	    (o (head-offset (current-head))))
	(move-window-to w (+ (car o) (round (/ (- (car s) (car d)) 2)))
			  (+ (cdr o) (round (/ (- (cdr s) (cdr d)) 2)))))
    nil))

(defun center-window-screen (w)
  "Position the window in the center of the screen"
  (interactive "%W")
  (if (windowp w)
      (let ((d (window-frame-dimensions w))
	    (s (screen-dimensions)))
	(move-window-to w (round (/ (- (car s) (car d)) 2))
			  (round (/ (- (cdr s) (cdr d)) 2))))
    nil))

(defun move-window-right (w)
  "Move the window as far right as possible"
  (interactive "%W")
  (if (windowp w)
      (let ((p (window-position w))
	    (d (window-frame-dimensions w))
	    (s (screen-dimensions)))
	(move-window-to w (- (car s) (car d)) (cdr p)))
    nil))

(defun move-window-left (w)
  "Move the window as far left as possible"
  (interactive "%W")
  (if (windowp w)
      (let ((p (window-position w)))
	(move-window-to w 0 (cdr p)))
    nil))

(defun move-window-down (w)
  "Move the window as far down as possible"
  (interactive "%W")
  (if (windowp w)
      (let ((p (window-position w))
	    (d (window-frame-dimensions w))
	    (s (head-dimensions (current-head))))
	(move-window-to w (car p) (- (cdr s) (cdr d))))
    nil))

(defun move-window-up (w)
  "Move the window as far up as possible"
  (interactive "%W")
  (if (windowp w)
      (let ((p (window-position w)))
	(move-window-to w (car p) 0))
    nil))

(defun toggle-desktop ()
  "Toggle visibility of the desktop"
  (interactive)
  (if (showing-desktop-p) (hide-desktop) (show-desktop)))

(define-command 'toggle-window-always-on-top toggle-window-always-on-top #:spec "%W")
(define-command 'center-window #'center-window #:spec "%W")
(define-command 'center-window-screen #'center-window-screen #:spec "%W")
(define-command 'move-window-left #'move-window-left #:spec "%W")
(define-command 'move-window-right #'move-window-right #:spec "%W")
(define-command 'move-window-up #'move-window-up #:spec "%W")
(define-command 'move-window-down #'move-window-down #:spec "%W")
(define-command 'toggle-desktop #'toggle-desktop)

(defun cancel-actions ()
  "Cancel actions in progress and hide the message display"
  (interactive)
  (display-message nil))

(defun banish-pointer ()
  "Warp the mouse pointer to the upper right corner of the screen"
  (interactive)
  (warp-cursor (- (screen-width) 1) 0))

(defun gnome-panel-window ()
  "Return a window object for one of the GNOME Panel windows"
  (get-window-by-class-re "^Gnome-panel/gnome-panel$"))

(defun gnome-main-menu ()
  "Open the GNOME main menu"
  (interactive)
  (send-client-message (gnome-panel-window)
		       '_GNOME_PANEL_ACTION
		       (vector (x-atom '_GNOME_PANEL_ACTION_MAIN_MENU) 0)
		       32))

(defun gnome-run-dialog ()
  "Open the GNOME 'Run' dialog"
  (interactive)
  (send-client-message (gnome-panel-window)
		       '_GNOME_PANEL_ACTION
		       (vector (x-atom '_GNOME_PANEL_ACTION_RUN_DIALOG) 0)
		       32))


;;; KEYBINDINGS
(define help-keymap
  (bind-keys (make-keymap)
	     "k"          'describe-key-to-screen
	     "W-k"        'describe-key-to-screen
	     "b"          'customize:bindings
	     "W-b"        'customize:bindings
	     "v"          'apropos-variable-to-screen
	     "W-v"        'describe-symbol-to-screen
	     "i"          'help:show-programmer-manual
	     "W-i"        'help:show-programmer-manual 
	     "f"          'apropos-function-to-screen
	     "W-f"        'describe-symbol-to-screen))

(bind-keys global-keymap
	   "M-W-Left"     'focus-west
	   "M-W-Right"    'focus-east
	   "M-W-Up"       'focus-north
	   "M-W-Down"     'focus-south
	   "W-w"          'iswitch-window    ; in iswitch-window-with-class.jl
	   "W-g"          'cancel-actions
	   "W-?"          help-keymap
	   "W-o"          '(run-shell-command "clipboard-open")
	   "W-`"          'banish-pointer)

(bind-keys window-keymap
	   "W-KP_Up"    'pack-window-up
	   "W-KP_Left"  'pack-window-left
	   "W-KP_Right" 'pack-window-right
	   "W-KP_Down"  'pack-window-down
	   "W-KP_Home"  '(command-sequence '(pack-window-left  pack-window-up))
	   "W-KP_Prior" '(command-sequence '(pack-window-right pack-window-up))
	   "W-KP_End"   '(command-sequence '(pack-window-left  pack-window-down))
	   "W-KP_Next"  '(command-sequence '(pack-window-right pack-window-down))
	   "W-KP_Begin" 'center-window
	   
	   "C-W-KP_Up"    'move-window-up
	   "C-W-KP_Left"  'move-window-left
	   "C-W-KP_Right" 'move-window-right
	   "C-W-KP_Down"  'move-window-down
	   "C-W-KP_Home"  '(command-sequence '(move-window-left  move-window-up))
	   "C-W-KP_Prior" '(command-sequence '(move-window-right move-window-up))
	   "C-W-KP_End"   '(command-sequence '(move-window-left  move-window-down))
	   "C-W-KP_Next"  '(command-sequence '(move-window-right move-window-down))
	   "C-W-KP_Begin" 'center-window-screen
	   
	   "W-KP_8"   'grow-window-up
	   "W-KP_4"   'grow-window-left
	   "W-KP_6"   'grow-window-right
	   "W-KP_2"   'grow-window-down
	   "W-KP_7"   '(command-sequence '(grow-window-left  grow-window-up))
	   "W-KP_9"   '(command-sequence '(grow-window-right grow-window-up))
	   "W-KP_1"   '(command-sequence '(grow-window-left  grow-window-down))
	   "W-KP_3"   '(command-sequence '(grow-window-right grow-window-down))
	   "W-KP_5"   'unmaximize-window)


(mapc
 #'(lambda (p)
     (let* ((n (car p))
	    (s (cdr p))
	    (k  (format nil "W-%d" n))
	    (ck (format nil "C-W-%d" n))
	    (sk (format nil "W-%s" s)))
       (bind-keys global-keymap k  `(activate-workspace ,n))
       (bind-keys global-keymap sk `(command-sequence '((send-to-workspace ,n) (activate-workspace ,n))))
       (bind-keys global-keymap ck `(command-sequence '((copy-to-workspace ,n) (activate-workspace ,n))))
       ))
 '((1 . !)  (2 . @)  (3 . \#)  (4 . $) (5 . %) (6 . ^)))


;;; MISC. INITIALIZATION


;; Want five workspaces on main screen, just one on the others
(setq workspace-names (list "Main" "XEmacs" "WWW" "IRC" "Games" "Work"))

(setq workspace-boundary-mode      'wrap-around
      workspace-send-boundary-mode 'wrap-around)

;; If $DISPLAY is :0 etc, change it to :0.0
(let ((DISP (getenv "DISPLAY")))
  (unless (string-match "\\." DISP)
    (setenv "DISPLAY" (concat DISP ".0"))))