vrvirtualdesktop 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +4 -0
- data/LICENSE +1 -0
- data/README +37 -0
- data/TODO +3 -0
- data/bin/vrdesk.rbw +55 -0
- data/lib/VRVirtualDesktopForm.rb +267 -0
- data/lib/Win32/APIMapper.rb +62 -0
- data/lib/Win32/Base-consts.rb +891 -0
- data/lib/Win32/Base.rb +275 -0
- data/lib/Win32/Encoding.rb +68 -0
- data/lib/Win32/GetSystemMetrics.rb +107 -0
- data/lib/Win32/NetResources.rb +160 -0
- data/lib/Win32/Process.rb +468 -0
- data/lib/Win32/Registry.rb +515 -0
- data/lib/Win32/User32.rb +142 -0
- data/lib/Win32/VirtualDesktop.rb +418 -0
- data/lib/Win32/WindowManager.rb +177 -0
- data/lib/resources/desktops.ico +0 -0
- data/lib/resources/five_down.ico +0 -0
- data/lib/resources/five_up.ico +0 -0
- data/lib/resources/four_down.ico +0 -0
- data/lib/resources/four_up.ico +0 -0
- data/lib/resources/obdb.ico +0 -0
- data/lib/resources/one_down.ico +0 -0
- data/lib/resources/one_up.ico +0 -0
- data/lib/resources/six_down.ico +0 -0
- data/lib/resources/six_up.ico +0 -0
- data/lib/resources/three_down.ico +0 -0
- data/lib/resources/three_up.ico +0 -0
- data/lib/resources/two_down.ico +0 -0
- data/lib/resources/two_up.ico +0 -0
- metadata +97 -0
data/lib/Win32/User32.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
#
|
2
|
+
# This module contains information allowing the user to call
|
3
|
+
# functions defined in User32.dll
|
4
|
+
#
|
5
|
+
|
6
|
+
require "dl"
|
7
|
+
require "Win32API"
|
8
|
+
|
9
|
+
module Win32
|
10
|
+
# Constants
|
11
|
+
|
12
|
+
NULL = 0
|
13
|
+
SW_HIDE = 0
|
14
|
+
SW_SHOWNORMAL = 1
|
15
|
+
SW_NORMAL = 1
|
16
|
+
SW_SHOWMINIMIZED = 2
|
17
|
+
SW_SHOWMAXIMIZED = 3
|
18
|
+
SW_MAXIMIZE = 3
|
19
|
+
SW_SHOWNOACTIVATE = 4
|
20
|
+
SW_SHOW = 5
|
21
|
+
SW_MINIMIZE = 6
|
22
|
+
SW_SHOWMINNOACTIVE = 7
|
23
|
+
SW_SHOWNA = 8
|
24
|
+
SW_RESTORE = 9
|
25
|
+
SW_SHOWDEFAULT = 10
|
26
|
+
SW_FORCEMINIMIZE = 11
|
27
|
+
SW_MAX = 11
|
28
|
+
|
29
|
+
GWL_WNDPROC = (-4)
|
30
|
+
GWL_HINSTANCE = (-6)
|
31
|
+
GWL_HWNDPARENT = (-8)
|
32
|
+
GWL_STYLE = (-16)
|
33
|
+
GWL_EXSTYLE = (-20)
|
34
|
+
GWL_USERDATA = (-21)
|
35
|
+
GWL_ID = (-12)
|
36
|
+
|
37
|
+
WS_OVERLAPPED = 0x00000000
|
38
|
+
WS_POPUP = 0x80000000
|
39
|
+
WS_CHILD = 0x40000000
|
40
|
+
WS_MINIMIZE = 0x20000000
|
41
|
+
WS_VISIBLE = 0x10000000
|
42
|
+
WS_DISABLED = 0x08000000
|
43
|
+
WS_CLIPSIBLINGS = 0x04000000
|
44
|
+
WS_CLIPCHILDREN = 0x02000000
|
45
|
+
WS_MAXIMIZE = 0x01000000
|
46
|
+
WS_CAPTION = 0x00C00000 #/* WS_BORDER | WS_DLGFRAME =*/
|
47
|
+
WS_BORDER = 0x00800000
|
48
|
+
WS_DLGFRAME = 0x00400000
|
49
|
+
WS_VSCROLL = 0x00200000
|
50
|
+
WS_HSCROLL = 0x00100000
|
51
|
+
WS_SYSMENU = 0x00080000
|
52
|
+
WS_THICKFRAME = 0x00040000
|
53
|
+
WS_GROUP = 0x00020000
|
54
|
+
WS_TABSTOP = 0x00010000
|
55
|
+
|
56
|
+
WS_MINIMIZEBOX = 0x00020000
|
57
|
+
WS_MAXIMIZEBOX = 0x00010000
|
58
|
+
|
59
|
+
|
60
|
+
WS_TILED = WS_OVERLAPPED
|
61
|
+
WS_ICONIC = WS_MINIMIZE
|
62
|
+
WS_SIZEBOX = WS_THICKFRAME
|
63
|
+
|
64
|
+
#
|
65
|
+
# Common Window Styles
|
66
|
+
#
|
67
|
+
WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED |
|
68
|
+
WS_CAPTION |
|
69
|
+
WS_SYSMENU |
|
70
|
+
WS_THICKFRAME |
|
71
|
+
WS_MINIMIZEBOX |
|
72
|
+
WS_MAXIMIZEBOX)
|
73
|
+
|
74
|
+
WS_POPUPWINDOW = (WS_POPUP |
|
75
|
+
WS_BORDER |
|
76
|
+
WS_SYSMENU)
|
77
|
+
|
78
|
+
WS_CHILDWINDOW = (WS_CHILD)
|
79
|
+
|
80
|
+
WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW
|
81
|
+
|
82
|
+
#
|
83
|
+
# Extended Window Styles
|
84
|
+
#
|
85
|
+
WS_EX_DLGMODALFRAME = 0x00000001
|
86
|
+
WS_EX_NOPARENTNOTIFY = 0x00000004
|
87
|
+
WS_EX_TOPMOST = 0x00000008
|
88
|
+
WS_EX_ACCEPTFILES = 0x00000010
|
89
|
+
WS_EX_TRANSPARENT = 0x00000020
|
90
|
+
|
91
|
+
WS_EX_MDICHILD = 0x00000040
|
92
|
+
WS_EX_TOOLWINDOW = 0x00000080
|
93
|
+
WS_EX_WINDOWEDGE = 0x00000100
|
94
|
+
WS_EX_CLIENTEDGE = 0x00000200
|
95
|
+
WS_EX_CONTEXTHELP = 0x00000400
|
96
|
+
|
97
|
+
WS_EX_RIGHT = 0x00001000
|
98
|
+
WS_EX_LEFT = 0x00000000
|
99
|
+
WS_EX_RTLREADING = 0x00002000
|
100
|
+
WS_EX_LTRREADING = 0x00000000
|
101
|
+
WS_EX_LEFTSCROLLBAR = 0x00004000
|
102
|
+
WS_EX_RIGHTSCROLLBAR = 0x00000000
|
103
|
+
|
104
|
+
WS_EX_CONTROLPARENT = 0x00010000
|
105
|
+
WS_EX_STATICEDGE = 0x00020000
|
106
|
+
WS_EX_APPWINDOW = 0x00040000
|
107
|
+
|
108
|
+
WS_EX_OVERLAPPEDWINDOW =(WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE)
|
109
|
+
WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST)
|
110
|
+
|
111
|
+
#
|
112
|
+
# GetWindow() Constants
|
113
|
+
#
|
114
|
+
GW_HWNDFIRST = 0
|
115
|
+
GW_HWNDLAST = 1
|
116
|
+
GW_HWNDNEXT = 2
|
117
|
+
GW_HWNDPREV = 3
|
118
|
+
GW_OWNER = 4
|
119
|
+
GW_CHILD = 5
|
120
|
+
GW_ENABLEDPOPUP = 6
|
121
|
+
GW_MAX = 6
|
122
|
+
|
123
|
+
# Functions
|
124
|
+
|
125
|
+
User32 = DL.dlopen("user32")
|
126
|
+
EnumWindows = User32['EnumWindows', 'IPL']
|
127
|
+
PostMessage = User32['PostMessage', 'ILILL']
|
128
|
+
GetClassName = User32['GetClassName', 'ILpI']
|
129
|
+
FindWindowEx = User32["FindWindowEx", "IIIPP"]
|
130
|
+
RegisterWindowMessage = User32["RegisterWindowMessage", "IP"]
|
131
|
+
SendMessage = User32["SendMessage", "IIIII"]
|
132
|
+
ShowWindow = User32["ShowWindow", "III"]
|
133
|
+
GetWindowLong = User32["GetWindowLong", "III"]
|
134
|
+
GetWindow = User32["GetWindow", "III"]
|
135
|
+
GetTopWindow = User32["GetTopWindow", "II"]
|
136
|
+
IsIconic = User32["IsIconic", "II"]
|
137
|
+
|
138
|
+
GetWindowLong_2 = Win32API.new("user32","GetWindowLong", ["I","I"],"I")
|
139
|
+
GetWindow_2 = Win32API.new("user32","GetWindow", ["I","I"],"I")
|
140
|
+
GetClassName_2 = Win32API.new("user32", "GetClassName", ["I", "P", "I"], "I")
|
141
|
+
|
142
|
+
end # module Win32
|
@@ -0,0 +1,418 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require_gem "SimpleTrace", "< 0.1.0"
|
3
|
+
require "yaml"
|
4
|
+
require "Win32API"
|
5
|
+
require_gem "VRTools", "< 0.1.0"
|
6
|
+
require "vr/vrdialog"
|
7
|
+
|
8
|
+
module Win32
|
9
|
+
|
10
|
+
#
|
11
|
+
# A virtual desktop consists of a set of windows on it, a name, a numbered icon and whether it is active
|
12
|
+
# or not
|
13
|
+
#
|
14
|
+
class VirtualDesktop
|
15
|
+
attr_reader :icon_id, :name, :index, :windows
|
16
|
+
attr_accessor :active
|
17
|
+
attr_accessor :form
|
18
|
+
|
19
|
+
class SetScreenName < VRModalDialog
|
20
|
+
#include AddControlFont
|
21
|
+
include VRCenterFeasible
|
22
|
+
include VRLayout
|
23
|
+
include VRKey_CREscFeasible
|
24
|
+
|
25
|
+
attr_reader :name
|
26
|
+
|
27
|
+
DEFAULT_FONT = VRLocalScreen.factory.newfont("Arial",14)
|
28
|
+
|
29
|
+
LABEL_H = 20
|
30
|
+
LABEL_W = 100
|
31
|
+
EDIT_H = 20
|
32
|
+
EDIT_W = 100
|
33
|
+
BUTTON_W = 70
|
34
|
+
BUTTON_H = 25
|
35
|
+
|
36
|
+
def exinit(name)
|
37
|
+
@name = name
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def construct
|
42
|
+
self.caption = "Set Desktop Name"
|
43
|
+
v_frame = Layout::VertLayoutFrame.new(nil,{Layout::SPACING=>10}) do |vf|
|
44
|
+
# For the date input
|
45
|
+
Layout::HorzLayoutFrame.new(vf, {Layout::SPACING=>5}) do |hf|
|
46
|
+
hf.addcontrol(self, Layout::Dimensions.new(LABEL_W,LABEL_H), VRStatic, "static", "Screen Name:", 0)
|
47
|
+
hf.addcontrol(self, Layout::Dimensions.new(EDIT_W,EDIT_H), VREdit, "name_edit", @name, WStyle::WS_TABSTOP)
|
48
|
+
end
|
49
|
+
|
50
|
+
Layout::HorzLayoutFrame.new(vf, {Layout::SPACING=>5}) do |hf|
|
51
|
+
hf.addcontrol(self, Layout::Dimensions.new(BUTTON_W,BUTTON_H), VRButton, "okbutton", "Ok", WStyle::WS_TABSTOP)
|
52
|
+
hf.addcontrol(self, Layout::Dimensions.new(BUTTON_W,BUTTON_H), VRButton, "cancelbutton", "Cancel", WStyle::WS_TABSTOP)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
v_frame.layout(0,0, v_frame.dimensions.min_width, v_frame.dimensions.min_height)
|
57
|
+
|
58
|
+
@name_edit.text = @name
|
59
|
+
|
60
|
+
if self.kind_of?(VRDialogComponent) then
|
61
|
+
setButtonAs(@okbutton, VRDialogComponent::IDOK)
|
62
|
+
setButtonAs(@cancelbutton, VRDialogComponent::IDCANCEL)
|
63
|
+
end
|
64
|
+
|
65
|
+
w, h = self.set_client_size(v_frame, v_frame.dimensions.min_width, v_frame.dimensions.min_height, 10)
|
66
|
+
center(@creator, w, h)
|
67
|
+
end
|
68
|
+
|
69
|
+
def okbutton_clicked
|
70
|
+
@name = @name_edit.text
|
71
|
+
self.close(VRDialogComponent::IDOK)
|
72
|
+
end
|
73
|
+
|
74
|
+
def cancelbutton_clicked
|
75
|
+
self.close(VRDialogComponent::IDCANCEL)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
class << self
|
81
|
+
# create is here to allow another program to
|
82
|
+
# change how virtual desktops are created (use an object
|
83
|
+
# loaded off of disk instead of a freshly created one
|
84
|
+
def create(*args)
|
85
|
+
VirtualDesktop.new(*args)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def initialize(virtual_desktops, up_icon_filename, down_icon_filename, icon_id, name, index, active, window_manager)
|
90
|
+
@virtual_desktops ||= virtual_desktops
|
91
|
+
@up_icon ||= VRLocalScreen.factory.iconfromfile(up_icon_filename)
|
92
|
+
@down_icon ||= VRLocalScreen.factory.iconfromfile(down_icon_filename)
|
93
|
+
@icon_id ||= icon_id
|
94
|
+
@name ||= name
|
95
|
+
@index ||= index
|
96
|
+
@windows ||= []
|
97
|
+
@active ||= active
|
98
|
+
@form ||= nil
|
99
|
+
@windows ||= []
|
100
|
+
@window_manager ||= window_manager
|
101
|
+
end
|
102
|
+
|
103
|
+
def icon
|
104
|
+
if @active then
|
105
|
+
@down_icon
|
106
|
+
else
|
107
|
+
@up_icon
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def modify_trayicon
|
112
|
+
form.modify_trayicon(icon.hicon, @name, @icon_id)
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_trayicon
|
116
|
+
form.create_trayicon(icon.hicon, @name, @icon_id)
|
117
|
+
end
|
118
|
+
|
119
|
+
def delete_trayicon
|
120
|
+
form.delete_trayicon(@icon_id)
|
121
|
+
end
|
122
|
+
|
123
|
+
def active=(activate)
|
124
|
+
# if we are becoming active
|
125
|
+
if (activate && !@active) then
|
126
|
+
$TRACE.debug 5, "desktop '#{@name}' becoming active"
|
127
|
+
@windows.each do |window|
|
128
|
+
$TRACE.debug 5, "activating window #{window}"
|
129
|
+
window.show
|
130
|
+
end
|
131
|
+
# if we are becoming inactive
|
132
|
+
elsif (@active && !activate) then
|
133
|
+
$TRACE.debug 5, "desktop '#{@name}' becoming inactive"
|
134
|
+
@windows.each do |window|
|
135
|
+
$TRACE.debug 5, "deactivating window #{window}"
|
136
|
+
window.hide
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
@active = activate
|
141
|
+
modify_trayicon
|
142
|
+
end
|
143
|
+
|
144
|
+
def add_window(window)
|
145
|
+
@virtual_desktops.add_window(window)
|
146
|
+
@windows.push(window)
|
147
|
+
$TRACE.debug 5, "adding window #{window}"
|
148
|
+
$TRACE.debug 5, "after add windows = #{@windows.map{|w| w.to_s}.join(',')}"
|
149
|
+
end
|
150
|
+
|
151
|
+
def remove_window(window)
|
152
|
+
@windows.delete_if {|x| x.hwnd == window.hwnd}
|
153
|
+
$TRACE.debug 5, "removing window #{window}"
|
154
|
+
$TRACE.debug 5, "after remove windows = #{@windows.map{|w| w.to_s}.join(',')}"
|
155
|
+
end
|
156
|
+
|
157
|
+
def handle_exit
|
158
|
+
@windows.each {|window| window.show}
|
159
|
+
end
|
160
|
+
|
161
|
+
def set_screen_name
|
162
|
+
set_screen_name_form = VRLocalScreen.newdialog(@mainForm,nil,SetScreenName)
|
163
|
+
returnResult = set_screen_name_form.exinit(@name).open nil,true
|
164
|
+
|
165
|
+
if returnResult == VRDialogComponent::IDOK then
|
166
|
+
@name = set_screen_name_form.name
|
167
|
+
modify_trayicon
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def contains_window(window)
|
172
|
+
@windows.index(window)
|
173
|
+
end
|
174
|
+
|
175
|
+
def to_s
|
176
|
+
"#{name}: windows = " + @windows.map{|w| w.to_s}.join(",")
|
177
|
+
end
|
178
|
+
|
179
|
+
class SaveInfo
|
180
|
+
attr_reader :window_handles, :name
|
181
|
+
def initialize(window_handles, name)
|
182
|
+
@window_handles = window_handles
|
183
|
+
@name = name
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
#
|
189
|
+
# the info that we save for this desktop is just an array of window handles of
|
190
|
+
# the windows on this desktop
|
191
|
+
#
|
192
|
+
def save_info
|
193
|
+
SaveInfo.new(@windows.map{|w| w.hwnd}, @name)
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
# when restoring those windows, find the window associated with the stored window handle
|
198
|
+
# and add it to the desktop and show it if we are active
|
199
|
+
#
|
200
|
+
def restore_info(save_info)
|
201
|
+
window_handles = save_info.window_handles
|
202
|
+
|
203
|
+
# add in the windows
|
204
|
+
$TRACE.debug 5, "window_handles = #{window_handles.inspect}"
|
205
|
+
all_windows = @window_manager.get_all_windows(true).values
|
206
|
+
$TRACE.debug 5, "all-windows = " + all_windows.map{|w| w.to_s}.join(",")
|
207
|
+
window_handles.each do |hwnd|
|
208
|
+
window = all_windows.select{|w| w.hwnd == hwnd}[0]
|
209
|
+
if window then
|
210
|
+
$TRACE.debug 5, "found window = #{window}"
|
211
|
+
add_window(window)
|
212
|
+
if @active then
|
213
|
+
window.show
|
214
|
+
else
|
215
|
+
window.hide
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# modify the tray icon name
|
221
|
+
@name = save_info.name
|
222
|
+
modify_trayicon
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
#
|
227
|
+
# This class holds the array of virtual desktops
|
228
|
+
#
|
229
|
+
class VirtualDesktops < Array
|
230
|
+
attr_reader :active_desktop_index
|
231
|
+
|
232
|
+
class << self
|
233
|
+
# create is here to allow another program to
|
234
|
+
# change how virtual desktops are created (use an object
|
235
|
+
# loaded off of disk instead of a freshly created one
|
236
|
+
def create(*args)
|
237
|
+
VirtualDesktops.new(*args)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
NUM_NAMES = ["one", "two", "three", "four", "five", "six", "seven", "eight"]
|
242
|
+
def initialize(form, dir_base, icon_id_base, num_desktops, window_manager, *args)
|
243
|
+
super(*args)
|
244
|
+
@form ||= form
|
245
|
+
@active_desktop_index ||= 0
|
246
|
+
@window_manager ||= window_manager
|
247
|
+
@last_windows ||= get_all_windows
|
248
|
+
@all_windows ||= []
|
249
|
+
|
250
|
+
NUM_NAMES.each_with_index do |number, index|
|
251
|
+
icon_base = dir_base + "/" + number
|
252
|
+
self.push(VirtualDesktop.create(self, icon_base + "_up.ico", icon_base + "_down.ico", icon_id_base+index, "Screen #{index+1}", index, index == 0, window_manager))
|
253
|
+
break if index+1 >= num_desktops
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def push(virtual_desktop)
|
258
|
+
super(virtual_desktop)
|
259
|
+
virtual_desktop.form = @form
|
260
|
+
end
|
261
|
+
|
262
|
+
def active_desktop_index=(desktop_num)
|
263
|
+
self[@active_desktop_index].active = false
|
264
|
+
@active_desktop_index = desktop_num
|
265
|
+
self[desktop_num].active = true
|
266
|
+
@last_windows = get_all_windows
|
267
|
+
end
|
268
|
+
|
269
|
+
def active_desktop
|
270
|
+
self[@active_desktop_index]
|
271
|
+
end
|
272
|
+
|
273
|
+
def change_desktop(icon_id)
|
274
|
+
clicked_desktop = self.select{|s| s.icon_id == icon_id}[0]
|
275
|
+
$TRACE.debug 5, "change_desktop: #{icon_id} -> #{clicked_desktop} ? #{@active_desktop_index}"
|
276
|
+
if clicked_desktop.index != @active_desktop_index then
|
277
|
+
$TRACE.debug 5, "changing desktops"
|
278
|
+
self.active_desktop_index = clicked_desktop.index
|
279
|
+
|
280
|
+
# save the changed state
|
281
|
+
save
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def move_window(icon_id)
|
286
|
+
# if the clicked desktop is not the active desktop then
|
287
|
+
clicked_desktop = self.select{|s| s.icon_id == icon_id}[0]
|
288
|
+
if clicked_desktop.index != @active_desktop_index then
|
289
|
+
# get top window object
|
290
|
+
windows = @window_manager.get_all_windows
|
291
|
+
top_window_hwnd = @window_manager.get_top_window(windows)
|
292
|
+
top_window = windows[top_window_hwnd]
|
293
|
+
|
294
|
+
# move it from the active to the clicked desktop
|
295
|
+
self[@active_desktop_index].remove_window(top_window)
|
296
|
+
self[clicked_desktop.index].add_window(top_window)
|
297
|
+
|
298
|
+
# and now hide it
|
299
|
+
top_window.hide
|
300
|
+
|
301
|
+
# save the changed state
|
302
|
+
save
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def add_window(window)
|
307
|
+
@all_windows.push(window) unless @all_windows.index(window)
|
308
|
+
end
|
309
|
+
|
310
|
+
def create_trayicons
|
311
|
+
self.reverse.each do |desktop|
|
312
|
+
desktop.create_trayicon
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def delete_trayicons
|
317
|
+
self.each do |desktop|
|
318
|
+
desktop.delete_trayicon
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def get_all_windows
|
323
|
+
# select all non-tooltip windows
|
324
|
+
@window_manager.get_all_windows.values.select do |w|
|
325
|
+
!/tooltips/.match(w.class_name)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def contains_window(window)
|
330
|
+
self.each do |virtual_desktop|
|
331
|
+
if virtual_desktop.contains_window(window) then
|
332
|
+
return true
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
return false
|
337
|
+
end
|
338
|
+
|
339
|
+
#
|
340
|
+
# this needs to be called periodically (< 1sec) to detect
|
341
|
+
# windows that are being closed or opened
|
342
|
+
#
|
343
|
+
def periodic_timer
|
344
|
+
current_windows = get_all_windows
|
345
|
+
added_windows = current_windows - @last_windows
|
346
|
+
removed_windows = @last_windows - current_windows
|
347
|
+
|
348
|
+
$TRACE.debug 7, "cur windows = " + current_windows.map{|w|w.hwnd}.join(",")
|
349
|
+
$TRACE.debug 7, "last windows = " + @last_windows.map{|w|w.hwnd}.join(",")
|
350
|
+
$TRACE.debug 7, "added_windows = " + added_windows.map{|w|"#{w.hwnd}-#{w.class_name}"}.join(",")
|
351
|
+
$TRACE.debug 7, "removed_windows = " + removed_windows.map{|w|"#{w.hwnd}-#{w.class_name}"}.join(",")
|
352
|
+
|
353
|
+
active_desktop = self[@active_desktop_index]
|
354
|
+
added_windows.each do |window|
|
355
|
+
active_desktop.add_window(window)
|
356
|
+
end
|
357
|
+
removed_windows.each do |window|
|
358
|
+
active_desktop.remove_window(window)
|
359
|
+
end
|
360
|
+
|
361
|
+
# save the state if there were any modifications
|
362
|
+
if added_windows.size > 0 || removed_windows.size > 0 then
|
363
|
+
save
|
364
|
+
end
|
365
|
+
|
366
|
+
@last_windows = current_windows
|
367
|
+
end
|
368
|
+
|
369
|
+
def set_screen_name
|
370
|
+
self[@active_desktop_index].set_screen_name
|
371
|
+
end
|
372
|
+
|
373
|
+
def save_info
|
374
|
+
virtual_desktops = []
|
375
|
+
self.each do |vd|
|
376
|
+
virtual_desktops.push(vd.save_info)
|
377
|
+
end
|
378
|
+
virtual_desktops
|
379
|
+
end
|
380
|
+
|
381
|
+
def restore_info(virtual_desktop_infos)
|
382
|
+
self.each_with_index do |virtual_desktop, i|
|
383
|
+
virtual_desktop.restore_info(virtual_desktop_infos[i])
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
class Configuration
|
388
|
+
attr_reader :save_info
|
389
|
+
def initialize(save_info)
|
390
|
+
@name = "Virtual Desktop Configuration File"
|
391
|
+
@version = "1.0"
|
392
|
+
@save_info = save_info
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
def save
|
397
|
+
File.open("c:/vtdesk.txt", "w") do |f|
|
398
|
+
f.write(Configuration.new(self.save_info).to_yaml)
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
def restore
|
403
|
+
configuration = nil
|
404
|
+
File.open("c:/vtdesk.txt", "r") do |f|
|
405
|
+
configuration = YAML::load(f)
|
406
|
+
end
|
407
|
+
|
408
|
+
restore_info(configuration.save_info)
|
409
|
+
end
|
410
|
+
|
411
|
+
def handle_exit
|
412
|
+
self.each do |desktop|
|
413
|
+
desktop.handle_exit
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
end # module Win32
|