ruby-wmctrl 0.0.3 → 0.0.4

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.
Files changed (5) hide show
  1. data/README.md +57 -3
  2. data/bin/rwmctrl +197 -0
  3. data/ext/wmctrl.c +11 -62
  4. data/lib/wmctrl/version.rb +1 -1
  5. metadata +11 -9
data/README.md CHANGED
@@ -5,12 +5,66 @@ Ruby bindings to control windows in EWMH and NetWM compatible X Window manager.
5
5
  - <http://rubygems.org/gems/ruby-wmctrl>
6
6
  - <https://github.com/ytaka/ruby-wmctrl>
7
7
 
8
- ## Compilation
8
+ ## Installation
9
9
 
10
10
  ruby-wmctrl is a C extended library, which uses glib and x11.
11
11
  For ubuntu 11.04, we should install packages.
12
12
 
13
- apt-get install libx11-dev libglib2.0-dev
13
+ apt-get install libx11-dev libglib2.0-dev libxmu-dev
14
+
15
+ Then we can install ruby-wmctrl from rubygems.
16
+
17
+ gem install ruby-wmctrl
18
+
19
+ ## Usage
20
+
21
+ We load 'wmctrl' as below
22
+
23
+ require 'wmctrl'
24
+
25
+ and call methods of an instance of WMCtrl.
26
+
27
+ ### List windows
28
+
29
+ require 'wmctrl'
30
+ require 'pp'
31
+ wm = WMCtrl.new
32
+ pp wm.list_windows
33
+
34
+ ### Activate a window
35
+
36
+ wm.action_window(window_id, :activate)
37
+
38
+ The method 'action_window' takes window ID as first argument.
39
+ We can get window ID by the method 'list_windows'.
40
+ The second argument of 'action_window' is an action that
41
+ manages the window of window ID.
42
+ The rest arguments are arguments of the action.
43
+
44
+ ### Close a window
45
+
46
+ wm.action_window(window_id, :close)
47
+
48
+ ### Move and resize a window
49
+
50
+ wm.action_window(window_id, :move_resize, 0, 100, 200, 500, 400)
51
+
52
+ The integers of the arguments means gravity, x coordinate, y coordinate,
53
+ width, and height, respectively. That is,
54
+
55
+ wm.action_window(window_id, :move_resize, gravity, x, y, width, height)
56
+
57
+ ### Move window to a desktop
58
+
59
+ wm.action_window(window_id, :move_to_desktop, desktop_id)
60
+
61
+ ### Move wndow to current desktop
62
+
63
+ wm.action_window(window_id, :move_to_current)
64
+
65
+ ### List desktops
66
+
67
+ pp wm.list_desktops
14
68
 
15
69
  ## License
16
70
 
@@ -22,7 +76,7 @@ GPLv2
22
76
 
23
77
  ruby-wmctrl is created from source code of wmctrl <http://sweb.cz/tripie/utils/wmctrl/>.
24
78
 
25
- The copyright of originl wmctrl:
79
+ The copyright of original wmctrl:
26
80
 
27
81
  Author, current maintainer: Tomas Styblo tripie@cpan.org
28
82
  Copyright (C) 2003
@@ -0,0 +1,197 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
4
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../ext'))
5
+ require 'wmctrl'
6
+ require 'optparse'
7
+
8
+ help_message =<<HELP
9
+ Usage: rwmctrl [options ...]
10
+ HELP
11
+
12
+ Version = WMCtrl::VERSION
13
+
14
+ options = {}
15
+ begin
16
+ OptionParser.new(help_message) do |opt|
17
+ opt.on('-l', 'List windows.') do |v|
18
+ options[:mode] = :list_windows
19
+ end
20
+ opt.on('-p', 'Display PID of windows.') do |v|
21
+ options[:pid] = true
22
+ end
23
+ opt.on('-x', 'Display class name.') do |v|
24
+ options[:class] = true
25
+ end
26
+ opt.on('-G', 'Display geometry of windows.') do |v|
27
+ options[:geometry] = true
28
+ end
29
+ opt.on('-A', 'Mark active window.') do |v|
30
+ options[:active] = true
31
+ end
32
+ opt.on('-E', 'Display corners of exterior frame of windows.') do |v|
33
+ options[:exterior_frame] = true
34
+ end
35
+ opt.on('-e <MVARG>', String, 'Move and resize windows.') do |v|
36
+ options[:mode] = :move_resize
37
+ options[:move_resize] = v
38
+ end
39
+ opt.on('-r <WIN>', String, 'Specify target window.') do |v|
40
+ options[:target] = v
41
+ end
42
+ opt.on('-c <WIN>', String, 'Close window.') do |v|
43
+ options[:mode] = :close
44
+ options[:target] = v
45
+ end
46
+ opt.on('-d', 'List all desktops.') do |v|
47
+ options[:mode] = :desktop
48
+ end
49
+ opt.on('-m', 'Show information of window manager.') do |v|
50
+ options[:mode] = :wm_info
51
+ end
52
+ opt.on('-b STR', String, 'Change window properties. Format is (add|remove|toggle),prop1[,prop2]') do |v|
53
+ options[:mode] = :change_state
54
+ options[:change_state] = v
55
+ end
56
+ opt.on('-n N', Integer, 'Change the number of desktops.') do |v|
57
+ options[:mode] = :desktop_number
58
+ options[:desktop_number] = v
59
+ end
60
+ # Not implemented options
61
+ # '-g'
62
+ # '-I'
63
+ # '-k'
64
+ # '-N'
65
+ # '-o'
66
+ # '-R'
67
+ # '-s'
68
+ # '-t'
69
+ # '-T'
70
+ # '-w'
71
+
72
+ # '-u'
73
+ # '-v'
74
+ opt.on('-i', 'Use window ID number as window argument.') do |v|
75
+ options[:use_wid] = true
76
+ end
77
+ opt.on('-F', 'Use exact match of window title.') do |v|
78
+ option[:use_exact] = true
79
+ end
80
+ opt.on('--ignore-case', 'Ignore case to specfy target window.') do |v|
81
+ options[:ignore_case] = true
82
+ end
83
+ opt.parse!(ARGV)
84
+ end
85
+ rescue OptionParser::InvalidOption
86
+ $stderr.print <<MES
87
+ error: Invalid Option
88
+ #{help_message}
89
+ MES
90
+ exit(2)
91
+ rescue OptionParser::InvalidArgument
92
+ $stderr.print <<MES
93
+ error: Invalid Argument
94
+ #{help_message}
95
+ MES
96
+ exit(2)
97
+ end
98
+
99
+ wm = WMCtrl.new
100
+
101
+ def specify_window(wm, arg, options)
102
+ if arg == ':ACTIVE:'
103
+ wm.list_windows.find do |w|
104
+ w[:active] ? w : nil
105
+ end
106
+ elsif arg == ':SELECT:'
107
+ raise 'Not implemented.'
108
+ elsif options[:use_wid]
109
+ wid = Integer(arg)
110
+ wm.list_windows.find do |w|
111
+ wid == w[:id] ? w : nil
112
+ end
113
+ else
114
+ if options[:use_exact]
115
+ wm.list_windows.find do |w|
116
+ arg == w[:title] ? w : nil
117
+ end
118
+ else
119
+ reg = Regexp.new(arg, options[:ignore_case] ? Regexp::IGNORECASE : 0)
120
+ wm.list_windows.find do |w|
121
+ reg =~ w[:title] ? w : nil
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ case options[:mode]
128
+ when :list_windows
129
+ windows = wm.list_windows(true)
130
+ str_class_size = windows.map { |w| w[:class].to_s.size }.max
131
+ windows.each do |win|
132
+ s = ''
133
+ if options[:active]
134
+ s << (win[:active] ? "* " : " ")
135
+ end
136
+ s << sprintf("0x%08x %2d ", win[:id], win[:desktop])
137
+ if options[:pid]
138
+ s << "%-7d" % (win[:pid] || 0)
139
+ end
140
+ if options[:geometry]
141
+ s << win[:geometry].map { |n| "%-5d" % n}.join
142
+ end
143
+ if options[:exterior_frame]
144
+ if win[:exterior_frame]
145
+ s << win[:exterior_frame].map { |n| "%-5d" % n}.join
146
+ else
147
+ s << "N/A"
148
+ end
149
+ end
150
+ if options[:class]
151
+ s << sprintf("%*s ", -str_class_size, (win[:class] || "N/A"))
152
+ end
153
+ s << sprintf("%s %s", win[:client_machine] || "N/A", win[:title] || "N/A")
154
+ puts s
155
+ end
156
+ when :move_resize
157
+ if target_win = specify_window(wm, options[:target], options)
158
+ args = options[:move_resize].split(',').map(&:to_i)
159
+ if args.size == 5
160
+ wm.action_window(target_win[:id], :move_resize, *args)
161
+ else
162
+ puts "Invalid arguments."
163
+ end
164
+ else
165
+ puts "Can not specify target window."
166
+ end
167
+ when :change_state
168
+ if target_win = specify_window(wm, options[:target], options)
169
+ args = options[:change_state].split(',')
170
+ if args.size == 2 || args.size == 3
171
+ wm.action_window(target_win[:id], :change_state, *args)
172
+ else
173
+ puts "Invalid property string."
174
+ end
175
+ end
176
+ when :close
177
+ if target_win = specify_window(wm, options[:target], options)
178
+ wm.action_window(target_win[:id], :close)
179
+ end
180
+ when :desktop
181
+ wm.list_desktops.each do |dt|
182
+ printf("%d %s DG: %dx%d VP: %d,%d WA: %d,%d %dx%d %s\n",
183
+ dt[:id], dt[:current] ? '*' : '-', dt[:geometry][0], dt[:geometry][1], dt[:viewport][0], dt[:viewport][1],
184
+ dt[:workarea][0], dt[:workarea][1], dt[:workarea][2], dt[:workarea][3], dt[:title])
185
+ end
186
+ when :desktop_number
187
+ wm.change_number_of_desktops(options[:desktop_number])
188
+ when :wm_info
189
+ info = wm.info
190
+ puts "Name: #{info[:name]}"
191
+ puts "Class: #{info[:class]}"
192
+ puts "PID: #{info[:pid] ? info[:pid].to_s : "N/A"}"
193
+ puts "Window manager's \"showing the desktop\" mode: #{info[:showing_desktop]}"
194
+ else
195
+ puts "Not implemented."
196
+ exit(1)
197
+ end
@@ -53,7 +53,7 @@ static Window get_target_window (Display *disp, VALUE obj);
53
53
  static VALUE rb_wmctrl_class, key_id, key_title, key_pid, key_geometry,
54
54
  key_active, key_class, key_client_machine, key_desktop,
55
55
  key_viewport, key_workarea, key_current, key_showing_desktop, key_name,
56
- key_state, key_frame_extents, key_strut;
56
+ key_state, key_frame_extents, key_strut, key_exterior_frame;
57
57
 
58
58
  static ID id_select, id_active, id_activate, id_close, id_move_resize,
59
59
  id_change_state, id_move_to_desktop, id_move_to_current,
@@ -318,7 +318,7 @@ static VALUE rb_wmctrl_list_windows (int argc, VALUE *argv, VALUE self) {
318
318
 
319
319
  /* geometry */
320
320
  XGetGeometry (disp, client_list[i], &junkroot, &junkx, &junky, &wwidth, &wheight, &bw, &depth);
321
- XTranslateCoordinates (disp, client_list[i], junkroot, junkx, junky, &x, &y, &junkroot);
321
+ XTranslateCoordinates (disp, client_list[i], junkroot, -bw, -bw, &x, &y, &junkroot);
322
322
 
323
323
  rb_hash_aset(window_obj, key_geometry,
324
324
  rb_ary_new3(4, INT2NUM(x), INT2NUM(y), INT2NUM(wwidth), INT2NUM(wheight)));
@@ -345,6 +345,13 @@ static VALUE rb_wmctrl_list_windows (int argc, VALUE *argv, VALUE self) {
345
345
  for (j = 0; j < extents_size / sizeof(unsigned long); j++) {
346
346
  rb_ary_push(extents_ary, ULONG2NUM(extents[j]));
347
347
  }
348
+ /* exterior frame */
349
+ if (extents) {
350
+ rb_hash_aset(window_obj, key_exterior_frame,
351
+ rb_ary_new3(4, INT2NUM(x - (int)extents[0]), INT2NUM(y - (int)extents[2]),
352
+ INT2NUM(wwidth + (int)extents[0] + (int)extents[1]),
353
+ INT2NUM(wheight + (int)extents[2] + (int)extents[3])));
354
+ }
348
355
  g_free(extents);
349
356
  } else {
350
357
  extents_ary = Qnil;
@@ -806,7 +813,7 @@ static int window_move_resize (Display *disp, Window win, signed long grav,
806
813
  if (w != -1) grflags |= (1 << 10);
807
814
  if (h != -1) grflags |= (1 << 11);
808
815
 
809
- p_verbose("grflags: %lu\n", grflags);
816
+ p_verbose("move_resize: %lu %ld %ld %ld %ld\n", grflags, x, y, w, h);
810
817
 
811
818
  if (wm_supports(disp, "_NET_MOVERESIZE_WINDOW")){
812
819
  return client_msg(disp, win, "_NET_MOVERESIZE_WINDOW",
@@ -1101,65 +1108,6 @@ static Window get_target_window (Display *disp, VALUE obj)
1101
1108
  return wid;
1102
1109
  }
1103
1110
 
1104
- /* static int action_window_str (Display *disp) { */
1105
- /* Window activate = 0; */
1106
- /* Window *client_list; */
1107
- /* unsigned long client_list_size; */
1108
- /* int i; */
1109
-
1110
- /* if ((client_list = get_client_list(disp, &client_list_size)) != NULL) { */
1111
- /* for (i = 0; i < client_list_size / sizeof(Window); i++) { */
1112
- /* gchar *match_utf8; */
1113
- /* if (options.show_class) { */
1114
- /* match_utf8 = get_window_class(disp, client_list[i]); /\* UTF8 *\/ */
1115
- /* } */
1116
- /* else { */
1117
- /* match_utf8 = get_window_title(disp, client_list[i]); /\* UTF8 *\/ */
1118
- /* } */
1119
- /* if (match_utf8) { */
1120
- /* gchar *match; */
1121
- /* gchar *match_cf; */
1122
- /* gchar *match_utf8_cf = NULL; */
1123
- /* if (envir_utf8) { */
1124
- /* match = g_strdup(options.param_window); */
1125
- /* match_cf = g_utf8_casefold(options.param_window, -1); */
1126
- /* } */
1127
- /* else { */
1128
- /* if (! (match = g_locale_to_utf8(options.param_window, -1, NULL, NULL, NULL))) { */
1129
- /* match = g_strdup(options.param_window); */
1130
- /* } */
1131
- /* match_cf = g_utf8_casefold(match, -1); */
1132
- /* } */
1133
-
1134
- /* if (!match || !match_cf) { */
1135
- /* continue; */
1136
- /* } */
1137
-
1138
- /* match_utf8_cf = g_utf8_casefold(match_utf8, -1); */
1139
-
1140
- /* if ((options.full_window_title_match && strcmp(match_utf8, match) == 0) || */
1141
- /* (!options.full_window_title_match && strstr(match_utf8_cf, match_cf))) { */
1142
- /* activate = client_list[i]; */
1143
- /* g_free(match); */
1144
- /* g_free(match_cf); */
1145
- /* g_free(match_utf8); */
1146
- /* g_free(match_utf8_cf); */
1147
- /* break; */
1148
- /* } */
1149
- /* g_free(match); */
1150
- /* g_free(match_cf); */
1151
- /* g_free(match_utf8); */
1152
- /* g_free(match_utf8_cf); */
1153
- /* } */
1154
- /* g_free(client_list); */
1155
- /* if (activate) { */
1156
- /* break; */
1157
- /* } */
1158
- /* } */
1159
- /* } */
1160
- /* return activate; */
1161
- /* } */
1162
-
1163
1111
  /*
1164
1112
  call-seq:
1165
1113
  wm.action_window(wid, cmd, *args)
@@ -1281,6 +1229,7 @@ void Init_wmctrl()
1281
1229
  key_state = ID2SYM(rb_intern("state"));
1282
1230
  key_frame_extents = ID2SYM(rb_intern("frame_extents"));
1283
1231
  key_strut = ID2SYM(rb_intern("strut"));
1232
+ key_exterior_frame = ID2SYM(rb_intern("exterior_frame"));
1284
1233
 
1285
1234
  id_active = rb_intern("active");
1286
1235
  id_select = rb_intern("select");
@@ -1,3 +1,3 @@
1
1
  class WMCtrl
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-wmctrl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-18 00:00:00.000000000 Z
12
+ date: 2011-09-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &9960620 !ruby/object:Gem::Requirement
16
+ requirement: &7241240 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *9960620
24
+ version_requirements: *7241240
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: yard
27
- requirement: &9960120 !ruby/object:Gem::Requirement
27
+ requirement: &7240760 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *9960120
35
+ version_requirements: *7240760
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: pkg-config
38
- requirement: &9959580 !ruby/object:Gem::Requirement
38
+ requirement: &7240220 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,12 +43,13 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *9959580
46
+ version_requirements: *7240220
47
47
  description: Ruby bindings to control windows in EWMH and NetWM compatible X Window
48
48
  manager, which is created from source code of wmctrl command.
49
49
  email:
50
50
  - d@ytak.info
51
- executables: []
51
+ executables:
52
+ - rwmctrl
52
53
  extensions:
53
54
  - ext/extconf.rb
54
55
  extra_rdoc_files: []
@@ -59,6 +60,7 @@ files:
59
60
  - Gemfile
60
61
  - README.md
61
62
  - Rakefile
63
+ - bin/rwmctrl
62
64
  - ext/extconf.rb
63
65
  - ext/wmctrl.c
64
66
  - lib/wmctrl.rb