Module: TotalSpaces2

Defined in:
lib/totalspaces2.rb

Defined Under Namespace

Classes: Display, Displays, Window, Windows

Constant Summary collapse

MAX_DESKTOPS =
16

Class Method Summary collapse

Class Method Details

.add_desktops(number_to_add) ⇒ Object

Add desktops There can be at most 16 desktops unless the display has collected some when a secondary display has been unplugged. 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.

TotalSpaces2.add_desktops(1)


569
570
571
# File 'lib/totalspaces2.rb', line 569

def add_desktops(number_to_add)
  TSApi.tsapi_addDesktopsOnDisplay(number_to_add, 0)
end

.add_desktops_on_display(number_to_add, display_id) ⇒ Object

Add desktops There can be at most 16 desktops unless the display has collected some when a secondary display has been unplugged. 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.

display_id = TotalSpaces2.main_display[:display_id]
TotalSpaces2.add_desktops_on_display(1, display_id)


583
584
585
# File 'lib/totalspaces2.rb', line 583

def add_desktops_on_display(number_to_add, display_id)
  TSApi.tsapi_addDesktopsOnDisplay(number_to_add, display_id)
end

.api_versionObject

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

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

 if TotalSpaces2.lib_total_spaces_version.split('.')[0] != TotalSpaces2.api_version.split('.')[0]
  puts "Comms error!"
  exit(1)
end


208
209
210
# File 'lib/totalspaces2.rb', line 208

def api_version
  string_and_free(TSApi.tsapi_apiVersion)
end

.bind_app_to_space(bundle_id, space_uuid) ⇒ Object

Bind an app to a space. The bundle_id is normally in the format “com.apple.mail” Setting the space_uuid to AllSpaces will result in an app appearing on every desktop. Setting the space_uuid to nil will delete the setting for the given bundle_id.

TotalSpaces2.bind_app_to_space("com.apple.mail", "AllSpaces")


650
651
652
# File 'lib/totalspaces2.rb', line 650

def bind_app_to_space(bundle_id, space_uuid)
  TSApi.tsapi_bindAppToSpace(bundle_id, space_uuid)
end

.cancel_on_layout_changeObject

Cancel the layout change notification



462
463
464
465
# File 'lib/totalspaces2.rb', line 462

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.



434
435
436
437
# File 'lib/totalspaces2.rb', line 434

def cancel_on_space_change
  $tsapi_on_space_change_block = nil
  TSApi.tsapi_unsetSpaceWillChangeCallback
end

.current_spaceObject

Returns the number of the current space on the main display. Numbering starts at 1.

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


251
252
253
# File 'lib/totalspaces2.rb', line 251

def current_space
  TSApi.tsapi_currentSpaceNumberOnDisplay(0)
end

.current_space_on_display(display_id) ⇒ Object

Returns the number of the current space on the given display. Space numbering starts at 1.

display_id = TotalSpaces2.displays[0]
puts "Current space number: #{TotalSpaces2.current_space_on_display(display_id)}"


261
262
263
# File 'lib/totalspaces2.rb', line 261

def current_space_on_display(display_id)
  TSApi.tsapi_currentSpaceNumberOnDisplay(display_id)
end

.display_listObject

Returns an array of hashes with information about attached displays. The ids returned from this call can be used where a display id is required in the other calls in this library.

puts "Attached displays: #{TotalSpaces2.display_list}"

[{:display_id=>69679040, :display_name=>"Color LCD", :width=>1440, :height=>900}, 
{:display_id=>69514913, :display_name=>"LED Cinema Display", :width=>2560, :height=>1440}]


228
229
230
231
232
233
234
# File 'lib/totalspaces2.rb', line 228

def display_list
  list = TSApi.tsapi_displayList
  displays = Displays.new(list)
  result = displays.null? ? [] : displays.display_info
  TSApi.tsapi_freeDisplayList(list)
  result
end

.grid_columnsObject

Returns the number of columns defined in TotalSpaces2 for the main display

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


332
333
334
# File 'lib/totalspaces2.rb', line 332

def grid_columns
  TSApi.tsapi_definedColumnsOnDisplay(0)
end

.grid_columns_on_display(display_id) ⇒ Object

Returns the number of columns defined in TotalSpaces2

display_id = TotalSpaces2.main_display[:display_id]
puts "Number of columns: #{TotalSpaces2.grid_columns_on_display(display_id)}"


341
342
343
# File 'lib/totalspaces2.rb', line 341

def grid_columns_on_display(display_id)
  TSApi.tsapi_definedColumnsOnDisplay(display_id)
end

.lib_total_spaces_versionObject

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

puts "libTotalSpaces2 version: #{TotalSpaces2.lib_total_spaces_version}"

if TotalSpaces2.lib_total_spaces_version.split('.')[0] != TotalSpaces2.api_version.split('.')[0]
  puts "Comms error!"
  exit(1)
end


194
195
196
# File 'lib/totalspaces2.rb', line 194

def lib_total_spaces_version
  string_and_free(TSApi.tsapi_libTotalSpacesVersion)
end

.main_displayObject

Returns information about the main display. Methods that do not take a display id always operate on this display.

puts "Main display id: #{TotalSpaces2.main_display_id}"

{:display_id=>69679040, :display_name=>"Color LCD", :width=>1440, :height=>900}


243
244
245
# File 'lib/totalspaces2.rb', line 243

def main_display
  self.display_list[0]
end

.move_space_on_display_to_position_on_display(space_number, from_display_id, position_number, to_display_id) ⇒ Object

Move space to a new position on another screen. This won’t work if you do not have displays have separate spaces enabled.

Returns false if any parameters are not valid.

display_id = TotalSpaces2.main_display[:display_id]
display2_id = TotalSpaces2.display_list[1][:display_id]
TotalSpaces2.move_space_on_display_to_position_on_display(2, display_id, 1, display2_id)


556
557
558
# File 'lib/totalspaces2.rb', line 556

def move_space_on_display_to_position_on_display(space_number, from_display_id, position_number, to_display_id)
  TSApi.tsapi_moveSpaceOnDisplayToPositionOnDisplay(space_number, from_display_id, position_number, to_display_id)
end

.move_space_to_position(space_number, position_number) ⇒ Object

Move space to a new position in the grid on the main display.

Returns false if the space_number or position_number is not valid.

TotalSpaces2.move_space_to_position(4, 2)


531
532
533
# File 'lib/totalspaces2.rb', line 531

def move_space_to_position(space_number, position_number)
  TSApi.tsapi_moveSpaceToPositionOnDisplay(space_number, position_number, 0)
end

.move_space_to_position_on_display(space_number, position_number, display_id) ⇒ Object

Move space to a new position in the grid. Spaces can only be moved within their own display.

Returns false if the space_number or position_number is not valid.

display_id = TotalSpaces2.main_display[:display_id]
TotalSpaces2.move_space_to_position_on_display(4, 2, display_id)


543
544
545
# File 'lib/totalspaces2.rb', line 543

def move_space_to_position_on_display(space_number, position_number, display_id)
  TSApi.tsapi_moveSpaceToPositionOnDisplay(space_number, position_number, display_id)
end

.move_to_space(space_number) ⇒ Object

Command TotalSpaces2 to switch to the given space number on the main display. Returns false if the space number was invalid. The on_space_change notification will be sent.

TotalSpaces2.move_to_space(1)


376
377
378
# File 'lib/totalspaces2.rb', line 376

def move_to_space(space_number)
  TSApi.tsapi_moveToSpaceOnDisplay(space_number, 0)
end

.move_to_space_on_display(space_number, display_id) ⇒ Object

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

display_id = TotalSpaces2.main_display[:display_id]
TotalSpaces2.move_to_space_on_Display(1, display_id)


387
388
389
# File 'lib/totalspaces2.rb', line 387

def move_to_space_on_display(space_number, display_id)
  TSApi.tsapi_moveToSpaceOnDisplay(space_number, display_id)
end

.move_window(window_id, x, y) ⇒ Object

Move a particular window to a new position. Use the origin from the frame given by window_list as the starting point to make adustments. There is no validation, you can place a window far off the screen if you wish.

For instance, if the frame or window id 123 is “23, 754}”, the origin is (146, 23). To move the window down 20 pixels, you would do this:

TotalSpaces2.move_window(123, 146, 43)


637
638
639
# File 'lib/totalspaces2.rb', line 637

def move_window(window_id, x, y)
  TSApi.tsapi_moveWindow(window_id, x, y)
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.



513
514
515
# File 'lib/totalspaces2.rb', line 513

def move_window_to_space(window_id, space_number)
  TSApi.tsapi_moveWindowToSpaceOnDisplay(window_id, space_number, 0)
end

.move_window_to_space_on_display(window_id, space_number, display_id) ⇒ Object

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



521
522
523
# File 'lib/totalspaces2.rb', line 521

def move_window_to_space_on_display(window_id, space_number, display_id)
  TSApi.tsapi_moveWindowToSpaceOnDisplay(window_id, space_number, display_id)
end

.name_for_space(space_number) ⇒ Object

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

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


271
272
273
274
# File 'lib/totalspaces2.rb', line 271

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

.name_for_space_on_display(space_number, display_id) ⇒ Object

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

current_space = TotalSpaces2.current_space
display_id = TotalSpaces2.main_display[:display_id]
puts "Current space is called: #{TotalSpaces2.name_for_space_on_display(current_space, display_id)}"


283
284
285
286
# File 'lib/totalspaces2.rb', line 283

def name_for_space_on_display(space_number, display_id)
  name = string_and_free(TSApi.tsapi_spaceNameForSpaceNumberOnDisplay(space_number, display_id))
  name.force_encoding("UTF-8")
end

.number_of_spacesObject

Returns the total number of spaces including fullscreens, dashboard (if it’s a space).

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


315
316
317
# File 'lib/totalspaces2.rb', line 315

def number_of_spaces
  TSApi.tsapi_numberOfSpacesOnDisplay(0)
end

.number_of_spaces_on_display(display_id) ⇒ Object

Returns the total number of spaces including fullscreens, dashboard (if it’s a space).

display_id = TotalSpaces2.main_display[:display_id]
puts "Total number of spaces: #{TotalSpaces2.number_of_spaces_on_display(display_id)}"


324
325
326
# File 'lib/totalspaces2.rb', line 324

def number_of_spaces_on_display(display_id)
  TSApi.tsapi_numberOfSpacesOnDisplay(display_id)
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 TotalSpaces2 grid. There are no arguments passed to the block.

TotalSpaces2.on_layout_change {puts "Spaces changed"}

sleep

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.



455
456
457
458
# File 'lib/totalspaces2.rb', line 455

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.

TotalSpaces2.on_space_change {|from, to, displayID| puts "Moving from space #{from} to space #{to}"}

sleep

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.



427
428
429
430
# File 'lib/totalspaces2.rb', line 427

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 TotalSpaces2 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.

TotalSpaces2.remove_desktops(1)


599
600
601
# File 'lib/totalspaces2.rb', line 599

def remove_desktops(number_to_remove)
  TSApi.tsapi_removeDesktopsOnDisplay(number_to_remove, 0)
end

.remove_desktops_on_display(number_to_remove, display_id) ⇒ Object

Remove desktops The highest numbered desktops are removed. Removing a desktop you are currently on will result in TotalSpaces2 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.

display_id = TotalSpaces2.main_display[:display_id]
TotalSpaces2.remove_desktops_on_display(1, display_id)


616
617
618
# File 'lib/totalspaces2.rb', line 616

def remove_desktops_on_display(number_to_remove, display_id)
  TSApi.tsapi_removeDesktopsOnDisplay(number_to_remove, display_id)
end

.set_front_window(window_id) ⇒ Object

Move a particular window to the front and activate it. This might be usful after moving windows to other desktops.



623
624
625
# File 'lib/totalspaces2.rb', line 623

def set_front_window(window_id)
  TSApi.tsapi_setFrontWindow(window_id)
end

.set_grid_columns(columns) ⇒ Object

Sets the number of columns defined in TotalSpaces2 for the main display.

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.

TotalSpaces2.set_grid_columns(3)


353
354
355
# File 'lib/totalspaces2.rb', line 353

def set_grid_columns(columns)
  TSApi.tsapi_setDefinedColumnsOnDisplay(columns, 0)
end

.set_grid_columns_on_display(columns, display_id) ⇒ Object

Sets the number of columns defined in TotalSpaces2.

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

display_id = TotalSpaces2.main_display[:display_id]
TotalSpaces2.set_grid_columns_on_display(3, display_id)


366
367
368
# File 'lib/totalspaces2.rb', line 366

def set_grid_columns_on_display(columns, display_id)
  TSApi.tsapi_setDefinedColumnsOnDisplay(columns, display_id)
end

.set_name_for_space(space_number, name) ⇒ Object

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

TotalSpaces2.set_name_for_space(1, "Home")


398
399
400
# File 'lib/totalspaces2.rb', line 398

def set_name_for_space(space_number, name)
  TSApi.tsapi_setNameForSpaceOnDisplay(space_number, name, 0)
end

.set_name_for_space_on_display(space_number, name, display_id) ⇒ Object

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

display_id = TotalSpaces2.main_display[:display_id]
TotalSpaces2.set_name_for_space_on_display(1, "Home", display_id)


410
411
412
# File 'lib/totalspaces2.rb', line 410

def set_name_for_space_on_display(space_number, name, display_id)
  TSApi.tsapi_setNameForSpaceOnDisplay(space_number, name, display_id)
end

.total_spaces_versionObject

Returns the version of TotalSpaces2 running on the system, a string such as “2.0.12”

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


216
217
218
# File 'lib/totalspaces2.rb', line 216

def total_spaces_version
  string_and_free(TSApi.tsapi_totalSpacesVersion)
end

.uuid_for_space(space_number) ⇒ Object

Returns the uuid for a space on the main display. The returned string will be empty if the space number is not valid.

current_space = TotalSpaces2.current_space
puts "Current space uuid is: #{TotalSpaces2.uuid_for_space(current_space)}"


294
295
296
297
# File 'lib/totalspaces2.rb', line 294

def uuid_for_space(space_number)
  uuid = string_and_free(TSApi.tsapi_uuidForSpaceNumberOnDisplay(space_number, 0))
  uuid.force_encoding("UTF-8")
end

.uuid_for_space_on_display(space_number, display_id) ⇒ Object

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

current_space = TotalSpaces2.current_space
display_id = TotalSpaces2.main_display[:display_id]
puts "Current space uuid is: #{TotalSpaces2.uuid_for_space_on_display(current_space, display_id)}"


306
307
308
309
# File 'lib/totalspaces2.rb', line 306

def uuid_for_space_on_display(space_number, display_id)
  uuid = string_and_free(TSApi.tsapi_uuidForSpaceNumberOnDisplay(space_number, display_id))
  uuid.force_encoding("UTF-8")
end

.window_listObject

Get a list of all the windows on your mac It returns an array containing a hash for each window. The hash contains the display id (key :display_id) and space number (key :space_number) and details for each window. The windows are in front to back order within each space. Each window hash also 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 = TotalSpaces2.window_list
current_space = TotalSpaces2.current_space
main_display_id = TotalSpaces2.main_display[:display_id]
if !windows.empty?
  current_space_windows = windows.select {|window| window[:display_id] == main_display_id 
                                                   && window[:space_number] == current_space}
  front_window = current_space_windows[0]
  TotalSpaces2.move_window_to_space(front_window[:window_id], TotalSpaces.current_space + 1)
end


486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
# File 'lib/totalspaces2.rb', line 486

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

  (0...main_array[:count]).each do |n|
    window = Window.new(main_array[:windows_array] + n * Window.size)
    window_hash = {}
    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")
    window_hash[:display_id] = window[:display_id]
    window_hash[:space_number] = window[:space_number]
    result << window_hash
  end
  
  TSApi.tsapi_freeWindowList(list)

  result
end