diff --git a/README.md b/README.md
index 9b03792..afd70b3 100644
--- a/README.md
+++ b/README.md
@@ -12,9 +12,11 @@ On-demand tiling for Openbox, Xfce and other [EWMH Compliant Window Managers](ht
 
 ### Features
 - Workspace based tiling. You can enable tiling in one workspace and leave others untouched.
-- Ships with two simple tiling layouts (Vertical & Horizontal)
+- Ships with four simple tiling layouts:
+    Vertical, Horizontal, Square, and FullScreen
 - Customizable gap between tiling windows.
 - Autodetection of panels and docks.
+- Support for multiple monitors (Square Layout)
 
 ### Installation
 
diff --git a/config.go b/config.go
index 81a3310..e78de55 100644
--- a/config.go
+++ b/config.go
@@ -17,7 +17,9 @@ type cfg struct {
 	WindowsToIgnore []string `toml:"ignore"`
 	Gap             int
 	Proportion      float64
-	HideDecor       bool `toml:"remove_decorations"`
+	HideDecor       bool     `toml:"remove_decorations"`
+	MMRegions       [][4]int `toml:"multi_region_geometry"`
+	DefaultLayout   uint     `toml:"default_layout"`
 }
 
 func init() {
@@ -56,7 +58,16 @@ func configFilePath() string {
 	return filepath.Join(configFolderPath(), "config.toml")
 }
 
-var defaultConfig = `# Window decorations will be removed when tiling if set to true
+var defaultConfig = `## General Config
+
+# Startup Layout - preferred layout to begin with
+# 0 - Vertical
+# 1 - Horizontal
+# 2 - Square
+# 3 - Full Screen
+default_layout = 0
+
+# Window decorations will be removed when tiling if set to true
 remove_decorations = false
 
 # Zentile will ignore windows added to this list.
@@ -70,6 +81,27 @@ gap = 5
 # How much to increment the master area size.
 proportion = 0.1
 
+
+## Square Layout Config
+# Multiple Monitor Support (optional)
+#
+# You can use this to describe one or more areas where you want windows to be
+# handled separately.  This is most commonly because you have multiple monitors
+# displaying portions of, but not the full, workarea dimensions.
+# 
+# This is a list of region descriptions in the form (x, y, width, height)
+# where x and y represent the Top-Left corner of the region within the workarea
+# 
+# Here is an example with two monitors: one portrait and one landscape, with the
+# landscape display at a vertical offset of 630 pixels and to the right edge of the
+# portrait display
+
+# multi_region_geometry = [
+#	[0, 0, 1080, 1920],
+#	[1080, 630, 1920, 1080]
+#]
+
+
 [keybindings]
 # key sequences can have zero or more modifiers and exactly one key.
 # example: Control-Shift-t has two modifiers and one key.
diff --git a/keybinding.go b/keybinding.go
index ee55967..c4eeb15 100644
--- a/keybinding.go
+++ b/keybinding.go
@@ -29,6 +29,9 @@ func bindKeys(t *tracker) {
 
 	k.bind("tile", func() {
 		ws := workspaces[state.CurrentDesk]
+		if !ws.IsTiling {
+			ws.activeLayoutNum = Config.DefaultLayout % uint(len(ws.layouts))
+		}
 		ws.IsTiling = true
 		ws.Tile()
 	})
diff --git a/state/state.go b/state/state.go
index d02d441..3ab6342 100644
--- a/state/state.go
+++ b/state/state.go
@@ -93,5 +93,6 @@ func WorkAreaDimensions(num uint) (x, y, width, height int) {
 	y = w.Y
 	width = int(w.Width)
 	height = int(w.Height)
+	// log.Info("workArea ", num, " - X: ", x, " Y: ", y, " W: ", width, " H: ", height)
 	return
 }
diff --git a/store.go b/store.go
index a3b0472..124dcd0 100644
--- a/store.go
+++ b/store.go
@@ -67,9 +67,28 @@ func (st *Store) DecreaseMaster() {
 }
 
 func (st *Store) MakeMaster(c Client) {
+	if len(st.masters) > 0 && st.masters[0].window.Id == c.window.Id {
+		// Mastering the first master demotes it
+		s := st.masters[0]
+		slen := len(st.slaves)
+		if slen == 0 {
+			st.slaves = []Client{s}
+			st.masters = st.masters[1:]
+		} else {
+			st.masters[0], st.slaves[slen-1] = st.slaves[slen-1], st.masters[0]
+		}
+		return
+	}
+
 	for i, slave := range st.slaves {
 		if slave.window.Id == c.window.Id {
-			st.masters[0], st.slaves[i] = st.slaves[i], st.masters[0]
+			if len(st.masters) > 0 {
+				st.masters[0], st.slaves[i] = st.slaves[i], st.masters[0]
+			} else {
+				st.masters = []Client{st.slaves[i]}
+				st.slaves = append(st.slaves[:i], st.slaves[i+1:]...)
+			}
+			break
 		}
 	}
 }
diff --git a/vertical_horizonal_layout.go b/vertical_horizonal_layout.go
index ce3bb36..8bb0b3a 100644
--- a/vertical_horizonal_layout.go
+++ b/vertical_horizonal_layout.go
@@ -1,6 +1,8 @@
 package main
 
 import (
+	"math"
+
 	"github.com/blrsn/zentile/state"
 	log "github.com/sirupsen/logrus"
 )
@@ -98,3 +100,128 @@ func (l *HorizontalLayout) Do() {
 
 	state.X.Conn().Sync()
 }
+
+type SquareLayout struct {
+	*VertHorz
+}
+
+func (l *SquareLayout) Do() {
+	// intended for lots of small windows
+	log.Info("Switching to Square Layout")
+	wx, wy, ww, wh := state.WorkAreaDimensions(l.WorkspaceNum)
+
+	gap := Config.Gap
+
+	// concatenating all the window clients into a single list
+	// The master window proportional zoom is not supported in this layout.
+	// Selecting a window as a master using the hotkey has the effect of
+	// 		swapping it with whatever window was currently  in the number
+	//		one (top-left) position.
+	allClients := append(l.masters, l.slaves...)
+
+	// sub-regions of the main work area (to describe multiple monitors)
+	// regions is a slice of (x,y,width,height) arrays
+	// clients get divided evenly among regions then regions are
+	// rendered serially
+	var regions [][4]int = Config.MMRegions
+
+	if len(regions) == 0 {
+		regions = append(regions, [4]int{wx, wy, ww, wh})
+	}
+
+	nregions := len(regions)
+	segsize := len(allClients) / nregions
+
+	for i := 0; i < nregions; i += 1 {
+		region := regions[i]
+		rx := region[0]
+		ry := region[1]
+		rw := region[2]
+		rh := region[3]
+
+		var regionClients []Client
+		if i+1 == nregions {
+			regionClients = allClients[i*segsize:]
+		} else {
+			regionClients = allClients[i*segsize : (i+1)*segsize]
+		}
+		csize := len(regionClients)
+
+		if csize == 0 {
+			continue
+		}
+		cols := int(math.Floor(math.Sqrt(float64(csize))))
+		rows := cols // default to perfect square
+
+		// cols^2 + 2*cols + 1 === (cols + 1)^2
+		extras := int(math.Ceil(float64(csize)/float64(cols))) - cols // 0..2
+
+		// if taller than wide, add additional rows first
+		// if wider than tall, add additional columns first
+		if extras > 0 {
+			if rh >= rw {
+				rows = rows + 1
+			} else {
+				cols = cols + 1
+			}
+		}
+		if extras == 2 {
+			if rh >= rw {
+				cols = cols + 1
+			} else {
+				rows = rows + 1
+			}
+		}
+
+		colsize := rw/cols - gap
+		rowsize := rh/rows - gap
+
+		padx := 0
+		pady := 0
+
+		// here is an algo for auto-padding (gap becomes minimum pad)
+		// i ended up not liking it and figured it would add too
+		// much complexity to the config, but here it is...
+
+		// if rowsize < colsize && cols > 1 {
+		// 	padx = (colsize - rowsize) * cols / (cols - 1)
+		// 	colsize = rowsize
+		// 	for padx > colsize {
+		// 		colsize = colsize * 3 / 2
+		// 		padx = (rw - colsize*cols) / (cols - 1)
+		// 	}
+		// } else if rowsize > colsize && rows > 1 {
+		// 	pady = (rowsize - colsize) * rows / (rows - 1)
+		// 	rowsize = colsize
+		// 	for pady > rowsize {
+		// 		rowsize = rowsize * 3 / 2
+		// 		pady = (rh - rowsize*rows) / (rows - 1)
+		// 	}
+		// }
+
+		mx := rx
+		my := ry
+
+		log.Info("cols: ", cols, " rows: ", rows, " colsize: ", colsize, " rowsize: ", rowsize, " padx: ", padx, " pady: ", pady)
+
+		currcol := 1
+		for _, c := range regionClients {
+			if Config.HideDecor {
+				c.UnDecorate()
+			}
+
+			log.Info("Moving ", c.name(), ": ", " X: ", mx, " Y: ", my)
+			c.MoveResize(mx, my, colsize, rowsize)
+
+			mx = mx + colsize + padx + gap
+			currcol = currcol + 1
+			if currcol > cols {
+				mx = rx
+				my = my + rowsize + pady + gap
+				currcol = 1
+			}
+		}
+	}
+
+	state.X.Conn().Sync()
+}
diff --git a/workspace.go b/workspace.go
index 990978b..7ed0456 100644
--- a/workspace.go
+++ b/workspace.go
@@ -38,6 +38,10 @@ func createLayouts(workspaceNum uint) []Layout {
 			Proportion:   0.5,
 			WorkspaceNum: workspaceNum,
 		}},
+		&SquareLayout{&VertHorz{
+			Store:        buildStore(),
+			WorkspaceNum: workspaceNum,
+		}},
 		&FullScreen{
 			Store:        buildStore(),
 			WorkspaceNum: workspaceNum,