ruby-wmctrl 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4cf9848c86b0484717aa10282cad3b80d6fe4ea7
4
- data.tar.gz: 893e41f4b1da558a574473149ba4109a1a13f351
2
+ SHA256:
3
+ metadata.gz: 64b85024233d08a600bd914867fcf4e3250aa4c21e8ec45eb7bf31644c3a317c
4
+ data.tar.gz: d42e156ef9c64fd3b43664b3cc4738295528541c12cae7dd7d4897c34e9496e4
5
5
  SHA512:
6
- metadata.gz: b208af445e7333c390ea5ef42780e8f9738070520599ce4ee1957b09c5e130b8393ff0572f3ac5c933cf6bcd22d0ebc27e710af0d07e914c9488f0a62ac9a544
7
- data.tar.gz: 8286f7c16f86ffad0169ede09ce432a926fca52d8bc02e5c63121c089711b1d035ee8d0114606567be12458ec21eaefc15cee8dd2cd6e3aa619cf35ad0ce480d
6
+ metadata.gz: b83996d39afbf0b47c6b964673f0a147ac6dc10d49670f3dfac051092fb45684e9e114ec07378034e443b04c539fff7bb7cc564773484efc8931dc771b8e134b
7
+ data.tar.gz: 412805d6b06f93ba5fad169dc2192204cdfcbb410778c1459421a11c6d3d5891d9f6aab9507f265d96abd4342af2f8603ff6959936448794ad8d56e954e734f7
@@ -8,6 +8,7 @@ $CFLAGS << " " << glib.cflags
8
8
  $libs << " " << glib.libs
9
9
 
10
10
  dir_config("X11")
11
- if have_header('X11/Xlib.h') && have_library('X11')
11
+ if have_header('X11/Xlib.h') && have_library('X11') &&
12
+ have_header('X11/Xmu/WinUtil.h') && have_library('Xmu')
12
13
  create_makefile("wmctrl")
13
14
  end
@@ -35,16 +35,13 @@ static gchar *get_property (Display *disp, Window win,
35
35
  static Window *get_client_list (Display *disp, unsigned long *size);
36
36
  static gchar *get_window_class (Display *disp, Window win);
37
37
  static gchar *get_window_title (Display *disp, Window win);
38
- static int activate_window (Display *disp, Window win, gboolean switch_desktop);
39
- static int close_window (Display *disp, Window win);
38
+ static VALUE activate_window (Display *disp, Window win, gboolean switch_desktop);
39
+ static VALUE close_window (Display *disp, Window win);
40
40
  static gboolean wm_supports (Display *disp, const gchar *prop);
41
- static int window_move_resize (Display *disp, Window win, signed long grav,
42
- signed long x, signed long y, signed long w, signed long h);
43
- static int window_state (Display *disp, Window win,
44
- const char *action_str, const char *prop1_str, const char *prop2_str);
41
+ static VALUE window_move_resize (Display *disp, Window win, signed long grav, signed long x, signed long y, signed long w, signed long h);
42
+ static VALUE change_window_state (Display *disp, Window win, const char *action_str, const char *prop1_str, const char *prop2_str);
45
43
  static int window_to_desktop (Display *disp, Window win, int desktop);
46
- static void window_set_title (Display *disp, Window win, char *title, char mode);
47
- static int action_window (Display *disp, Window win, char mode, int argc, VALUE *argv);
44
+ static VALUE window_set_title (Display *disp, Window win, char *title, ID sym_id);
48
45
  static Window Select_Window(Display *dpy);
49
46
  static Window get_active_window(Display *disp);
50
47
  static Window get_target_window (Display *disp, VALUE obj);
@@ -53,7 +50,7 @@ static Window get_target_window (Display *disp, VALUE obj);
53
50
  static VALUE rb_wmctrl_class, key_id, key_title, key_pid, key_geometry,
54
51
  key_active, key_class, key_client_machine, key_desktop,
55
52
  key_viewport, key_workarea, key_current, key_showing_desktop, key_name,
56
- key_state, key_frame_extents, key_strut, key_exterior_frame;
53
+ key_state, key_window_type, key_frame_extents, key_strut, key_exterior_frame;
57
54
 
58
55
  static ID id_select, id_active, id_activate, id_close, id_move_resize,
59
56
  id_change_state, id_move_to_desktop, id_move_to_current,
@@ -283,6 +280,10 @@ static VALUE get_window_hash_data (Window win, Display *disp, Window window_acti
283
280
  Atom *window_state;
284
281
  gchar *state_name;
285
282
  VALUE state_ary;
283
+ unsigned long window_type_size;
284
+ Atom *window_type;
285
+ gchar *window_type_name;
286
+ VALUE window_type_ary;
286
287
  Atom *extents;
287
288
  unsigned long extents_size;
288
289
  VALUE extents_ary;
@@ -317,6 +318,21 @@ static VALUE get_window_hash_data (Window win, Display *disp, Window window_acti
317
318
  }
318
319
  rb_hash_aset(window_obj, key_state, state_ary);
319
320
 
321
+ /* window type */
322
+ if ((window_type = (Atom *)get_property(disp, win,
323
+ XA_ATOM, "_NET_WM_WINDOW_TYPE", &window_type_size)) != NULL) {
324
+ window_type_ary = rb_ary_new();
325
+ for (j = 0; j < window_type_size / sizeof(Atom); j++) {
326
+ window_type_name = XGetAtomName(disp, window_type[j]);
327
+ rb_ary_push(window_type_ary, rb_str_new2(window_type_name));
328
+ g_free(window_type_name);
329
+ }
330
+ g_free(window_type);
331
+ } else {
332
+ window_type_ary = Qnil;
333
+ }
334
+ rb_hash_aset(window_obj, key_window_type, window_type_ary);
335
+
320
336
  /* frame extents */
321
337
  if ((extents = (unsigned long *)get_property(disp, win,
322
338
  XA_CARDINAL, "_NET_FRAME_EXTENTS", &extents_size)) != NULL) {
@@ -828,7 +844,7 @@ static VALUE rb_wmctrl_change_number_of_desktops (VALUE self, VALUE num) {
828
844
  return Qtrue;
829
845
  }
830
846
 
831
- static int activate_window (Display *disp, Window win, gboolean switch_desktop)
847
+ static VALUE activate_window (Display *disp, Window win, gboolean switch_desktop)
832
848
  {
833
849
  unsigned long *desktop;
834
850
 
@@ -853,12 +869,15 @@ static int activate_window (Display *disp, Window win, gboolean switch_desktop)
853
869
  client_msg(disp, win, "_NET_ACTIVE_WINDOW", 0, 0, 0, 0, 0);
854
870
  XMapRaised(disp, win);
855
871
 
856
- return True;
872
+ return Qtrue;
857
873
  }
858
874
 
859
- static int close_window (Display *disp, Window win)
875
+ static VALUE close_window (Display *disp, Window win)
860
876
  {
861
- return client_msg(disp, win, "_NET_CLOSE_WINDOW", 0, 0, 0, 0, 0);
877
+ if (client_msg(disp, win, "_NET_CLOSE_WINDOW", 0, 0, 0, 0, 0)) {
878
+ return Qtrue;
879
+ }
880
+ return Qfalse;
862
881
  }
863
882
 
864
883
  static gboolean wm_supports (Display *disp, const gchar *prop)
@@ -885,39 +904,42 @@ static gboolean wm_supports (Display *disp, const gchar *prop)
885
904
  return FALSE;
886
905
  }
887
906
 
888
- static int window_move_resize (Display *disp, Window win, signed long grav,
889
- signed long x, signed long y, signed long w, signed long h)
907
+ static VALUE window_move_resize (Display *disp, Window win, signed long grav, signed long x, signed long y, signed long w, signed long h)
890
908
  {
891
- unsigned long grflags;
892
- grflags = grav;
893
- if (x != -1) grflags |= (1 << 8);
894
- if (y != -1) grflags |= (1 << 9);
895
- if (w != -1) grflags |= (1 << 10);
896
- if (h != -1) grflags |= (1 << 11);
897
-
898
- p_verbose("move_resize: %lu %ld %ld %ld %ld\n", grflags, x, y, w, h);
899
-
900
- if (wm_supports(disp, "_NET_MOVERESIZE_WINDOW")){
901
- return client_msg(disp, win, "_NET_MOVERESIZE_WINDOW",
902
- grflags, (unsigned long)x, (unsigned long)y, (unsigned long)w, (unsigned long)h);
903
- }
904
- else {
909
+ p_verbose("move_resize: %lu %ld %ld %ld %ld\n", grav, x, y, w, h);
910
+ if ((grav >= 0) && wm_supports(disp, "_NET_MOVERESIZE_WINDOW")) {
911
+ unsigned long grflags;
912
+ grflags = grav;
913
+ if (x != -1) {
914
+ grflags |= (1 << 8);
915
+ }
916
+ if (y != -1) {
917
+ grflags |= (1 << 9);
918
+ }
919
+ if (w != -1) {
920
+ grflags |= (1 << 10);
921
+ }
922
+ if (h != -1) {
923
+ grflags |= (1 << 11);
924
+ }
925
+ if (client_msg(disp, win, "_NET_MOVERESIZE_WINDOW", grflags, (unsigned long) x, (unsigned long) y, (unsigned long) w, (unsigned long) h)) {
926
+ return Qtrue;
927
+ }
928
+ return Qfalse;
929
+ } else {
905
930
  p_verbose("WM doesn't support _NET_MOVERESIZE_WINDOW. Gravity will be ignored.\n");
906
931
  if ((w < 1 || h < 1) && (x >= 0 && y >= 0)) {
907
932
  XMoveWindow(disp, win, x, y);
908
- }
909
- else if ((x < 0 || y < 0) && (w >= 1 && h >= -1)) {
933
+ } else if ((x < 0 || y < 0) && (w >= 1 && h >= -1)) {
910
934
  XResizeWindow(disp, win, w, h);
911
- }
912
- else if (x >= 0 && y >= 0 && w >= 1 && h >= 1) {
935
+ } else if (x >= 0 && y >= 0 && w >= 1 && h >= 1) {
913
936
  XMoveResizeWindow(disp, win, x, y, w, h);
914
937
  }
915
- return EXIT_SUCCESS;
938
+ return Qtrue;
916
939
  }
917
940
  }
918
941
 
919
- static int window_state (Display *disp, Window win,
920
- const char *action_str, const char *prop1_str, const char *prop2_str)
942
+ static VALUE change_window_state (Display *disp, Window win, const char *action_str, const char *prop1_str, const char *prop2_str)
921
943
  {
922
944
  unsigned long action;
923
945
  Atom prop1 = 0;
@@ -927,14 +949,11 @@ static int window_state (Display *disp, Window win,
927
949
  /* action */
928
950
  if (strcmp(action_str, "remove") == 0) {
929
951
  action = _NET_WM_STATE_REMOVE;
930
- }
931
- else if (strcmp(action_str, "add") == 0) {
952
+ } else if (strcmp(action_str, "add") == 0) {
932
953
  action = _NET_WM_STATE_ADD;
933
- }
934
- else if (strcmp(action_str, "toggle") == 0) {
954
+ } else if (strcmp(action_str, "toggle") == 0) {
935
955
  action = _NET_WM_STATE_TOGGLE;
936
- }
937
- else {
956
+ } else {
938
957
  rb_raise(rb_eArgError, "Invalid action. Use either remove, add or toggle.");
939
958
  }
940
959
 
@@ -953,7 +972,10 @@ static int window_state (Display *disp, Window win,
953
972
  g_free(tmp2);
954
973
  g_free(tmp_prop2);
955
974
  }
956
- return client_msg(disp, win, "_NET_WM_STATE", action, (unsigned long)prop1, (unsigned long)prop2, 0, 0);
975
+ if (client_msg(disp, win, "_NET_WM_STATE", action, (unsigned long) prop1, (unsigned long) prop2, 0, 0)) {
976
+ return Qtrue;
977
+ }
978
+ return Qnil;
957
979
  }
958
980
 
959
981
  static int window_to_desktop (Display *disp, Window win, int desktop)
@@ -979,7 +1001,7 @@ static int window_to_desktop (Display *disp, Window win, int desktop)
979
1001
  return client_msg(disp, win, "_NET_WM_DESKTOP", (unsigned long)desktop, 0, 0, 0, 0);
980
1002
  }
981
1003
 
982
- static void window_set_title (Display *disp, Window win, char *title, char mode)
1004
+ static VALUE window_set_title (Display *disp, Window win, char *title, ID sym_id)
983
1005
  {
984
1006
  gchar *title_utf8;
985
1007
  gchar *title_local;
@@ -987,109 +1009,38 @@ static void window_set_title (Display *disp, Window win, char *title, char mode)
987
1009
  if (envir_utf8) {
988
1010
  title_utf8 = g_strdup(title);
989
1011
  title_local = NULL;
990
- }
991
- else {
992
- if (! (title_utf8 = g_locale_to_utf8(title, -1, NULL, NULL, NULL))) {
1012
+ } else {
1013
+ if (!(title_utf8 = g_locale_to_utf8(title, -1, NULL, NULL, NULL))) {
993
1014
  title_utf8 = g_strdup(title);
994
1015
  }
995
1016
  title_local = g_strdup(title);
996
1017
  }
997
1018
 
998
- if (mode == 'T' || mode == 'N') {
1019
+ if ((sym_id == id_set_title_both) || (sym_id == id_set_title_long)) {
999
1020
  /* set name */
1000
1021
  if (title_local) {
1001
- XChangeProperty(disp, win, XA_WM_NAME, XA_STRING, 8, PropModeReplace,
1002
- (const unsigned char *)title_local, strlen(title_local));
1003
- }
1004
- else {
1022
+ XChangeProperty(disp, win, XA_WM_NAME, XA_STRING, 8, PropModeReplace, (const unsigned char *) title_local, strlen(title_local));
1023
+ } else {
1005
1024
  XDeleteProperty(disp, win, XA_WM_NAME);
1006
1025
  }
1007
- XChangeProperty(disp, win, XInternAtom(disp, "_NET_WM_NAME", False),
1008
- XInternAtom(disp, "UTF8_STRING", False), 8, PropModeReplace,
1009
- (const unsigned char *)title_utf8, strlen(title_utf8));
1026
+ XChangeProperty(disp, win, XInternAtom(disp, "_NET_WM_NAME", False), XInternAtom(disp, "UTF8_STRING", False), 8, PropModeReplace, (const unsigned char *) title_utf8, strlen(title_utf8));
1010
1027
  }
1011
1028
 
1012
- if (mode == 'T' || mode == 'I') {
1029
+ if ((sym_id == id_set_title_both) || (sym_id == id_set_title_short)) {
1013
1030
  /* set icon name */
1014
1031
  if (title_local) {
1015
- XChangeProperty(disp, win, XA_WM_ICON_NAME, XA_STRING, 8, PropModeReplace,
1016
- (const unsigned char *)title_local, strlen(title_local));
1017
- }
1018
- else {
1032
+ XChangeProperty(disp, win, XA_WM_ICON_NAME, XA_STRING, 8, PropModeReplace, (const unsigned char *) title_local, strlen(title_local));
1033
+ } else {
1019
1034
  XDeleteProperty(disp, win, XA_WM_ICON_NAME);
1020
1035
  }
1021
- XChangeProperty(disp, win, XInternAtom(disp, "_NET_WM_ICON_NAME", False),
1022
- XInternAtom(disp, "UTF8_STRING", False), 8, PropModeReplace,
1023
- (const unsigned char *)title_utf8, strlen(title_utf8));
1036
+ XChangeProperty(disp, win, XInternAtom(disp, "_NET_WM_ICON_NAME", False), XInternAtom(disp, "UTF8_STRING", False), 8, PropModeReplace, (const unsigned char *) title_utf8, strlen(title_utf8));
1024
1037
  }
1025
1038
 
1026
1039
  g_free(title_utf8);
1027
- g_free(title_local);
1028
- }
1029
-
1030
- static int action_window (Display *disp, Window win, char mode, int argc, VALUE *argv)
1031
- {
1032
- p_verbose("Using window: 0x%.8lx\n", win);
1033
- switch (mode) {
1034
- case 'a':
1035
- if (argc == 0) {
1036
- return activate_window(disp, win, TRUE);
1037
- }
1038
- case 'c':
1039
- if (argc == 0) {
1040
- return close_window(disp, win);
1041
- }
1042
- case 'e':
1043
- /* resize/move the window around the desktop => -r -e */
1044
- if (argc == 5) {
1045
- int grav, x, y, w, h;
1046
- grav = FIX2INT(argv[0]);
1047
- x = FIX2INT(argv[1]);
1048
- y = FIX2INT(argv[2]);
1049
- w = FIX2INT(argv[3]);
1050
- h = FIX2INT(argv[4]);
1051
- if (grav >= 0) {
1052
- return window_move_resize(disp, win, grav, x, y, w, h);
1053
- }
1054
- }
1055
- break;
1056
- case 'b':
1057
- /* change state of a window => -r -b */
1058
- if (argc == 2 || argc == 3) {
1059
- const char *action, *prop1, *prop2;
1060
- action = StringValuePtr(argv[0]);
1061
- prop1 = StringValuePtr(argv[1]);
1062
- if (argc == 3) {
1063
- prop2 = StringValuePtr(argv[2]);
1064
- } else {
1065
- prop2 = NULL;
1066
- }
1067
- return window_state(disp, win, action, prop1, prop2);
1068
- }
1069
- case 't':
1070
- /* move the window to the specified desktop => -r -t */
1071
- if (argc == 1) {
1072
- return window_to_desktop(disp, win, FIX2INT(argv[0]));
1073
- }
1074
- case 'R':
1075
- /* move the window to the current desktop and activate it => -r */
1076
- if (argc == 0) {
1077
- if (window_to_desktop(disp, win, -1)) {
1078
- usleep(100000); /* 100 ms - make sure the WM has enough
1079
- time to move the window, before we activate it */
1080
- return activate_window(disp, win, FALSE);
1081
- }
1082
- else {
1083
- return False;
1084
- }
1085
- }
1086
- case 'N': case 'I': case 'T':
1087
- if (argc == 1) {
1088
- window_set_title(disp, win, StringValuePtr(argv[0]), mode);
1089
- return True;
1090
- }
1040
+ if (title_local) {
1041
+ g_free(title_local);
1091
1042
  }
1092
- rb_raise(rb_eArgError, "Invalid argument of action_window.");
1043
+ return Qtrue;
1093
1044
  }
1094
1045
 
1095
1046
  static Window Select_Window(Display *dpy)
@@ -1191,31 +1142,63 @@ static Window get_target_window (Display *disp, VALUE obj)
1191
1142
  }
1192
1143
 
1193
1144
  /*
1194
- @overload action_window(wid, cmd, *args)
1195
-
1196
- Manage windows.
1197
- @param wid Window ID
1198
- @param cmd [Symbol] Symbol of command
1199
- @param args [Array] Arguments for the command
1200
-
1201
- @return [boolean] true if succeeded. Otherwise, false.
1202
-
1203
- @example
1204
- wm.action_window(wid, :activate)
1205
- wm.action_window(wid, :close)
1206
- wm.action_window(wid, :move_resize, grav, x, y, w, h)
1207
- wm.action_window(wid, :change_state, add, prop1, prop2 = nil)
1208
- wm.action_window(wid, :change_state, remove, prop1, prop2 = nil)
1209
- wm.action_window(wid, :change_state, toggle, prop1, prop2 = nil)
1210
- wm.action_window(wid, :move_to_desktop, desktop_id)
1211
- wm.action_window(wid, :move_to_current)
1212
- wm.action_window(wid, :set_title_long, str)
1213
- wm.action_window(wid, :set_title_short, str)
1214
- wm.action_window(wid, :set_title_both, str)
1145
+ Manage a window.
1146
+ @overload action_window(wid, :activate)
1147
+ Activate a window.
1148
+ @param [Integer] wid Window ID
1149
+ @return [boolean] true if succeeded. Otherwise, false.
1150
+ @overload action_window(wid, :close)
1151
+ Close a window
1152
+ @param [Integer] wid Window ID
1153
+ @return [boolean] true if succeeded. Otherwise, false.
1154
+ @overload action_window(wid, :move_resize, grav, x, y, w, h)
1155
+ @param [Integer] wid Window ID
1156
+ @param [Integer] grav Gravity
1157
+ @param [Integer] x X coordinate
1158
+ @param [Integer] y Y coordinate
1159
+ @param [Integer] w Width
1160
+ @param [Integer] h Height
1161
+ @return [boolean] true if succeeded. Otherwise, false.
1162
+ @overload action_window(wid, :change_state, "add", prop1, prop2 = nil)
1163
+ @param [Integer] wid Window ID
1164
+ @param [String] prop1 String of _NET_WM_STATE type.
1165
+ @param [String] prop2 String of _NET_WM_STATE type.
1166
+ @return [boolean] true if succeeded. Otherwise, false.
1167
+ @overload action_window(wid, :change_state, "remove", prop1, prop2 = nil)
1168
+ @param [Integer] wid Window ID
1169
+ @param [String] prop1 String of _NET_WM_STATE type.
1170
+ @param [String] prop2 String of _NET_WM_STATE type.
1171
+ @return [boolean] true if succeeded. Otherwise, false.
1172
+ @overload action_window(wid, :change_state, "toggle", prop1, prop2 = nil)
1173
+ @param [Integer] wid Window ID
1174
+ @param [String] prop1 String of _NET_WM_STATE type.
1175
+ @param [String] prop2 String of _NET_WM_STATE type.
1176
+ @return [boolean] true if succeeded. Otherwise, false.
1177
+ @overload action_window(wid, :move_to_desktop, desktop_id)
1178
+ @param [Integer] wid Window ID
1179
+ @param [Integer] desktop_id Desktop ID
1180
+ @return [boolean] true if succeeded. Otherwise, false.
1181
+ @overload action_window(wid, :move_to_current)
1182
+ @param [Integer] wid Window ID
1183
+ @return [boolean] true if succeeded. Otherwise, false.
1184
+ @overload action_window(wid, :set_title_long, str)
1185
+ @param [Integer] wid Window ID
1186
+ @return [boolean] true if succeeded. Otherwise, false.
1187
+ @overload action_window(wid, :set_title_short, str)
1188
+ @param [Integer] wid Window ID
1189
+ @return [boolean] true if succeeded. Otherwise, false.
1190
+ @overload action_window(wid, :set_title_both, str)
1191
+ @param [Integer] wid Window ID
1192
+ @return [boolean] true if succeeded. Otherwise, false.
1193
+
1194
+ @note
1195
+ The arguments of prop1 and prop2 for :change_state command are strings
1196
+ that mean type of _NET_WM_STATE.
1197
+ For example, For example, we use "modal" or "MODAL" for _NET_WM_STATE_MODAL.
1198
+ See also http://standards.freedesktop.org/wm-spec/wm-spec-latest.html
1215
1199
  */
1216
1200
  static VALUE rb_wmctrl_action_window(int argc, VALUE *argv, VALUE self) {
1217
- Window wid;
1218
- int mode;
1201
+ Window win;
1219
1202
  ID sym_id;
1220
1203
  Display **ptr, *disp;
1221
1204
  Data_Get_Struct(self, Display*, ptr);
@@ -1223,34 +1206,67 @@ static VALUE rb_wmctrl_action_window(int argc, VALUE *argv, VALUE self) {
1223
1206
  if (argc < 2) {
1224
1207
  rb_raise(rb_eArgError, "Need more than one argument.");
1225
1208
  }
1226
- wid = get_target_window(disp, argv[0]);
1209
+ win = get_target_window(disp, argv[0]);
1227
1210
  sym_id = SYM2ID(argv[1]);
1211
+ argc = argc - 2;
1212
+ argv = argv + 2;
1213
+ p_verbose("Using window: 0x%.8lx\n", win);
1228
1214
  if (sym_id == id_activate) {
1229
- mode = 'a';
1215
+ if (argc == 0) {
1216
+ return activate_window(disp, win, TRUE);
1217
+ }
1230
1218
  } else if (sym_id == id_close) {
1231
- mode = 'c';
1219
+ if (argc == 0) {
1220
+ return close_window(disp, win);
1221
+ }
1232
1222
  } else if (sym_id == id_move_resize) {
1233
- mode = 'e';
1223
+ /* resize/move the window around the desktop => -r -e */
1224
+ if (argc == 5) {
1225
+ int grav, x, y, w, h;
1226
+ grav = FIX2INT(argv[0]);
1227
+ x = FIX2INT(argv[1]);
1228
+ y = FIX2INT(argv[2]);
1229
+ w = FIX2INT(argv[3]);
1230
+ h = FIX2INT(argv[4]);
1231
+ return window_move_resize(disp, win, grav, x, y, w, h);
1232
+ }
1234
1233
  } else if (sym_id == id_change_state) {
1235
- mode = 'b';
1234
+ /* change state of a window => -r -b */
1235
+ if (argc == 2 || argc == 3) {
1236
+ const char *action, *prop1, *prop2;
1237
+ action = StringValuePtr(argv[0]);
1238
+ prop1 = StringValuePtr(argv[1]);
1239
+ if (argc == 3) {
1240
+ prop2 = StringValuePtr(argv[2]);
1241
+ } else {
1242
+ prop2 = NULL;
1243
+ }
1244
+ return change_window_state(disp, win, action, prop1, prop2);
1245
+ }
1236
1246
  } else if (sym_id == id_move_to_desktop) {
1237
- mode = 't';
1247
+ /* move the window to the specified desktop => -r -t */
1248
+ if (argc == 1) {
1249
+ if (window_to_desktop(disp, win, FIX2INT(argv[0]))) {
1250
+ return Qtrue;
1251
+ }
1252
+ return Qfalse;
1253
+ }
1238
1254
  } else if (sym_id == id_move_to_current) {
1239
- mode = 'R';
1240
- } else if (sym_id == id_set_title_long) {
1241
- mode = 'N';
1242
- } else if (sym_id == id_set_title_short) {
1243
- mode = 'I';
1244
- } else if (sym_id == id_set_title_both) {
1245
- mode = 'T';
1246
- } else {
1247
- rb_raise(rb_eStandardError, "Invalid argument of action_window.");
1248
- }
1249
- if (action_window(disp, wid, mode, argc - 2, (argv + 2))) {
1250
- return Qtrue;
1251
- } else {
1252
- return Qfalse;
1255
+ /* move the window to the current desktop and activate it => -r */
1256
+ if (argc == 0) {
1257
+ if (window_to_desktop(disp, win, -1)) {
1258
+ usleep(100000);
1259
+ /* 100 ms - make sure the WM has enough time to move the window, before we activate it */
1260
+ return activate_window(disp, win, FALSE);
1261
+ }
1262
+ return Qfalse;
1263
+ }
1264
+ } else if (sym_id == id_set_title_long || sym_id == id_set_title_short || sym_id == id_set_title_both) {
1265
+ if (argc == 1) {
1266
+ return window_set_title(disp, win, StringValuePtr(argv[0]), sym_id);
1267
+ }
1253
1268
  }
1269
+ rb_raise(rb_eStandardError, "Invalid argument of action_window.");
1254
1270
  }
1255
1271
 
1256
1272
  /*
@@ -1317,6 +1333,7 @@ void Init_wmctrl()
1317
1333
  key_showing_desktop = ID2SYM(rb_intern("showing_desktop"));
1318
1334
  key_name = ID2SYM(rb_intern("name"));
1319
1335
  key_state = ID2SYM(rb_intern("state"));
1336
+ key_window_type = ID2SYM(rb_intern("window_type"));
1320
1337
  key_frame_extents = ID2SYM(rb_intern("frame_extents"));
1321
1338
  key_strut = ID2SYM(rb_intern("strut"));
1322
1339
  key_exterior_frame = ID2SYM(rb_intern("exterior_frame"));
@@ -1,3 +1,3 @@
1
1
  class WMCtrl
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -1,6 +1,19 @@
1
1
  require 'wmctrl.so'
2
2
 
3
3
  class WMCtrl
4
+ NOT_USE_NET_MOVERESIZE_WINDOW = -1
5
+ GRAVITY_DEFAULT = 0
6
+ GRAVITY_NORTH_WEST = 1
7
+ GRAVITY_NORTH = 2
8
+ GRAVITY_NORTH_EAST = 3
9
+ GRAVITY_WEST = 4
10
+ GRAVITY_CENTER = 5
11
+ GRAVITY_EAST = 6
12
+ GRAVITY_SOUTH_WEST = 7
13
+ GRAVITY_SOUTH = 8
14
+ GRAVITY_SOUTH_EAST = 9
15
+ GRAVITY_STATIC = 10
16
+
4
17
  def self.instance
5
18
  @wmctrl ||= self.new
6
19
  end
@@ -85,10 +98,36 @@ class WMCtrl
85
98
  self[:active]
86
99
  end
87
100
 
88
- STATE_FULLSCREEN = "_NET_WM_STATE_FULLSCREEN"
89
-
90
101
  def fullscreen?
91
- self[:state].include?(STATE_FULLSCREEN)
102
+ self[:state].include?("_NET_WM_STATE_FULLSCREEN")
103
+ end
104
+
105
+ def modal?
106
+ self[:state].include?("_NET_WM_STATE_MODAL")
107
+ end
108
+
109
+ def maximized_vertically?
110
+ self[:state].include?("_NET_WM_STATE_MAXIMIZED_VERT")
111
+ end
112
+
113
+ def maximized_horizontally?
114
+ self[:state].include?("_NET_WM_STATE_MAXIMIZED_HORZ")
115
+ end
116
+
117
+ def shaded?
118
+ self[:state].include?("_NET_WM_STATE_SHADED")
119
+ end
120
+
121
+ def hidden?
122
+ self[:state].include?("_NET_WM_STATE_HIDDEN")
123
+ end
124
+
125
+ def skipped_by_taskbar?
126
+ self[:state].include?("_NET_WM_STATE_SKIP_TASKBAR")
127
+ end
128
+
129
+ def skipped_by_pager?
130
+ self[:state].include?("_NET_WM_STATE_SKIP_PAGER")
92
131
  end
93
132
 
94
133
  def action(*args)
@@ -116,6 +155,9 @@ class WMCtrl
116
155
  # @option opts [Integer] :width Width of window
117
156
  # @option opts [Integer] :height Height of window
118
157
  # @option opts [Integer,:current] :desktop Desktop number
158
+ # @option opts [Integer] :gravity Number meaning gravity: NOT_USE_NET_MOVERESIZE_WINDOW,
159
+ # GRAVITY_DEFAULT, GRAVITY_NORTH_WEST, GRAVITY_NORTH, GRAVITY_NORTH_EAST, GRAVITY_WEST, GRAVITY_CENTER,
160
+ # GRAVITY_EAST, GRAVITY_SOUTH_WEST, GRAVITY_SOUTH, GRAVITY_SOUTH_EAST, GRAVITY_STATIC
119
161
  def place(opts = {})
120
162
  if opts[:desktop]
121
163
  if opts[:desktop] == :current
@@ -124,6 +166,7 @@ class WMCtrl
124
166
  action(:move_to_desktop, opts[:desktop])
125
167
  end
126
168
  end
169
+ gravity = opts[:gravity] || GRAVITY_DEFAULT
127
170
  x = self[:exterior_frame][0]
128
171
  y = self[:exterior_frame][1]
129
172
  width = self[:exterior_frame][2]
@@ -134,7 +177,7 @@ class WMCtrl
134
177
  height = opts[:height] if opts[:height] && (opts[:height] != height)
135
178
  x = opts[:x] if opts[:x] && (opts[:x] != x)
136
179
  y = opts[:y] if opts[:y] && (opts[:y] != y)
137
- action(:move_resize, 0, x + self[:frame_extents][0], y + self[:frame_extents][1], width - extent_horizontal, height - extent_vertical)
180
+ action(:move_resize, gravity, x + self[:frame_extents][0], y + self[:frame_extents][1], width - extent_horizontal, height - extent_vertical)
138
181
  end
139
182
 
140
183
  def position
@@ -148,9 +191,15 @@ class WMCtrl
148
191
  list_desktops.map { |hash| WMCtrl::Desktop.new(hash) }
149
192
  end
150
193
 
151
- # @param [Array] conditions An array of condition hash. The values of hash are tested by the method ===.
152
- # @return [Array] An array of WMCtrl::Window
153
- def windows(*conditions)
194
+ # @param [Array] conditions An array of condition hash.
195
+ # The keys of the hash are keys of WMCtrl::Window#[].
196
+ # The values of the hash are tested by the method ===.
197
+ # Keys of each condition are combined by logical product and
198
+ # all conditions are combined by logical sum.
199
+ # @yield [WMCtrl::Window] Test window by block
200
+ # @return [Array] An array of WMCtrl::Window including windows
201
+ # matched by the conditions and the block.
202
+ def windows(*conditions, &block)
154
203
  wins = list_windows(true).map { |hash| WMCtrl::Window.new(hash) }
155
204
  unless conditions.empty?
156
205
  wins_selected = []
@@ -167,6 +216,9 @@ class WMCtrl
167
216
  end
168
217
  wins = wins_selected
169
218
  end
219
+ if block_given?
220
+ wins.delete_if { |win| !yield(win) }
221
+ end
170
222
  wins
171
223
  end
172
224
  end
@@ -11,29 +11,29 @@ describe WMCtrl do
11
11
 
12
12
  it "should get an array of hashes." do
13
13
  wins = wm.list_windows
14
- wins.should be_an_instance_of Array
14
+ expect(wins).to be_an_instance_of Array
15
15
  wins.each do |w|
16
- w.should be_an_instance_of Hash
16
+ expect(w).to be_an_instance_of Hash
17
17
  end
18
18
  end
19
19
 
20
20
  it "should get an array of hashes." do
21
21
  desktops = wm.list_desktops
22
- desktops.should be_an_instance_of Array
22
+ expect(desktops).to be_an_instance_of Array
23
23
  desktops.each do |w|
24
- w.should be_an_instance_of Hash
24
+ expect(w).to be_an_instance_of Hash
25
25
  end
26
26
  end
27
27
 
28
28
  it "should get information of window manager." do
29
- wm.info.should be_an_instance_of Hash
29
+ expect(wm.info).to be_an_instance_of Hash
30
30
  end
31
31
 
32
32
  it "should get an array." do
33
33
  sp = wm.supported
34
- sp.should be_an_instance_of Array
34
+ expect(sp).to be_an_instance_of Array
35
35
  sp.each do |prop|
36
- prop.should be_an_instance_of String
36
+ expect(prop).to be_an_instance_of String
37
37
  end
38
38
  end
39
39
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-wmctrl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takayuki YAMAGUCHI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-05 00:00:00.000000000 Z
11
+ date: 2018-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -112,9 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
112
  version: '0'
113
113
  requirements: []
114
114
  rubyforge_project:
115
- rubygems_version: 2.0.3
115
+ rubygems_version: 2.7.3
116
116
  signing_key:
117
117
  specification_version: 4
118
118
  summary: Ruby bindings to control windows
119
119
  test_files: []
120
- has_rdoc: