cascade.lua 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. --[[
  2. Licensed under GNU General Public License v2
  3. * (c) 2014, projektile
  4. * (c) 2013, Luca CPZ
  5. * (c) 2010-2012, Peter Hofmann
  6. --]]
  7. local floor = math.floor
  8. local screen = screen
  9. local cascade = {
  10. name = "cascade",
  11. nmaster = 0,
  12. offset_x = 32,
  13. offset_y = 8,
  14. tile = {
  15. name = "cascadetile",
  16. nmaster = 0,
  17. ncol = 0,
  18. mwfact = 0,
  19. offset_x = 5,
  20. offset_y = 32,
  21. extra_padding = 0
  22. }
  23. }
  24. local function do_cascade(p, tiling)
  25. local t = p.tag or screen[p.screen].selected_tag
  26. local wa = p.workarea
  27. local cls = p.clients
  28. if #cls == 0 then return end
  29. if not tiling then
  30. -- Cascade windows.
  31. local num_c
  32. if cascade.nmaster > 0 then
  33. num_c = cascade.nmaster
  34. else
  35. num_c = t.master_count
  36. end
  37. -- Opening a new window will usually force all existing windows to
  38. -- get resized. This wastes a lot of CPU time. So let's set a lower
  39. -- bound to "how_many": This wastes a little screen space but you'll
  40. -- get a much better user experience.
  41. local how_many = (#cls >= num_c and #cls) or num_c
  42. local current_offset_x = cascade.offset_x * (how_many - 1)
  43. local current_offset_y = cascade.offset_y * (how_many - 1)
  44. -- Iterate.
  45. for i = 1,#cls,1 do
  46. local c = cls[i]
  47. local g = {}
  48. g.x = wa.x + (how_many - i) * cascade.offset_x
  49. g.y = wa.y + (i - 1) * cascade.offset_y
  50. g.width = wa.width - current_offset_x
  51. g.height = wa.height - current_offset_y
  52. if g.width < 1 then g.width = 1 end
  53. if g.height < 1 then g.height = 1 end
  54. p.geometries[c] = g
  55. end
  56. else
  57. -- Layout with one fixed column meant for a master window. Its
  58. -- width is calculated according to mwfact. Other clients are
  59. -- cascaded or "tabbed" in a slave column on the right.
  60. -- (1) (2) (3) (4)
  61. -- +----------+---+ +----------+---+ +----------+---+ +----------+---+
  62. -- | | | | | 3 | | | 4 | | +---+|
  63. -- | | | -> | | | -> | +---++ -> | +---+|+
  64. -- | 1 | 2 | | 1 +---++ | 1 | 3 || | 1 +---+|+|
  65. -- | | | | | 2 || | +---++| | +---+|+ |
  66. -- | | | | | || | | 2 | | | | 2 |+ |
  67. -- +----------+---+ +---------+---++ +--------+---+-+ +------+---+---+
  68. local mwfact
  69. if cascade.tile.mwfact > 0 then
  70. mwfact = cascade.tile.mwfact
  71. else
  72. mwfact = t.master_width_factor
  73. end
  74. -- Make slave windows overlap main window? Do this if ncol is 1.
  75. local overlap_main
  76. if cascade.tile.ncol > 0 then
  77. overlap_main = cascade.tile.ncol
  78. else
  79. overlap_main = t.column_count
  80. end
  81. -- Minimum space for slave windows? See cascade.tile.lua.
  82. local num_c
  83. if cascade.tile.nmaster > 0 then
  84. num_c = cascade.tile.nmaster
  85. else
  86. num_c = t.master_count
  87. end
  88. local how_many = (#cls - 1 >= num_c and (#cls - 1)) or num_c
  89. local current_offset_x = cascade.tile.offset_x * (how_many - 1)
  90. local current_offset_y = cascade.tile.offset_y * (how_many - 1)
  91. if #cls <= 0 then return end
  92. -- Main column, fixed width and height.
  93. local c = cls[1]
  94. local g = {}
  95. -- Rounding is necessary to prevent the rendered size of slavewid
  96. -- from being 1 pixel off when the result is not an integer.
  97. local mainwid = floor(wa.width * mwfact)
  98. local slavewid = wa.width - mainwid
  99. if overlap_main == 1 then
  100. g.width = wa.width
  101. -- The size of the main window may be reduced a little bit.
  102. -- This allows you to see if there are any windows below the
  103. -- main window.
  104. -- This only makes sense, though, if the main window is
  105. -- overlapping everything else.
  106. g.width = g.width - cascade.tile.extra_padding
  107. else
  108. g.width = mainwid
  109. end
  110. g.height = wa.height
  111. g.x = wa.x
  112. g.y = wa.y
  113. if g.width < 1 then g.width = 1 end
  114. if g.height < 1 then g.height = 1 end
  115. p.geometries[c] = g
  116. -- Remaining clients stacked in slave column, new ones on top.
  117. if #cls <= 1 then return end
  118. for i = 2,#cls do
  119. c = cls[i]
  120. g = {}
  121. g.width = slavewid - current_offset_x
  122. g.height = wa.height - current_offset_y
  123. g.x = wa.x + mainwid + (how_many - (i - 1)) * cascade.tile.offset_x
  124. g.y = wa.y + (i - 2) * cascade.tile.offset_y
  125. if g.width < 1 then g.width = 1 end
  126. if g.height < 1 then g.height = 1 end
  127. p.geometries[c] = g
  128. end
  129. end
  130. end
  131. function cascade.tile.arrange(p)
  132. return do_cascade(p, true)
  133. end
  134. function cascade.arrange(p)
  135. return do_cascade(p, false)
  136. end
  137. return cascade