Module: TotalSpaces

Defined in:
lib/totalspaces.rb

Defined Under Namespace

Classes: Space, Spaces, Window

Constant Summary collapse

MAX_DESKTOPS =
16
UNUSED_SPACE_NUMBER_OFFSET =
100

Class Method Summary collapse

Class Method Details

.add_desktops(number_to_add) ⇒ Object

Add desktops There can be at most 16 desktops Returns true on success, false if number_to_add was zero, or would result in more than 16 desktops. The on_layout_change notification will be sent if a changed was made.

TotalSpaces.add_desktops(1)


386
387
388
# File 'lib/totalspaces.rb', line 386

def add_desktops(number_to_add)
  TSApi.tsapi_addDesktops(number_to_add)
end

.api_versionObject

Returns the version of the api present in TotalSpaces, a string such as “1.0” You should be using the same dylib version as that returned by the this call

puts "TotalSpaces API version: #{TotalSpaces.api_version}"

if TotalSpaces.lib_total_spaces_version != TotalSpaces.api_version
  puts "Comms error!"
  exit(1)
end


131
132
133
# File 'lib/totalspaces.rb', line 131

def api_version
  string_and_free(TSApi.tsapi_apiVersion)
end

.cancel_on_layout_changeObject

Cancel the layout change notification



312
313
314
315
# File 'lib/totalspaces.rb', line 312

def cancel_on_layout_change
  $tsapi_on_layout_change_block = nil
  TSApi.tsapi_unsetLayoutChangedCallback
end

.cancel_on_space_changeObject

Cancel the on_space_change notification.



287
288
289
290
# File 'lib/totalspaces.rb', line 287

def cancel_on_space_change
  $tsapi_on_space_change_block = nil
  TSApi.tsapi_unsetSpaceWillChangeCallback
end

.current_spaceObject

Returns the number of the current space. Numbering starts at 1, except if you have the Dashboard enabled as a space, in which case the Dashboard counts as space 0

puts "Current space number: #{TotalSpaces.current_space}"


148
149
150
# File 'lib/totalspaces.rb', line 148

def current_space
  TSApi.tsapi_currentSpaceNumber
end

.dashboard_is_a_space?Boolean

Returns true if the dashboard is configured to appear as a space in Mission Control preferences.

puts "Dashboard is a space: #{TotalSpaces.dashboard_is_a_space?}"

Returns:

  • (Boolean)


204
205
206
# File 'lib/totalspaces.rb', line 204

def dashboard_is_a_space?
  TSApi.tsapi_dashboardIsASpace
end

.grid_columnsObject

Returns the number of columns defined in TotalSpaces

puts "Number of columns: #{TotalSpaces.grid_columns}"


220
221
222
# File 'lib/totalspaces.rb', line 220

def grid_columns
  TSApi.tsapi_definedColumns
end

.grid_rowsObject

Returns the number of rows defined in TotalSpaces

puts "Number of rows: #{TotalSpaces.grid_rows}"


212
213
214
# File 'lib/totalspaces.rb', line 212

def grid_rows
  TSApi.tsapi_definedRows
end

.lib_total_spaces_versionObject

Returns the version of the dylib, a string such as “1.0” You should be using the same dylib version as that returned by the api_version call

puts "libTotalSpaces version: #{TotalSpaces.lib_total_spaces_version}"

if TotalSpaces.lib_total_spaces_version != TotalSpaces.api_version
  puts "Comms error!"
  exit(1)
end


117
118
119
# File 'lib/totalspaces.rb', line 117

def lib_total_spaces_version
  string_and_free(TSApi.tsapi_libTotalSpacesVersion)
end

.move_space_to_position(space_number, position_number) ⇒ Object

Move space to a new position You cannot move a space to position 1, and you cannot move the first space anywhere else - it is fixed. You cannot move full screen apps around with this method, only normal desktops Returns false if the space_number or position_number is not valid.

TotalSpaces.move_space_to_position(4, 2)


374
375
376
# File 'lib/totalspaces.rb', line 374

def move_space_to_position(space_number, position_number)
  TSApi.tsapi_moveSpaceToPosition(space_number, position_number)
end

.move_to_space(space_number) ⇒ Object

Command TotalSpaces to switch to the given space number. Returns false if the space number was invalid. The on_space_change notification will be sent.

TotalSpaces.move_to_space(1)


254
255
256
# File 'lib/totalspaces.rb', line 254

def move_to_space(space_number)
  TSApi.tsapi_moveToSpace(space_number)
end

.move_window_to_space(window_id, space_number) ⇒ Object

Move a window to a given space The window_id parameter must be fetched using window_list. Returns false if the space_number or window_id is invalid.



362
363
364
# File 'lib/totalspaces.rb', line 362

def move_window_to_space(window_id, space_number)
  TSApi.tsapi_moveWindowToSpace(window_id, space_number)
end

.name_for_space(space_number) ⇒ Object

Returns the name for a space. The returned string will be empty if the space number is not valid

current_space = TotalSpaces.current_space
puts "Current space is called: #{TotalSpaces.name_for_space(current_space)}"


158
159
160
161
# File 'lib/totalspaces.rb', line 158

def name_for_space(space_number)
  name = string_and_free(TSApi.tsapi_spaceNameForSpaceNumber(space_number))
  name.force_encoding("UTF-8")
end

.number_of_desktopsObject

Returns the number of desktops that are present in the system. This may be a bigger number that the rows x columns in the grid if more desktops have been created in Mission Control.

puts "Number of desktops: #{TotalSpaces.number_of_desktops}"


196
197
198
# File 'lib/totalspaces.rb', line 196

def number_of_desktops
  TSApi.tsapi_numberOfDesktops
end

.number_of_fullscreensObject

Returns the number of fullscreen apps present

puts "Number of fullscreens: #{TotalSpaces.number_of_fullscreens}"


176
177
178
# File 'lib/totalspaces.rb', line 176

def number_of_fullscreens
  TSApi.tsapi_numberOfFullScreens
end

.number_of_fullscreens_in_gridObject

Returns the number of fullscreen apps tht are defined in the grid - this can be defined in Advanced preferences in TotalSpaces. The return value does not depend on how many fullscreens actually exist in the grid - the value is the definition only, there could be fewer than this actually present.

puts "Number of fullscreens in the grid: #{TotalSpaces.number_of_fullscreens_in_grid}"


187
188
189
# File 'lib/totalspaces.rb', line 187

def number_of_fullscreens_in_grid
  TSApi.tsapi_numberOfFullScreensInGrid
end

.number_of_spacesObject

Returns the total number of spaces including fullscreens, dashboard (if it’s a space), and spaces that are unused in the grid

puts "Total number of spaces: #{TotalSpaces.number_of_spaces}"


168
169
170
# File 'lib/totalspaces.rb', line 168

def number_of_spaces
  TSApi.tsapi_numberOfSpaces
end

.on_layout_change(&block) ⇒ Object

Register for notifications on layout change. The given block will be called whenever the layout changes - this could be due to making an app fullscreen, changing a space name, or changing the layout of the TotalSpaces grid. There are no arguments passed to the block.

TotalSpaces.on_layout_change {puts "Spaces changed"}

When you get a notification from this method, you should re-fetch any information about the spaces that you may be storing.

There can only be one block registered at any time, the most recently registered one will be called.



305
306
307
308
# File 'lib/totalspaces.rb', line 305

def on_layout_change(&block)
  $tsapi_on_layout_change_block = block  # prevent GC
  TSApi.tsapi_setLayoutChangedCallback(block)
end

.on_space_change(&block) ⇒ Object

Register for notifications on space change. The given block will be called whenever you move from one space to another. The arguments are the space number you moved from, and the one you are moving to.

TotalSpaces.on_space_change {|from, to| puts "Moving from space #{from} to space #{to}";}

There can only be one block registered at any time, the most recently registered one will be called. This callback is called just before the space actually changes - current_space will still report the from space.



280
281
282
283
# File 'lib/totalspaces.rb', line 280

def on_space_change(&block)
  $tsapi_on_space_change_block = block  # prevent GC
  TSApi.tsapi_setSpaceWillChangeCallback(block)
end

.remove_desktops(number_to_remove) ⇒ Object

Remove desktops The highest numbered desktops are removed. Removing a desktop you are currently on will result in TotalSpaces switching to another dektop. Any windows present on a desktop being removed will be moved to one of the remaining desktops. Returns true on success, false if number_to_remove was zero or would result in less than 1 desktop remaining. The on_layout_change notification will be sent if a change was made.

TotalSpaces.remove_desktops(1)



402
403
404
# File 'lib/totalspaces.rb', line 402

def remove_desktops(number_to_remove)
  TSApi.tsapi_removeDesktops(number_to_remove)
end

.set_grid_columns(columns) ⇒ Object

Sets the number of columns defined in TotalSpaces.

This does not change the actual number of desktops present, you should call add_desktops or remove_desktops as appropriate after changing the number of columns.

TotalSpaces.set_grid_columns(3)


244
245
246
# File 'lib/totalspaces.rb', line 244

def set_grid_columns(columns)
  TSApi.tsapi_setDefinedColumns(columns)
end

.set_grid_rows(rows) ⇒ Object

Sets the number of rows defined in TotalSpaces.

This does not change the actual number of desktops present, you should call add_desktops or remove_desktops as appropriate after changing the number of rows.

TotalSpaces.set_grid_rows(3)


232
233
234
# File 'lib/totalspaces.rb', line 232

def set_grid_rows(rows)
  TSApi.tsapi_setDefinedRows(rows)
end

.set_name_for_space(space_number, name) ⇒ Object

Set the name for a space. Note that using this command will cause a layout notification to be sent. if the new name was different from that previously set. The maximum length for a name is 255 bytes.

TotalSpaces.set_name_for_space(1, "Home")


265
266
267
# File 'lib/totalspaces.rb', line 265

def set_name_for_space(space_number, name)
  TSApi.tsapi_setNameForSpace(space_number, name)
end

.total_spaces_versionObject

Returns the version of TotalSpaces running on the system, a string such as “1.1.4”

puts "TotalSpaces version: #{TotalSpaces.total_spaces_version}"


139
140
141
# File 'lib/totalspaces.rb', line 139

def total_spaces_version
  string_and_free(TSApi.tsapi_totalSpacesVersion)
end

.window_listObject

Get a list of all the windows on your mac It returns an array containing a hash for each space. The hash contains the space number (key :space_number) and an array of hashes, one for each window (key :windows). The windows are in front to back order. Each window hash contains a window_id, title, frame, app_name and is_on_all_spaces flag

The below example would move the frontmost window to the next space to the right.

windows = TotalSpaces.window_list
if !windows.empty?
  current_space_windows = windows[TotalSpaces.current_space - 1]
  front_window = current_space_windows[:windows][0]
  TotalSpaces.move_window_to_space(front_window[:window_id], TotalSpaces.current_space + 1)
end


332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'lib/totalspaces.rb', line 332

def window_list
  result = []
  list = TSApi.tsapi_windowList
  main_array = Spaces.new(list)

  (0...main_array[:count]).each do |n|
    result[n] = {}
    windows_array = Space.new(main_array[:windows_arrays] + n * Space.size)
    result[n][:space_number] = windows_array[:space_number]
    result[n][:windows] = []
    (0...windows_array[:count]).each do |m|
      window_hash = result[n][:windows][m] = {}
      window = Window.new(windows_array[:windows_array] + m * Window.size)
      window_hash[:window_id] = window[:window_id]
      window_hash[:title] = window[:title].dup.force_encoding("UTF-8")
      window_hash[:frame] = window[:frame].dup.force_encoding("UTF-8")
      window_hash[:is_on_all_spaces] = window[:is_on_all_spaces]
      window_hash[:app_name] = window[:app_name].dup.force_encoding("UTF-8")
    end
  end
  
  TSApi.tsapi_freeWindowList(list)

  result
end