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 +5 -5
- data/ext/extconf.rb +2 -1
- data/ext/wmctrl.c +188 -171
- data/lib/wmctrl/version.rb +1 -1
- data/lib/wmctrl/wmctrl.rb +59 -7
- data/spec/wmctrl_spec.rb +7 -7
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 64b85024233d08a600bd914867fcf4e3250aa4c21e8ec45eb7bf31644c3a317c
|
4
|
+
data.tar.gz: d42e156ef9c64fd3b43664b3cc4738295528541c12cae7dd7d4897c34e9496e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b83996d39afbf0b47c6b964673f0a147ac6dc10d49670f3dfac051092fb45684e9e114ec07378034e443b04c539fff7bb7cc564773484efc8931dc771b8e134b
|
7
|
+
data.tar.gz: 412805d6b06f93ba5fad169dc2192204cdfcbb410778c1459421a11c6d3d5891d9f6aab9507f265d96abd4342af2f8603ff6959936448794ad8d56e954e734f7
|
data/ext/extconf.rb
CHANGED
@@ -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
|
data/ext/wmctrl.c
CHANGED
@@ -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
|
39
|
-
static
|
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
|
42
|
-
|
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
|
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
|
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
|
872
|
+
return Qtrue;
|
857
873
|
}
|
858
874
|
|
859
|
-
static
|
875
|
+
static VALUE close_window (Display *disp, Window win)
|
860
876
|
{
|
861
|
-
|
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
|
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
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
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
|
938
|
+
return Qtrue;
|
916
939
|
}
|
917
940
|
}
|
918
941
|
|
919
|
-
static
|
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
|
-
|
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
|
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
|
-
|
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 (
|
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
|
-
|
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 (
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
@
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
@
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
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
|
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
|
-
|
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
|
-
|
1215
|
+
if (argc == 0) {
|
1216
|
+
return activate_window(disp, win, TRUE);
|
1217
|
+
}
|
1230
1218
|
} else if (sym_id == id_close) {
|
1231
|
-
|
1219
|
+
if (argc == 0) {
|
1220
|
+
return close_window(disp, win);
|
1221
|
+
}
|
1232
1222
|
} else if (sym_id == id_move_resize) {
|
1233
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
}
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
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"));
|
data/lib/wmctrl/version.rb
CHANGED
data/lib/wmctrl/wmctrl.rb
CHANGED
@@ -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?(
|
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,
|
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.
|
152
|
-
#
|
153
|
-
|
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
|
data/spec/wmctrl_spec.rb
CHANGED
@@ -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.
|
14
|
+
expect(wins).to be_an_instance_of Array
|
15
15
|
wins.each do |w|
|
16
|
-
w.
|
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.
|
22
|
+
expect(desktops).to be_an_instance_of Array
|
23
23
|
desktops.each do |w|
|
24
|
-
w.
|
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.
|
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.
|
34
|
+
expect(sp).to be_an_instance_of Array
|
35
35
|
sp.each do |prop|
|
36
|
-
prop.
|
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.
|
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:
|
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.
|
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:
|