totalspaces2 2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a133c5d3f23844aa9ca70332146796499c6e3b9e
4
+ data.tar.gz: 342ceaf3ec96f133b4e6b0a06e8f1a7400c24a4c
5
+ SHA512:
6
+ metadata.gz: 4455a450a3c33fa50fce7162d9ebca2285fcb10d1828132cdbbf99d9aa2c36f02f6e01d354a0efd6f58f89bb749429e35b400e7ad48ec1dedb79d8cac14d7ac6
7
+ data.tar.gz: 2f025c0a21fc74d0f166ed95d7cb0bab5c0d1ec955a7ce743a0e5893267353f7e0d01a31446d36c3f232bd73fec51bd785dc48f0aefe66ee073759f479d70408
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Stephen Sykes
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,65 @@
1
+ = TotalSpaces2 - Ruby API bindings for TotalSpaces2 from BinaryAge
2
+
3
+ == PRERELEASE: You will be able to use the API with versions 2.1 and above of totalspaces.
4
+
5
+ This gem enables you to get information from and to control {TotalSpaces2}[link:http://totalspaces.binaryage.com]
6
+
7
+ It is the officially supported way of using the API library libtotalspaces2api, and the required dylib
8
+ comes bundled with this gem. This gem uses {Ruby-FFI}[link:https://github.com/ffi/ffi] to call the functions in the dylib.
9
+ You'll need a sane ruby and compilation environment to install ruby-ffi - it probably won't install immediately with the
10
+ ruby that comes with Mavericks because none of the compilation tools are present. We use {homebrew}[link:http://mxcl.github.com/homebrew/]
11
+ and {rbenv}[link:https://github.com/sstephenson/rbenv/] to manage our ruby scripting environment.
12
+
13
+ You may use this gem in various ways. For instance, you could:
14
+
15
+ * Display a message or alert when a particular space is moved to
16
+
17
+ * Automatically change the name of spaces depending on what apps are in them
18
+
19
+ * Record which spaces certain windows are on, and restoring those windows to those spaces when the owning app restarts
20
+
21
+ * Trigger moving certain windows between spaces
22
+
23
+ API support, and support for this gem starts with TotalSpaces2 v2.0.12 The API is a premium feature,
24
+ and will only work with registered versions of TotalSpaces2.
25
+
26
+ == Download and installation
27
+
28
+ The latest version of the TotalSpaces2 gem can be installed with RubyGems:
29
+
30
+ % [sudo] gem install totalspaces2
31
+
32
+ Source code can be downloaded on GitHub
33
+
34
+ * https://github.com/binaryage/totalspaces2-api
35
+
36
+
37
+ == Documentation
38
+
39
+ {module TotalSpaces2}[link:http://binaryage.github.io/totalspaces2-api/ruby/rdoc/TotalSpaces2.html]
40
+
41
+ == Examples
42
+ require 'totalspaces2'
43
+
44
+ TotalSpaces2.on_space_change {|from, to, display_id| puts "Moving from space #{from} to space #{to}";}
45
+
46
+ TotalSpaces2.move_to_space(1)
47
+
48
+ current_space = TotalSpaces2.current_space
49
+ puts "Current space number: #{current_space}"
50
+ puts "Current space is called: #{TotalSpaces2.name_for_space(current_space)}"
51
+
52
+ TotalSpaces2.set_name_for_space(1, "Home")
53
+
54
+ == License
55
+
56
+ The TotalSpaces2 gem is released under the MIT license:
57
+
58
+ * http://www.opensource.org/licenses/MIT
59
+
60
+ The source code of the dylib is not available at this time.
61
+
62
+
63
+ == Support and feature requests
64
+
65
+ * http://discuss.binaryage.com
@@ -0,0 +1,256 @@
1
+ //
2
+ // TSLib.h
3
+ // totalspacesapi
4
+ //
5
+ // Created by Stephen Sykes on 27/1/13.
6
+ // Copyright (c) 2013 Stephen Sykes. All rights reserved.
7
+ //
8
+ // The API is a premium feature, and will only work with registered versions of TotalSpaces.
9
+ //
10
+
11
+ #ifndef totalspacesapi_tslib
12
+ #define totalspacesapi_tslib_h
13
+
14
+ #import <Foundation/Foundation.h>
15
+
16
+ #define TSAPI_MAX_SPACES 32
17
+
18
+ /*
19
+ * In case of comm error, all the functions apart from tsapi_libTotalSpacesVersion() will
20
+ * return an empty string, zero, false or a pointer to a struct containing zero spaces (in
21
+ * the case of tsapi_windowList).
22
+ * It is recommended to check that comms to TotalSpaces are working by, for instance,
23
+ * checking that tsapi_apiVersion() matches tsapi_libTotalSpacesVersion() when you initialize
24
+ * your app.
25
+ *
26
+ * Some actions such as renaming a space will cause the overview grid to be exited if it
27
+ * is showing at the time.
28
+ */
29
+
30
+ /*
31
+ * The version of the API present in TotalSpaces.app.
32
+ *
33
+ * You must call tsapi_freeString when you have finished with the returned string.
34
+ */
35
+ const char *tsapi_apiVersion();
36
+
37
+ /*
38
+ * The version number of TotalSpaces itself.
39
+ *
40
+ * You must call tsapi_freeString when you have finished with the returned string.
41
+ */
42
+ const char *tsapi_totalSpacesVersion();
43
+
44
+ /*
45
+ * The version of the API dylib. This should match the string returned
46
+ * by tsapi_apiVersion().
47
+ *
48
+ * You must call tsapi_freeString when you have finished with the returned string.
49
+ */
50
+ const char *tsapi_libTotalSpacesVersion();
51
+
52
+ /*
53
+ * Struct containing info about a display.
54
+ */
55
+ struct tsapi_display {
56
+ CGDirectDisplayID displayId;
57
+ char *displayName;
58
+ size_t width;
59
+ size_t height;
60
+ };
61
+
62
+ /*
63
+ * Struct containing the count of spaces and a pointer to an
64
+ * array of CGDirectDisplayIDs.
65
+ */
66
+ struct tsapi_displays {
67
+ unsigned int displaysCount;
68
+ struct tsapi_display *displays;
69
+ };
70
+
71
+ /*
72
+ * Return a pointer to a tsapi_displays struct containing information about all the displays.
73
+ *
74
+ * The first display in the list will be the main display. The main display is the display
75
+ * with its screen location at (0,0) in the global display coordinate space. In a system
76
+ * without display mirroring, the display with the menu bar is typically the main display.
77
+ *
78
+ * You must call tsapi_freeDisplayList when you have finished with this.
79
+ */
80
+ struct tsapi_displays *tsapi_displayList();
81
+
82
+ /*
83
+ * Free a previously returned tsapi_displays struct
84
+ */
85
+ void tsapi_freeDisplayList(struct tsapi_displays *displayList);
86
+
87
+ /*
88
+ * The number of the current space.
89
+ *
90
+ * If the current space is the dashboard, 0 is returned.
91
+ */
92
+ unsigned int tsapi_currentSpaceNumberOnDisplay(CGDirectDisplayID displayID);
93
+
94
+ /*
95
+ * The name for the given space number.
96
+ *
97
+ * You must call tsapi_freeString when you have finished with the returned string.
98
+ */
99
+ const char *tsapi_spaceNameForSpaceNumberOnDisplay(unsigned int spaceNumber, CGDirectDisplayID displayID);
100
+
101
+ /*
102
+ * The total number of spaces.
103
+ * This includes the dashboard if you have it set as a space, and any
104
+ * fullscreen apps.
105
+ */
106
+ unsigned int tsapi_numberOfSpacesOnDisplay(CGDirectDisplayID displayID);
107
+
108
+ /*
109
+ * The number of columns defined in TotalSpaces layout preferences.
110
+ */
111
+ unsigned int tsapi_definedColumnsOnDisplay(CGDirectDisplayID displayID);
112
+
113
+ /*
114
+ * Sets the number of columns in the TotalSpaces grid.
115
+ * Returns true on success, false if the new grid would exceed TSAPI_MAX_SPACES
116
+ * or if columns is zero.
117
+ * Note that the actual number of desktops present in the system is unchanged,
118
+ * you should call tsapi_addDesktops or tsapi_removeDesktops after calling this
119
+ * function.
120
+ */
121
+ bool tsapi_setDefinedColumnsOnDisplay(unsigned int columns, CGDirectDisplayID displayID);
122
+
123
+ /*
124
+ * Call this to free strings returned by the TotalSpaces API.
125
+ */
126
+ void tsapi_freeString(char *str);
127
+
128
+ /*
129
+ * Switch the display to the given space.
130
+ * Returns false if the space number is invalid.
131
+ */
132
+ bool tsapi_moveToSpaceOnDisplay(unsigned int spaceNumber, CGDirectDisplayID displayID);
133
+
134
+ /*
135
+ * Set the name of a space.
136
+ * The maximum length is 255 bytes. The name should be in UTF-8.
137
+ * Returns true on success, false if the name was too long or the space number was invalid.
138
+ */
139
+ bool tsapi_setNameForSpaceOnDisplay(unsigned int spaceNumber, char *name, CGDirectDisplayID displayID);
140
+
141
+ /*
142
+ * Type for space change callback.
143
+ */
144
+ typedef void (*space_change_callback_t)(unsigned int fromSpaceNumber, unsigned int toSpaceNumber, CGDirectDisplayID displayID);
145
+
146
+ /*
147
+ * Set the function that will be called when the visible space changes.
148
+ * There is only one callback per process, registering a new callback will supercede any previous one.
149
+ */
150
+ void tsapi_setSpaceWillChangeCallback(space_change_callback_t callback);
151
+
152
+ /*
153
+ * Cancel space change callbacks
154
+ */
155
+ void tsapi_unsetSpaceWillChangeCallback();
156
+
157
+ /*
158
+ * Type for layout change callback
159
+ */
160
+ typedef void (*space_layout_changed_callback_t)(void);
161
+
162
+ /*
163
+ * Set the function that will be called when the layout changes.
164
+ * This could be any change - for instance adding or removing a fullscreen, changing the name of a space,
165
+ * or a change of rows or columns.
166
+ * It indicates that you should re-request any information you are holding on the spaces.
167
+ * There is only one callback per process, registering a new callback will supercede any previous one.
168
+ */
169
+ void tsapi_setLayoutChangedCallback(space_layout_changed_callback_t callback);
170
+
171
+ /*
172
+ * Cancel layout change callbacks.
173
+ */
174
+ void tsapi_unsetLayoutChangedCallback();
175
+
176
+ /*
177
+ * Struct containing information about a window.
178
+ */
179
+ struct tsapi_window {
180
+ char *appName;
181
+ unsigned int windowId;
182
+ bool isOnAllSpaces;
183
+ char *title;
184
+ char *frame;
185
+ CGDirectDisplayID displayID;
186
+ unsigned int spaceNumber;
187
+ };
188
+
189
+ /*
190
+ * Struct containing information about windows.
191
+ * Contains a pointer to an array of tsapi_window structs.
192
+ */
193
+ struct tsapi_windows {
194
+ unsigned int windowCount;
195
+ struct tsapi_window *windows;
196
+ };
197
+
198
+ /*
199
+ * Return a pointer to a tsapi_windows struct containing information about all the windows
200
+ * in all spaces.
201
+ *
202
+ * The windows are listed in space order for each display, and within each space
203
+ * the windows are listed front to back, so earlier windows in the array are frontmost.
204
+ *
205
+ * You must call tsapi_freeWindowList when you have finished with this.
206
+ */
207
+ struct tsapi_windows *tsapi_windowList();
208
+
209
+ /*
210
+ * Free a previously returned tsapi_spaces struct
211
+ */
212
+ void tsapi_freeWindowList(struct tsapi_windows *windowList);
213
+
214
+ /*
215
+ * Move a window to a different space
216
+ * The windowId must be one that has been returned in a tsapi_window struct
217
+ *
218
+ * Returns true on success, false if the windowID or spaceNumber was invalid
219
+ */
220
+ bool tsapi_moveWindowToSpaceOnDisplay(unsigned int windowID, unsigned int spaceNumber, CGDirectDisplayID displayID);
221
+
222
+ /*
223
+ * Move a space to another position
224
+ * You cannot move space 1 when displays have separate spaces is turned off.
225
+ *
226
+ * Returns true on success, false if the spaceNumber or positionNumber was
227
+ * invalid
228
+ */
229
+ bool tsapi_moveSpaceToPositionOnDisplay(unsigned int spaceNumber, unsigned int positionNumber, CGDirectDisplayID displayID);
230
+
231
+ /*
232
+ * Add desktops
233
+ * There can usually be at most 16 desktops, unless desktops have migrated
234
+ * from another monitor.
235
+ *
236
+ * Returns the number of desktops actually added.
237
+ */
238
+ unsigned int tsapi_addDesktopsOnDisplay(unsigned int numberToAdd, CGDirectDisplayID displayID);
239
+
240
+ /*
241
+ * Remove desktops
242
+ * Removes numberToRemove desktops. The highest numbered desktops are removed.
243
+ *
244
+ * Removing a desktop you are currently on will result in TotalSpaces switching to
245
+ * another dektop.
246
+ *
247
+ * Any windows present on a desktop being removed will be moved to one of the
248
+ * remaining desktops.
249
+ *
250
+ * Returns true on success, false if numberToRemove was zero or would result in less
251
+ * than 1 desktop remaining.
252
+ */
253
+ bool tsapi_removeDesktopsOnDisplay(unsigned int numberToRemove, CGDirectDisplayID displayID);
254
+
255
+ #endif
256
+
@@ -0,0 +1,575 @@
1
+ # = TotalSpaces2 - Ruby API bindings for TotalSpaces2 from BinaryAge
2
+ #
3
+ # This gem enables you to get information from and to control {TotalSpaces2}[link:http://totalspaces.binaryage.com]
4
+ #
5
+ # It is the officially supported way of using the API library libtotalspaces2api, and the required dylib
6
+ # comes bundled with this gem. This gem uses {Ruby-FFI}[link:https://github.com/ffi/ffi] to call the functions in the dylib.
7
+ # You'll need a sane ruby and compilation environment to install ruby-ffi - it probably won't install immediately with the
8
+ # ruby that comes with OSX because none of the compilation tools are present. We use {homebrew}[link:http://mxcl.github.com/homebrew/]
9
+ # and {rbenv}[link:https://github.com/sstephenson/rbenv/] to manage our ruby scripting environment.
10
+ #
11
+ # You may use this gem in various ways. For instance, you could:
12
+ #
13
+ # * Display a message or alert when a particular space is moved to
14
+ #
15
+ # * Automatically change the name of spaces depending on what apps are in them
16
+ #
17
+ # * Record which spaces certain windows are on, and restoring those windows to those spaces when the owning app restarts
18
+ #
19
+ # * Trigger moving certain windows between spaces
20
+ #
21
+ # API support, and support for this gem starts with TotalSpaces2 v2.1.0. The API is a premium feature,
22
+ # and will only work with registered versions of TotalSpaces2.
23
+ #
24
+ # == Download and installation
25
+ #
26
+ # The latest version of the TotalSpaces2 gem can be installed with RubyGems:
27
+ #
28
+ # % [sudo] gem install totalspaces2
29
+ #
30
+ # Source code can be downloaded on GitHub
31
+ #
32
+ # * https://github.com/binaryage/totalspaces2-api
33
+ #
34
+ #
35
+ # == Documentation
36
+ #
37
+ # * http://binaryage.github.io/totalspaces2-api/ruby/rdoc/TotalSpaces2.html
38
+ #
39
+ # == License
40
+ #
41
+ # The TotalSpaces gem is released under the MIT license:
42
+ #
43
+ # * http://www.opensource.org/licenses/MIT
44
+ #
45
+ # The source code of the dylib is not available at this time.
46
+ #
47
+ #
48
+ # == Support and feature requests
49
+ #
50
+ # * http://discuss.binaryage.com
51
+ #
52
+ #
53
+ # == Examples
54
+ # require 'totalspaces2'
55
+ #
56
+ # TotalSpaces2.on_space_change {|from, to, display_id| puts "Moving from space #{from} to space #{to}";}
57
+ #
58
+ # TotalSpaces2.move_to_space(1)
59
+ #
60
+ # current_space = TotalSpaces2.current_space
61
+ # puts "Current space number: #{current_space}"
62
+ # puts "Current space is called: #{TotalSpaces2.name_for_space(current_space)}"
63
+ #
64
+ # TotalSpaces2.set_name_for_space(1, "Home")
65
+ #
66
+
67
+ require 'ffi'
68
+
69
+ module TSApi #:nodoc:
70
+ extend FFI::Library
71
+ ffi_lib File.join(File.dirname(__FILE__), "libtotalspaces2api.dylib")
72
+
73
+ attach_function :tsapi_freeString, [:pointer], :void
74
+
75
+ attach_function :tsapi_libTotalSpacesVersion, [], :pointer
76
+ attach_function :tsapi_apiVersion, [], :pointer
77
+ attach_function :tsapi_totalSpacesVersion, [], :pointer
78
+
79
+ attach_function :tsapi_displayList, [], :pointer
80
+ attach_function :tsapi_freeDisplayList, [:pointer], :void
81
+
82
+ attach_function :tsapi_currentSpaceNumberOnDisplay, [:uint], :uint
83
+ attach_function :tsapi_spaceNameForSpaceNumberOnDisplay, [:uint, :uint], :pointer
84
+ attach_function :tsapi_numberOfSpacesOnDisplay, [:uint], :uint
85
+
86
+ attach_function :tsapi_definedColumnsOnDisplay, [:uint], :uint
87
+
88
+ attach_function :tsapi_setDefinedColumnsOnDisplay, [:uint, :uint], :bool
89
+
90
+ attach_function :tsapi_moveToSpaceOnDisplay, [:uint, :uint], :bool
91
+ attach_function :tsapi_setNameForSpaceOnDisplay, [:uint, :string, :uint], :bool
92
+
93
+ callback :space_change_function, [:uint, :uint, :uint], :void
94
+ attach_function :tsapi_setSpaceWillChangeCallback, [:space_change_function], :void
95
+ attach_function :tsapi_unsetSpaceWillChangeCallback, [], :void
96
+
97
+ callback :layout_changed_function, [], :void
98
+ attach_function :tsapi_setLayoutChangedCallback, [:layout_changed_function], :void
99
+ attach_function :tsapi_unsetLayoutChangedCallback, [], :void
100
+
101
+ attach_function :tsapi_windowList, [], :pointer
102
+ attach_function :tsapi_freeWindowList, [:pointer], :void
103
+
104
+ attach_function :tsapi_moveWindowToSpaceOnDisplay, [:uint, :uint, :uint], :bool
105
+
106
+ attach_function :tsapi_moveSpaceToPositionOnDisplay, [:uint, :uint, :uint], :bool
107
+
108
+ attach_function :tsapi_addDesktopsOnDisplay, [:uint, :uint], :uint
109
+ attach_function :tsapi_removeDesktopsOnDisplay, [:uint, :uint], :bool
110
+ end
111
+
112
+ module TotalSpaces2
113
+
114
+ MAX_DESKTOPS = 16
115
+
116
+ #--
117
+ # See TSLib.h for the structures returned by the C API
118
+ #++
119
+
120
+ class Display < FFI::Struct #:nodoc:
121
+ layout :displayID, :uint32,
122
+ :display_name, :string,
123
+ :width, :size_t,
124
+ :height, :size_t
125
+ end
126
+
127
+ class Displays < FFI::Struct #:nodoc:
128
+ layout :count, :uint,
129
+ :displays_array, :pointer
130
+
131
+ def display_info
132
+ displays = []
133
+ displays_array = self[:displays_array]
134
+ (0...self[:count]).each do |n|
135
+ display = Display.new(displays_array + n * Display.size)
136
+ info = {
137
+ display_id: display[:displayID],
138
+ display_name: display[:display_name],
139
+ width: display[:width],
140
+ height: display[:height]
141
+ }
142
+ displays << info
143
+ end
144
+
145
+ displays
146
+ end
147
+ end
148
+
149
+ class Windows < FFI::Struct #:nodoc:
150
+ layout :count, :uint,
151
+ :windows_array, :pointer
152
+ end
153
+
154
+ class Window < FFI::Struct #:nodoc:
155
+ layout :app_name, :string,
156
+ :window_id, :uint,
157
+ :is_on_all_spaces, :bool,
158
+ :title, :string,
159
+ :frame, :string,
160
+ :display_id, :uint,
161
+ :space_number, :uint
162
+ end
163
+
164
+ class << self
165
+ private
166
+ def string_and_free(cstr_pointer) #:nodoc:
167
+ str = cstr_pointer.get_string(0)
168
+ TSApi.tsapi_freeString(cstr_pointer)
169
+ str
170
+ end
171
+
172
+ public
173
+
174
+ # Returns the version of the dylib, a string such as "1.0"
175
+ # You should be using the same dylib major version number as that returned by the api_version call
176
+ #
177
+ # puts "libTotalSpaces2 version: #{TotalSpaces2.lib_total_spaces_version}"
178
+ #
179
+ # if TotalSpaces2.lib_total_spaces_version.split('.')[0] != TotalSpaces2.api_version.split('.')[0]
180
+ # puts "Comms error!"
181
+ # exit(1)
182
+ # end
183
+ #
184
+ #
185
+ def lib_total_spaces_version
186
+ string_and_free(TSApi.tsapi_libTotalSpacesVersion)
187
+ end
188
+
189
+ # Returns the version of the api present in TotalSpaces2, a string such as "1.0"
190
+ # You should be using the same dylib version as that returned by the this call
191
+ #
192
+ # puts "TotalSpaces2 API version: #{TotalSpaces2.api_version}"
193
+ #
194
+ # if TotalSpaces2.lib_total_spaces_version.split('.')[0] != TotalSpaces2.api_version.split('.')[0]
195
+ # puts "Comms error!"
196
+ # exit(1)
197
+ # end
198
+ #
199
+ def api_version
200
+ string_and_free(TSApi.tsapi_apiVersion)
201
+ end
202
+
203
+ # Returns the version of TotalSpaces2 running on the system, a string such as "2.0.12"
204
+ #
205
+ # puts "TotalSpaces2 version: #{TotalSpaces2.total_spaces_version}"
206
+ #
207
+ def total_spaces_version
208
+ string_and_free(TSApi.tsapi_totalSpacesVersion)
209
+ end
210
+
211
+ # Returns an array of hashes with information about attached displays. The ids returned
212
+ # from this call can be used where a display id is required in the other calls in this library.
213
+ #
214
+ # puts "Attached displays: #{TotalSpaces2.display_list}"
215
+ #
216
+ # [{:display_id=>69679040, :display_name=>"Color LCD", :width=>1440, :height=>900},
217
+ # {:display_id=>69514913, :display_name=>"LED Cinema Display", :width=>2560, :height=>1440}]
218
+ #
219
+ def display_list
220
+ list = TSApi.tsapi_displayList
221
+ displays = Displays.new(list)
222
+ result = displays.null? ? [] : displays.display_info
223
+ TSApi.tsapi_freeDisplayList(list)
224
+ result
225
+ end
226
+
227
+ # Returns information about the main display.
228
+ # Methods that do not take a display id always operate on this display.
229
+ #
230
+ # puts "Main display id: #{TotalSpaces2.main_display_id}"
231
+ #
232
+ # {:display_id=>69679040, :display_name=>"Color LCD", :width=>1440, :height=>900}
233
+ #
234
+ def main_display
235
+ self.display_list[0]
236
+ end
237
+
238
+ # Returns the number of the current space on the main display. Numbering starts at 1.
239
+ #
240
+ # puts "Current space number: #{TotalSpaces2.current_space}"
241
+ #
242
+ def current_space
243
+ TSApi.tsapi_currentSpaceNumberOnDisplay(0)
244
+ end
245
+
246
+ # Returns the number of the current space on the given display.
247
+ # Space numbering starts at 1
248
+ #
249
+ # display_id = TotalSpaces2.displays[0]
250
+ # puts "Current space number: #{TotalSpaces2.current_space_on_display(display_id)}"
251
+ #
252
+ def current_space_on_display(display_id)
253
+ TSApi.tsapi_currentSpaceNumberOnDisplay(display_id)
254
+ end
255
+
256
+ # Returns the name for a space on the main display. The returned string will be empty
257
+ # if the space number is not valid
258
+ #
259
+ # current_space = TotalSpaces2.current_space
260
+ # puts "Current space is called: #{TotalSpaces2.name_for_space(current_space)}"
261
+ #
262
+ def name_for_space(space_number)
263
+ name = string_and_free(TSApi.tsapi_spaceNameForSpaceNumberOnDisplay(space_number, 0))
264
+ name.force_encoding("UTF-8")
265
+ end
266
+
267
+ # Returns the name for a space. The returned string will be empty if the space number is
268
+ # not valid
269
+ #
270
+ # current_space = TotalSpaces2.current_space
271
+ # display_id = TotalSpaces2.main_display[:display_id]
272
+ # puts "Current space is called: #{TotalSpaces2.name_for_space_on_display(current_space, display_id)}"
273
+ #
274
+ def name_for_space_on_display(space_number, display_id)
275
+ name = string_and_free(TSApi.tsapi_spaceNameForSpaceNumberOnDisplay(space_number, display_id))
276
+ name.force_encoding("UTF-8")
277
+ end
278
+
279
+ # Returns the total number of spaces including fullscreens, dashboard (if it's a space).
280
+ #
281
+ # puts "Total number of spaces: #{TotalSpaces2.number_of_spaces}"
282
+ #
283
+ def number_of_spaces
284
+ TSApi.tsapi_numberOfSpacesOnDisplay(0)
285
+ end
286
+
287
+ # Returns the total number of spaces including fullscreens, dashboard (if it's a space).
288
+ #
289
+ # display_id = TotalSpaces2.main_display[:display_id]
290
+ # puts "Total number of spaces: #{TotalSpaces2.number_of_spaces_on_display(display_id)}"
291
+ #
292
+ def number_of_spaces_on_display(display_id)
293
+ TSApi.tsapi_numberOfSpacesOnDisplay(display_id)
294
+ end
295
+
296
+ # Returns the number of columns defined in TotalSpaces2 for the main display
297
+ #
298
+ # puts "Number of columns: #{TotalSpaces2.grid_columns}"
299
+ #
300
+ def grid_columns
301
+ TSApi.tsapi_definedColumnsOnDisplay(0)
302
+ end
303
+
304
+ # Returns the number of columns defined in TotalSpaces2
305
+ #
306
+ # display_id = TotalSpaces2.main_display[:display_id]
307
+ # puts "Number of columns: #{TotalSpaces2.grid_columns_on_display(display_id)}"
308
+ #
309
+ def grid_columns_on_display(display_id)
310
+ TSApi.tsapi_definedColumnsOnDisplay(display_id)
311
+ end
312
+
313
+ # Sets the number of columns defined in TotalSpaces2 for the main display.
314
+ #
315
+ # This does not change the actual number of desktops present, you should
316
+ # call add_desktops or remove_desktops as appropriate after changing the number
317
+ # of columns.
318
+ #
319
+ # TotalSpaces2.set_grid_columns(3)
320
+ #
321
+ def set_grid_columns(columns)
322
+ TSApi.tsapi_setDefinedColumnsOnDisplay(columns, 0)
323
+ end
324
+
325
+ # Sets the number of columns defined in TotalSpaces2.
326
+ #
327
+ # This does not change the actual number of desktops present, you should
328
+ # call add_desktops_on_display or remove_desktops_on_display as appropriate
329
+ # after changing the number of columns.
330
+ #
331
+ # display_id = TotalSpaces2.main_display[:display_id]
332
+ # TotalSpaces2.set_grid_columns_on_display(3, display_id)
333
+ #
334
+ def set_grid_columns_on_display(columns, display_id)
335
+ TSApi.tsapi_setDefinedColumnsOnDisplay(columns, display_id)
336
+ end
337
+
338
+ # Command TotalSpaces2 to switch to the given space number on the main display.
339
+ # Returns false if the space number was invalid.
340
+ # The on_space_change notification will be sent.
341
+ #
342
+ # TotalSpaces2.move_to_space(1)
343
+ #
344
+ def move_to_space(space_number)
345
+ TSApi.tsapi_moveToSpaceOnDisplay(space_number, 0)
346
+ end
347
+
348
+ # Command TotalSpaces2 to switch to the given space number.
349
+ # Returns false if the space number was invalid.
350
+ # The on_space_change notification will be sent.
351
+ #
352
+ # display_id = TotalSpaces2.main_display[:display_id]
353
+ # TotalSpaces2.move_to_space_on_Display(1, display_id)
354
+ #
355
+ def move_to_space_on_display(space_number, display_id)
356
+ TSApi.tsapi_moveToSpaceOnDisplay(space_number, display_id)
357
+ end
358
+
359
+ # Set the name for a space on the main display.
360
+ # Note that using this command will cause a layout change notification to be sent
361
+ # if the new name was different from that previously set.
362
+ # The maximum length for a name is 255 bytes.
363
+ #
364
+ # TotalSpaces2.set_name_for_space(1, "Home")
365
+ #
366
+ def set_name_for_space(space_number, name)
367
+ TSApi.tsapi_setNameForSpaceOnDisplay(space_number, name, 0)
368
+ end
369
+
370
+ # Set the name for a space.
371
+ # Note that using this command will cause a layout change notification to be sent
372
+ # if the new name was different from that previously set.
373
+ # The maximum length for a name is 255 bytes.
374
+ #
375
+ # display_id = TotalSpaces2.main_display[:display_id]
376
+ # TotalSpaces2.set_name_for_space_on_display(1, "Home", display_id)
377
+ #
378
+ def set_name_for_space_on_display(space_number, name, display_id)
379
+ TSApi.tsapi_setNameForSpaceOnDisplay(space_number, name, display_id)
380
+ end
381
+
382
+ # Register for notifications on space change.
383
+ # The given block will be called whenever you move from one space to another. The arguments are
384
+ # the space number you moved from, and the one you are moving to.
385
+ #
386
+ # TotalSpaces2.on_space_change {|from, to, displayID| puts "Moving from space #{from} to space #{to}"}
387
+ #
388
+ # sleep
389
+ #
390
+ # There can only be one block registered at any time, the most recently registered one will
391
+ # be called.
392
+ # This callback is called just before the space actually changes - current_space will still
393
+ # report the from space.
394
+ #
395
+ def on_space_change(&block)
396
+ $tsapi_on_space_change_block = block # prevent GC
397
+ TSApi.tsapi_setSpaceWillChangeCallback(block)
398
+ end
399
+
400
+ # Cancel the on_space_change notification.
401
+ #
402
+ def cancel_on_space_change
403
+ $tsapi_on_space_change_block = nil
404
+ TSApi.tsapi_unsetSpaceWillChangeCallback
405
+ end
406
+
407
+ # Register for notifications on layout change.
408
+ # The given block will be called whenever the layout changes - this could be due to making an app
409
+ # fullscreen, changing a space name, or changing the layout of the TotalSpaces2 grid. There are no
410
+ # arguments passed to the block.
411
+ #
412
+ #
413
+ # TotalSpaces.on_layout_change {puts "Spaces changed"}
414
+ #
415
+ # sleep
416
+ #
417
+ # When you get a notification from this method, you should re-fetch any information about the spaces
418
+ # that you may be storing.
419
+ #
420
+ # There can only be one block registered at any time, the most recently registered one will
421
+ # be called.
422
+ #
423
+ def on_layout_change(&block)
424
+ $tsapi_on_layout_change_block = block # prevent GC
425
+ TSApi.tsapi_setLayoutChangedCallback(block)
426
+ end
427
+
428
+ # Cancel the layout change notification
429
+ #
430
+ def cancel_on_layout_change
431
+ $tsapi_on_layout_change_block = nil
432
+ TSApi.tsapi_unsetLayoutChangedCallback
433
+ end
434
+
435
+ # Get a list of all the windows on your mac
436
+ # It returns an array containing a hash for each window.
437
+ # The hash contains the display id (key :display_id) and space number (key :space_number)
438
+ # and details for each window.
439
+ # The windows are in front to back order within each space.
440
+ # Each window hash also contains a window_id, title, frame, app_name and is_on_all_spaces flag
441
+ #
442
+ # The below example would move the frontmost window to the next space to the right.
443
+ #
444
+ # windows = TotalSpaces2.window_list
445
+ # current_space = TotalSpaces2.current_space
446
+ # main_display_id = TotalSpaces2.main_display[:display_id]
447
+ # if !windows.empty?
448
+ # current_space_windows = windows.select {|window| window[:display_id] == main_display_id
449
+ # && window[:space_number] == current_space}
450
+ # front_window = current_space_windows[0]
451
+ # TotalSpaces2.move_window_to_space(front_window[:window_id], TotalSpaces.current_space + 1)
452
+ # end
453
+ #
454
+ def window_list
455
+ result = []
456
+ list = TSApi.tsapi_windowList
457
+ main_array = Windows.new(list)
458
+
459
+ (0...main_array[:count]).each do |n|
460
+ window = Window.new(main_array[:windows_array] + n * Window.size)
461
+ window_hash = {}
462
+ window_hash[:window_id] = window[:window_id]
463
+ window_hash[:title] = window[:title].dup.force_encoding("UTF-8")
464
+ window_hash[:frame] = window[:frame].dup.force_encoding("UTF-8")
465
+ window_hash[:is_on_all_spaces] = window[:is_on_all_spaces]
466
+ window_hash[:app_name] = window[:app_name].dup.force_encoding("UTF-8")
467
+ window_hash[:display_id] = window[:display_id]
468
+ window_hash[:space_number] = window[:space_number]
469
+ result << window_hash
470
+ end
471
+
472
+ TSApi.tsapi_freeWindowList(list)
473
+
474
+ result
475
+ end
476
+
477
+ # Move a window to a given space
478
+ # The window_id parameter must be fetched using window_list.
479
+ # Returns false if the space_number or window_id is invalid.
480
+ #
481
+ def move_window_to_space(window_id, space_number)
482
+ TSApi.tsapi_moveWindowToSpaceOnDisplay(window_id, space_number, 0)
483
+ end
484
+
485
+ # Move a window to a given space on the main display
486
+ # The window_id parameter must be fetched using window_list.
487
+ # Returns false if the space_number or window_id is invalid.
488
+ #
489
+ def move_window_to_space_on_display(window_id, space_number, display_id)
490
+ TSApi.tsapi_moveWindowToSpaceOnDisplay(window_id, space_number, display_id)
491
+ end
492
+
493
+ # Move space to a new position in the grid on the main display.
494
+ #
495
+ # Returns false if the space_number or position_number is not valid.
496
+ #
497
+ # TotalSpaces2.move_space_to_position(4, 2)
498
+ #
499
+ def move_space_to_position(space_number, position_number)
500
+ TSApi.tsapi_moveSpaceToPositionOnDisplay(space_number, position_number)
501
+ end
502
+
503
+ # Move space to a new position in the grid. Spaces can only be moved
504
+ # within their own display.
505
+ #
506
+ # Returns false if the space_number or position_number is not valid.
507
+ #
508
+ # display_id = TotalSpaces2.main_display[:display_id]
509
+ # TotalSpaces2.move_space_to_position_on_display(4, 2, display_id)
510
+ #
511
+ def move_space_to_position_on_display(space_number, position_number, display_id)
512
+ TSApi.tsapi_moveSpaceToPositionOnDisplay(space_number, position_number, display_id)
513
+ end
514
+
515
+ # Add desktops
516
+ # There can be at most 16 desktops unless the display has collected some when
517
+ # a secondary display has been unplugged.
518
+ # Returns true on success, false if number_to_add was zero, or would result
519
+ # in more than 16 desktops.
520
+ # The on_layout_change notification will be sent if a changed was made.
521
+ #
522
+ # TotalSpaces2.add_desktops(1)
523
+ #
524
+ def add_desktops(number_to_add)
525
+ TSApi.tsapi_addDesktopsOnDisplay(number_to_add, 0)
526
+ end
527
+
528
+ # Add desktops
529
+ # There can be at most 16 desktops unless the display has collected some when
530
+ # a secondary display has been unplugged.
531
+ # Returns true on success, false if number_to_add was zero, or would result
532
+ # in more than 16 desktops.
533
+ # The on_layout_change notification will be sent if a changed was made.
534
+ #
535
+ # display_id = TotalSpaces2.main_display[:display_id]
536
+ # TotalSpaces2.add_desktops_on_display(1, display_id)
537
+ #
538
+ def add_desktops_on_display(number_to_add, display_id)
539
+ TSApi.tsapi_addDesktopsOnDisplay(number_to_add, display_id)
540
+ end
541
+
542
+ # Remove desktops
543
+ # The highest numbered desktops are removed.
544
+ # Removing a desktop you are currently on will result in TotalSpaces2 switching to
545
+ # another dektop.
546
+ # Any windows present on a desktop being removed will be moved to one of the
547
+ # remaining desktops.
548
+ # Returns true on success, false if number_to_remove was zero or would result in less
549
+ # than 1 desktop remaining.
550
+ # The on_layout_change notification will be sent if a change was made.
551
+ #
552
+ # TotalSpaces2.remove_desktops(1)
553
+ #
554
+ def remove_desktops(number_to_remove)
555
+ TSApi.tsapi_removeDesktopsOnDisplay(number_to_remove, 0)
556
+ end
557
+
558
+ # Remove desktops
559
+ # The highest numbered desktops are removed.
560
+ # Removing a desktop you are currently on will result in TotalSpaces2 switching to
561
+ # another dektop.
562
+ # Any windows present on a desktop being removed will be moved to one of the
563
+ # remaining desktops.
564
+ # Returns true on success, false if number_to_remove was zero or would result in less
565
+ # than 1 desktop remaining.
566
+ # The on_layout_change notification will be sent if a change was made.
567
+ #
568
+ # display_id = TotalSpaces2.main_display[:display_id]
569
+ # TotalSpaces2.remove_desktops_on_display(1, display_id)
570
+ #
571
+ def remove_desktops_on_display(number_to_remove, display_id)
572
+ TSApi.tsapi_removeDesktopsOnDisplay(number_to_remove, display_id)
573
+ end
574
+ end
575
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: totalspaces2
3
+ version: !ruby/object:Gem::Version
4
+ version: '2.0'
5
+ platform: ruby
6
+ authors:
7
+ - Stephen Sykes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.11
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.11
27
+ description: This allows you to control the TotalSpaces2 desktop manager for mac from
28
+ ruby.
29
+ email: stephen@binaryage.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.rdoc
35
+ - MIT_LICENCE
36
+ - lib/totalspaces2.rb
37
+ - lib/libtotalspaces2api.dylib
38
+ - lib/TSLib.h
39
+ homepage: https://github.com/binaryage/totalspaces2-api/tree/master/ruby
40
+ licenses: []
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.0.3
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: TotalSpaces2 control from ruby
63
+ test_files: []