ruby-wmctrl 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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