Class for interaction with windows
Methods
Public Class
Public Instance
Public Instance Aliases
| click | -> | send_button |
Aliases |
Public Class methods
subextWindowInit {{{
Initialize Window object.
win = Subtlext::Window.new(:x => 5, :y => 5) do |w| s.background = "#ffffff" end
VALUE
subextWindowInit(VALUE self,
VALUE value)
{
SubtlextWindow *w = NULL;
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
VALUE geometry = Qnil;
subextSubtlextConnect(NULL); ///< Implicit open connection
/* Check object type */
switch(rb_type(value))
{
case T_HASH:
case T_ARRAY:
{
XSetWindowAttributes sattrs;
XRectangle r = { 0 };
/* Create geometry */
geometry = subextGeometryInstantiate(0, 0, 1, 1);
geometry = subextGeometryInit(1, &value, geometry);
subextGeometryToRect(geometry, &r);
/* Create window */
sattrs.override_redirect = True;
w->win = XCreateWindow(display, DefaultRootWindow(display),
r.x, r.y, r.width, r.height, 1, CopyFromParent,
CopyFromParent, CopyFromParent, CWOverrideRedirect, &sattrs);
}
break;
case T_FIXNUM:
case T_BIGNUM:
{
int x = 0, y = 0;
unsigned int width = 0, height = 0, bw = 0, depth = 0;
Window root = None;
/* Update values */
w->win = FIX2LONG(value);
w->flags |= WINDOW_FOREIGN_WIN;
/* Get window geometry */
if(XGetGeometry(display, w->win, &root,
&x, &y, &width, &height, &bw, &depth))
geometry = subextGeometryInstantiate(x, y, width, height);
else rb_raise(rb_eArgError, "Invalid window `%#lx'", w->win);
}
break;
default: rb_raise(rb_eArgError, "Unexpected value-type `%s'",
rb_obj_classname(value));
}
/* Store data */
rb_iv_set(w->instance, "@win", LONG2NUM(w->win));
rb_iv_set(w->instance, "@geometry", geometry);
rb_iv_set(w->instance, "@hidden", Qtrue);
/* Set window font */
if(!w->font && !(w->font = subSharedFontNew(display, DEFFONT)))
rb_raise(rb_eStandardError, "Invalid font `%s'", DEFFONT);
/* Yield to block if given */
if(rb_block_given_p())
rb_yield_values(1, w->instance);
XSync(display, False); ///< Sync with X
}
return Qnil;
}
Show window once as long as proc runs
Subtlext::Window.once(:x => 10, :y => 10, :widht => 100, :height => 100) do |w| "test" end => "test"
VALUE
subextWindowSingOnce(VALUE self,
VALUE geometry)
{
VALUE win = Qnil, ret = Qnil;
rb_need_block();
/* Create new window */
win = subextWindowInstantiate(geometry);
/* Yield block */
ret = rb_yield_values(1, win);
subextWindowKill(win);
return ret;
}
Public Instance methods
Whether both objects have the same value. Returns -1, 0 or 1 when self is less than, equal to or grater than other. (based on win)
object1 <=> object2 => 0
static VALUE
SubtlextEqualSpaceWindow(VALUE self,
VALUE other)
{
return SubtlextSpaceship(self, other, "@win");
}
Whether both objects have the same values (based on win)
object1 == object2 => true
static VALUE
SubtlextEqualWindow(VALUE self,
VALUE other)
{
return SubtlextEqual(self, other, "@win", False);
}
Get arbitrary persistent property string or symbol value
object["wm"] => "subtle" object[:wm] => "subtle"
static VALUE
SubtlextPropReader(VALUE self,
VALUE key)
{
char *prop = NULL;
VALUE ret = Qnil;
/* Check ruby object */
rb_check_frozen(self);
/* Check object type */
switch(rb_type(key))
{
case T_STRING: prop = RSTRING_PTR(key); break;
case T_SYMBOL: prop = (char *)SYM2CHAR(key); break;
default:
rb_raise(rb_eArgError, "Unexpected key value type `%s'",
rb_obj_classname(key));
return Qnil;
}
/* Check results */
if(prop)
{
char propname[255] = { 0 }, *name = NULL, *result = NULL;
Window win = ROOT;
VALUE val = Qnil;
/* Sanitize property name */
name = strdup(prop);
SubtlextStringify(name);
/* Check object type */
if(rb_obj_is_instance_of(self, rb_const_get(mod, rb_intern("View"))))
{
GET_ATTR(self, "@name", val);
snprintf(propname, sizeof(propname), "SUBTLE_PROPERTY_%s_%s",
RSTRING_PTR(val), name);
}
else ///< Client
{
GET_ATTR(self, "@win", val);
win = NUM2LONG(val);
snprintf(propname, sizeof(propname), "SUBTLE_PROPERTY_%s", name);
}
/* Get actual property */
if((result = subSharedPropertyGet(display, win, XInternAtom(display,
"UTF8_STRING", False), XInternAtom(display, propname, False), NULL)))
{
ret = rb_str_new2(result);
free(result);
}
free(name);
}
return ret;
}
Set arbitrary persistent property string or symbol value
Symbols are implictly converted to string, to remove a property just set it
to nil.
object["wm"] = "subtle" => nil object[:wm] = "subtle" => nil object[:wm] = nil => nil
static VALUE
SubtlextPropWriter(VALUE self,
VALUE key,
VALUE value)
{
VALUE val = Qnil, str = value;
char *prop = NULL, *name = NULL, propname[255] = { 0 };
Window win = ROOT;
/* Check ruby object */
rb_check_frozen(self);
/* Check object type */
switch(rb_type(key))
{
case T_STRING: prop = RSTRING_PTR(key); break;
case T_SYMBOL: prop = (char *)SYM2CHAR(key); break;
default:
rb_raise(rb_eArgError, "Unexpected key value-type `%s'",
rb_obj_classname(key));
return Qnil;
}
/* Sanitize property name */
name = strdup(prop);
SubtlextStringify(name);
/* Assemble property name */
if(rb_obj_is_instance_of(self, rb_const_get(mod, rb_intern("View"))))
{
GET_ATTR(self, "@name", val);
snprintf(propname, sizeof(propname), "SUBTLE_PROPERTY_%s_%s",
RSTRING_PTR(val), name);
}
else ///< Client
{
GET_ATTR(self, "@win", val);
win = NUM2LONG(val);
snprintf(propname, sizeof(propname), "SUBTLE_PROPERTY_%s", name);
}
/* Check value type */
switch(rb_type(value))
{
case T_SYMBOL: str = rb_sym_to_s(value);
case T_STRING:
XChangeProperty(display, win, XInternAtom(display, propname, False),
XInternAtom(display, "UTF8_STRING", False), 8, PropModeReplace,
(unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
break;
case T_NIL:
XDeleteProperty(display, win, XInternAtom(display, propname, False));
break;
default:
rb_raise(rb_eArgError, "Unexpected value value-type `%s'",
rb_obj_classname(value));
}
XSync(display, False); ///< Sync all changes
if(name) free(name);
return Qnil;
}
Set the background color of this Window which can be of following types:
| String |
Any color representation of Xlib is allowed |
| Array |
Must be an array with values for red, green and blue |
| Hash |
Must be a hash with values for red, green and blue |
| Fixnum |
Pixel representation of a color in Xlib |
| Object |
Copy color from a Color object |
win.background = "#000000" => "#000000"
VALUE
subextWindowBackgroundWriter(VALUE self,
VALUE value)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
w->bg = subextColorPixel(value, Qnil, Qnil, NULL);
XSetWindowBackground(display, w->win, w->bg);
}
return value;
}
Set the border color of this Window which can be of following types:
| String |
Any color representation of Xlib is allowed |
| Array |
Must be an array with values for red, green and blue |
| Hash |
Must be a hash with values for red, green and blue |
| Fixnum |
Pixel representation of a color in Xlib |
| Object |
Copy color from a Color object |
win.border_color = "#000000" => "#000000"
VALUE
subextWindowBorderColorWriter(VALUE self,
VALUE value)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
XSetWindowBorder(display, w->win,
subextColorPixel(value, Qnil, Qnil, NULL));
XFlush(display);
}
return Qnil;
}
Set border size of this Window.
win.border_size = 3 => 3
VALUE
subextWindowBorderSizeWriter(VALUE self,
VALUE value)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
int width = 3;
/* Check object type */
if(FIXNUM_P(value))
{
width = FIX2INT(value);
XSetWindowBorderWidth(display, w->win, width);
XFlush(display);
}
else rb_raise(rb_eArgError, "Unexpected value-type `%s'",
rb_obj_classname(value));
}
return value;
}
Clear this Window and remove all stored text.
win.clear => #<Subtlext::Window:xxx>
VALUE
subextWindowClear(int argc,
VALUE *argv,
VALUE self)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
VALUE x = Qnil, y = Qnil, width = Qnil, height = Qnil;
rb_scan_args(argc, argv, "04", &x, &y, &width, &height);
/* Either clear area or whole window */
if(FIXNUM_P(x) && FIXNUM_P(y) && FIXNUM_P(width) && FIXNUM_P(height))
{
XClearArea(display, w->win, FIX2INT(x), FIX2INT(y),
FIX2INT(width), FIX2INT(height), False);
}
else XClearWindow(display, w->win);
}
return self;
}
Draw a icon on the Window starting at x/y with given width, height and color without caching it.
win.draw_icon(10, 10, Subtlext::Icon.new("foo.xbm"))
=> #<Subtlext::Window:xxx>
VALUE
subextWindowDrawIcon(int argc,
VALUE *argv,
VALUE self)
{
SubtlextWindow *w = NULL;
VALUE x = Qnil, y = Qnil, icon = Qnil, fg = Qnil, bg = Qnil;
/* Check ruby object */
rb_check_frozen(self);
rb_scan_args(argc, argv, "32", &x, &y, &icon, &fg, &bg);
Data_Get_Struct(self, SubtlextWindow, w);
if(w && FIXNUM_P(x) && FIXNUM_P(y) &&
rb_obj_is_instance_of(icon, rb_const_get(mod, rb_intern("Icon"))))
{
int bitmap = False;
long lfg = w->fg, lbg = w->bg;
VALUE width = Qnil, height = Qnil, pixmap = Qnil;
/* Create on demand */
if(0 == w->gc)
w->gc = XCreateGC(display, w->win, 0, NULL);
/* Parse colors */
if(!NIL_P(fg)) lfg = subextColorPixel(fg, Qnil, Qnil, NULL);
if(!NIL_P(bg)) lbg = subextColorPixel(bg, Qnil, Qnil, NULL);
/* Fetch icon values */
width = rb_iv_get(icon, "@width");
height = rb_iv_get(icon, "@height");
pixmap = rb_iv_get(icon, "@pixmap");
bitmap = Qtrue == subextIconAskBitmap(icon) ? True : False;
subSharedDrawIcon(display, w->gc, w->win, FIX2INT(x),
FIX2INT(y), FIX2INT(width), FIX2INT(height), lfg, lbg,
NUM2LONG(pixmap), bitmap);
}
return self;
}
Draw a line on the window starting at x1/y1 to x2/y2 in given color.
win.draw_line(1, 1, 10, 1) => #<Subtlext::Window:xxx> win.draw_line(1, 1, 10, 1, "#ff0000", "#000000") => #<Subtlext::Window:xxx>
VALUE
subextWindowDrawLine(int argc,
VALUE *argv,
VALUE self)
{
VALUE x1 = Qnil, x2 = Qnil, y1 = Qnil, y2 = Qnil, color = Qnil;
rb_scan_args(argc, argv, "41", &x1, &y1, &x2, &y2, &color);
/* Check object types */
if(FIXNUM_P(x1) && FIXNUM_P(y1) &&
FIXNUM_P(x2) && FIXNUM_P(x2))
{
SubtlextWindow *w = NULL;
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
XGCValues gvals;
/* Create on demand */
if(0 == w->gc)
w->gc = XCreateGC(display, w->win, 0, NULL);
/* Update GC */
gvals.foreground = w->fg;
gvals.background = w->bg;
if(!NIL_P(color))
gvals.foreground = subextColorPixel(color, Qnil, Qnil, NULL);
XChangeGC(display, w->gc, GCForeground|GCBackground, &gvals);
XDrawLine(display, w->win, w->gc, FIX2INT(x1),
FIX2INT(y1), FIX2INT(x2), FIX2INT(y2));
XFlush(display);
}
}
else rb_raise(rb_eArgError, "Unexpected value-types");
return self;
}
Draw a pixel on the window at given coordinates in given color.
win.draw_point(1, 1) => #<Subtlext::Window:xxx> win.draw_point(1, 1, "#ff0000") => #<Subtlext::Window:xxx>
VALUE
subextWindowDrawPoint(int argc,
VALUE *argv,
VALUE self)
{
VALUE x = Qnil, y = Qnil, color = Qnil;
rb_scan_args(argc, argv, "21", &x, &y, &color);
/* Check object types */
if(FIXNUM_P(x) && FIXNUM_P(y))
{
SubtlextWindow *w = NULL;
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
XGCValues gvals;
/* Create on demand */
if(0 == w->gc)
w->gc = XCreateGC(display, w->win, 0, NULL);
/* Update GC */
gvals.foreground = w->fg;
gvals.background = w->bg;
if(!NIL_P(color))
gvals.foreground = subextColorPixel(color, Qnil, Qnil, NULL);
XChangeGC(display, w->gc, GCForeground|GCBackground, &gvals);
XDrawPoint(display, w->win, w->gc, FIX2INT(x), FIX2INT(y));
XFlush(display);
}
}
else rb_raise(rb_eArgError, "Unexpected value-types");
return self;
}
Draw a rect on the Window starting at x/y with given width, height and colors.
win.draw_rect(1, 1, 10, 10) => #<Subtlext::Window:xxx> win.draw_rect(1, 1, 10, 10, "#ff0000", true) => #<Subtlext::Window:xxx>
VALUE
subextWindowDrawRect(int argc,
VALUE *argv,
VALUE self)
{
VALUE x = Qnil, y = Qnil, width = Qnil, height = Qnil;
VALUE color = Qnil, fill = Qnil;
rb_scan_args(argc, argv, "42", &x, &y, &width, &height, &color, &fill);
/* Check object types */
if(FIXNUM_P(x) && FIXNUM_P(y) && FIXNUM_P(width) && FIXNUM_P(height))
{
SubtlextWindow *w = NULL;
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
XGCValues gvals;
/* Create on demand */
if(0 == w->gc)
w->gc = XCreateGC(display, w->win, 0, NULL);
/* Update GC */
gvals.foreground = w->fg;
gvals.background = w->bg;
if(!NIL_P(color))
gvals.foreground = subextColorPixel(color, Qnil, Qnil, NULL);
XChangeGC(display, w->gc, GCForeground|GCBackground, &gvals);
/* Draw rect */
if(Qtrue == fill)
{
XFillRectangle(display, w->win, w->gc, FIX2INT(x),
FIX2INT(y), FIX2INT(width), FIX2INT(height));
}
else XDrawRectangle(display, w->win, w->gc, FIX2INT(x),
FIX2INT(y), FIX2INT(width), FIX2INT(height));
XFlush(display);
}
}
else rb_raise(rb_eArgError, "Unexpected value-types");
return self;
}
Draw a text on the Window starting at x/y with given width, height and color without caching it.
win.draw_text(10, 10, "subtle") => #<Subtlext::Window:xxx>
VALUE
subextWindowDrawText(int argc,
VALUE *argv,
VALUE self)
{
SubtlextWindow *w = NULL;
VALUE x = Qnil, y = Qnil, text = Qnil, color = Qnil;
/* Check ruby object */
rb_check_frozen(self);
rb_scan_args(argc, argv, "31", &x, &y, &text, &color);
Data_Get_Struct(self, SubtlextWindow, w);
if(w && FIXNUM_P(x) && FIXNUM_P(y) && T_STRING == rb_type(text))
{
long lcolor = w->fg;
/* Create on demand */
if(0 == w->gc)
w->gc = XCreateGC(display, w->win, 0, NULL);
/* Parse colors */
if(!NIL_P(color)) lcolor = subextColorPixel(color, Qnil, Qnil, NULL);
subSharedDrawString(display, w->gc, w->font, w->win, FIX2INT(x),
FIX2INT(y), lcolor, w->bg, RSTRING_PTR(text), RSTRING_LEN(text));
}
return self;
}
Whether both objects have the same value and types (based on win)
object1.eql? object2 => true
static VALUE
SubtlextEqualTypedWindow(VALUE self,
VALUE other)
{
return SubtlextEqual(self, other, "@win", True);
}
Set focus to window
object.focus => nil
static VALUE
SubtlextFocus(VALUE self)
{
VALUE win = Qnil;
SubMessageData data = { { 0, 0, 0, 0, 0 } };
/* Check ruby object */
rb_check_frozen(self);
GET_ATTR(self, "@win", win);
/* Send message */
data.l[0] = NUM2LONG(win);
subSharedMessage(display, ROOT, "_NET_ACTIVE_WINDOW", data, 32, True);
return self;
}
Set the font that is used for text inside of a W.indow
win.font = "-*-*-*-*-*-*-10-*-*-*-*-*-*-*" => "-*-*-*-*-*-*-10-*-*-*-*-*-*-*"
VALUE
subextWindowFontWriter(VALUE self,
VALUE value)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
/* Check object type */
if(T_STRING == rb_type(value))
{
SubFont *f = NULL;
char *font = RSTRING_PTR(value);
/* Create window font */
if((f = subSharedFontNew(display, font)))
{
/* Replace font */
if(w->font) subSharedFontKill(display, w->font);
w->font = f;
}
else rb_raise(rb_eStandardError, "Invalid font `%s'", font);
}
else rb_raise(rb_eArgError, "Unexpected value-type `%s'",
rb_obj_classname(value));
}
return value;
}
Get the height of selected Window font.
win.font_height => 10
VALUE
subextWindowFontHeightReader(VALUE self)
{
VALUE ret = INT2FIX(0);
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w && w->font) ret = INT2FIX(w->font->height);
return ret;
}
Get width of string for selected Window font.
win.font_width("subtle")
=> 10
VALUE
subextWindowFontWidth(VALUE self,
VALUE string)
{
VALUE ret = INT2FIX(0);
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w && w->font && T_STRING == rb_type(string))
ret = INT2FIX(subSharedStringWidth(display, w->font,
RSTRING_PTR(string), RSTRING_LEN(string), NULL, NULL, False));
return ret;
}
Get y offset of the selected Window font.
win.font_y => 10
VALUE
subextWindowFontYReader(VALUE self)
{
VALUE ret = INT2FIX(0);
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w && w->font) ret = INT2FIX(w->font->y);
return ret;
}
Set the foreground color of this Window which can be of following types:
| String |
Any color representation of Xlib is allowed |
| Array |
Must be an array with values for red, green and blue |
| Hash |
Must be a hash with values for red, green and blue |
| Fixnum |
Pixel representation of a color in Xlib |
| Object |
Copy color from a Color object |
win.foreground = "#000000" => "#000000"
VALUE
subextWindowForegroundWriter(VALUE self,
VALUE value)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w) w->fg = subextColorPixel(value, Qnil, Qnil, NULL);
return value;
}
VALUE
subextWindowGeometryReader(VALUE self)
{
VALUE geom = Qnil;
/* Check ruby object */
rb_check_frozen(self);
GET_ATTR(self, "@geometry", geom);
return geom;
}
Set the geometry of this Window which can be of following types:
| Array |
Must be an array with values for x, y, width and height |
| Hash |
Must be a hash with values for x, y, width and height |
| Geometry |
Copy geometry from a Geometry object |
win.geometry = { :x => 0, :y => 0, :width => 50, :height => 50 }
=> { :x => 0, :y => 0, :width => 50, :height => 50 }
VALUE
subextWindowGeometryWriter(VALUE self,
VALUE value)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
XRectangle r = { 0 };
VALUE geom = Qnil;
/* Create geometry */
geom = subextGeometryInstantiate(0, 0, 1, 1);
geom = subextGeometryInit(1, &value, geom);
rb_iv_set(self, "@geometry", geom);
subextGeometryToRect(geom, &r);
XMoveResizeWindow(display, w->win, r.x, r.y, r.width, r.height);
}
return value;
}
Hide this Window from screen.
win.hide => #<Subtlext::Window:xxx>
VALUE
subextWindowHide(VALUE self)
{
VALUE win = Qnil;
/* Check ruby object */
rb_check_frozen(self);
GET_ATTR(self, "@win", win);
if(RTEST(win))
{
rb_iv_set(self, "@hidden", Qtrue);
XUnmapWindow(display, NUM2LONG(win));
XSync(display, False); ///< Sync with X
}
return self;
}
Destroy this Window and freeze this object.
win.kill => nil
VALUE
subextWindowKill(VALUE self)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
XUnmapWindow(display, w->win);
rb_obj_freeze(self); ///< Freeze object
}
return Qnil;
}
Lower this Window to the bottom of the window stack, when the window manager supports that. (subtle does)
win.lower => #<Subtlext::Window:xxx>
VALUE
subextWindowLower(VALUE self)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
XLowerWindow(display, w->win);
WindowExpose(w);
}
return self;
}
Set the WM_NAME of a Window-
win.name = "sublet" => "sublet"
VALUE
subextWindowNameWriter(VALUE self,
VALUE value)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
Window win = None;
XClassHint hint;
XTextProperty text;
char *name = NULL;
/* Check object type */
if(T_STRING == rb_type(value))
{
name = RSTRING_PTR(value);
win = NUM2LONG(rb_iv_get(self, "@win"));
/* Set Window informations */
hint.res_name = name;
hint.res_class = "Subtlext";
XSetClassHint(display, win, &hint);
XStringListToTextProperty(&name, 1, &text);
XSetWMName(display, win, &text);
free(text.value);
}
else rb_raise(rb_eArgError, "Unexpected value-type `%s'",
rb_obj_classname(value));
}
return value;
}
Grab pointer button press events and pass them to the block until the return value of the block isn't true or an error occured.
grab_mouse do |x, y, button|
p "x=#{x}, y=#{y}, button=#{button}"
end
=> #<Subtlext::Window:xxx>
VALUE
subextWindowOn(int argc,
VALUE *argv,
VALUE self)
{
VALUE event = Qnil, value = Qnil;
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
rb_scan_args(argc, argv, "11", &event, &value);
if(rb_block_given_p()) value = rb_block_proc(); ///< Get proc
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
/* Check value type */
if(CHAR2SYM("draw") == event || CHAR2SYM("redraw") == event
|| CHAR2SYM("expose") == event)
{
w->expose = value;
}
else if(CHAR2SYM("key_down") == event)
{
w->keyboard = value;
}
else if(CHAR2SYM("mouse_down") == event)
{
w->pointer = value;
}
else rb_raise(rb_eArgError, "Unexpected value type for on");
}
return self;
}
Raise this Window to the top of the window stack, when the window manager supports that. (subtle does)
win.raise => #<Subtlext::Window:xxx>
VALUE
subextWindowRaise(VALUE self)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
XRaiseWindow(display, w->win);
WindowExpose(w);
}
return self;
}
Redraw Window content.
win.redraw => #<Subtlext::Window:xxx>
VALUE
subextWindowRedraw(VALUE self)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w) WindowExpose(w);
return self;
}
Emulate a click on a window with optional button and x/y position
object.send_button => nil object.send_button(2) => Object
static VALUE
SubtlextSendButton(int argc,
VALUE *argv,
VALUE self)
{
Window subwin = None;
XEvent event = { 0 };
VALUE button = Qnil, x = Qnil, y = Qnil, win = Qnil;
/* Check ruby object */
rb_check_frozen(self);
GET_ATTR(self, "@win", win);
rb_scan_args(argc, argv, "03", &button, &x, &y);
/* Assemble button event */
event.type = EnterNotify;
event.xcrossing.window = NUM2LONG(win);
event.xcrossing.root = ROOT;
event.xcrossing.subwindow = NUM2LONG(win);
event.xcrossing.same_screen = True;
event.xcrossing.x = FIXNUM_P(x) ? FIX2INT(x) : 5;
event.xcrossing.y = FIXNUM_P(y) ? FIX2INT(y) : 5;
/* Translate window x/y to root x/y */
XTranslateCoordinates(display, event.xcrossing.window,
event.xcrossing.root, event.xcrossing.x, event.xcrossing.y,
&event.xcrossing.x_root, &event.xcrossing.y_root, &subwin);
//XSetInputFocus(display, event.xany.window, RevertToPointerRoot, CurrentTime);
XSendEvent(display, NUM2LONG(win), True, EnterWindowMask, &event);
/* Send button press event */
event.type = ButtonPress;
event.xbutton.button = FIXNUM_P(button) ? FIX2INT(button) : 1;
XSendEvent(display, NUM2LONG(win), True, ButtonPressMask, &event);
XFlush(display);
usleep(12000);
/* Send button release event */
event.type = ButtonRelease;
XSendEvent(display, NUM2LONG(win), True, ButtonReleaseMask, &event);
XFlush(display);
return self;
}
Emulate a keypress on a window
object.send_key("d")
=> Object
static VALUE
SubtlextSendKey(int argc,
VALUE *argv,
VALUE self)
{
VALUE keys = Qnil, x = Qnil, y = Qnil, win = Qnil;
/* Check ruby object */
rb_check_frozen(self);
GET_ATTR(self, "@win", win);
rb_scan_args(argc, argv, "12", &keys, &x, &y);
/* Check object type */
if(T_STRING == rb_type(keys))
{
int mouse = False;
unsigned int code = 0, state = 0;
char *tokens = NULL, *tok = NULL, *save = NULL;
Window subwin = None;
KeySym sym = None;
XEvent event = { 0 };
/* Assemble enter event */
event.type = EnterNotify;
event.xcrossing.window = NUM2LONG(win);
event.xcrossing.root = ROOT;
event.xcrossing.subwindow = NUM2LONG(win);
event.xcrossing.same_screen = True;
event.xcrossing.x = FIXNUM_P(x) ? FIX2INT(x) : 5;
event.xcrossing.y = FIXNUM_P(y) ? FIX2INT(y) : 5;
/* Translate window x/y to root x/y */
XTranslateCoordinates(display, event.xcrossing.window,
event.xcrossing.root, event.xcrossing.x, event.xcrossing.y,
&event.xcrossing.x_root, &event.xcrossing.y_root, &subwin);
XSendEvent(display, NUM2LONG(win), True, EnterWindowMask, &event);
/* Parse keys */
tokens = strdup(RSTRING_PTR(keys));
tok = strtok_r(tokens, " ", &save);
while(tok)
{
/* Parse key chain */
if(NoSymbol == (sym = subSharedParseKey(display,
tok, &code, &state, &mouse)))
{
rb_raise(rb_eStandardError, "Unknown key");
return Qnil;
}
/* Check mouse */
if(True == mouse)
{
rb_raise(rb_eNotImpError, "Use #send_button instead");
return Qnil;
}
#ifdef HAVE_X11_EXTENSIONS_XTEST_H
XTestGrabControl(display, True);
/* Send key press/release events */
SubtlextSendModifier(state, True);
XTestFakeKeyEvent(display, code, True, CurrentTime);
XTestFakeKeyEvent(display, code, False, CurrentTime);
SubtlextSendModifier(state, False);
XTestGrabControl(display, False);
#else /* HAVE_X11_EXTENSIONS_XTEST_H */
/* Send key press event */
event.type = KeyPress;
event.xkey.state = state;
event.xkey.keycode = code;
XSendEvent(display, NUM2LONG(win), True, KeyPressMask, &event);
XFlush(display);
usleep(12000);
/* Send key release event */
event.type = KeyRelease;
XSendEvent(display, NUM2LONG(win), True, KeyReleaseMask, &event);
#endif /* HAVE_X11_EXTENSIONS_XTEST_H */
tok = strtok_r(NULL, " ", &save);
}
XFlush(display);
free(tokens);
}
else rb_raise(rb_eArgError, "Unexpected value-type `%s'",
rb_obj_classname(keys));
return self;
}
Show this Window on screen.
win.show => #<Subtlext::Window:xxx>
VALUE
subextWindowShow(VALUE self)
{
SubtlextWindow *w = NULL;
/* Check ruby object */
rb_check_frozen(self);
Data_Get_Struct(self, SubtlextWindow, w);
if(w)
{
rb_iv_set(self, "@hidden", Qfalse);
if(RTEST(w->keyboard) || RTEST(w->pointer)) WindowGrab(w);
else
{
XMapRaised(display, w->win);
WindowExpose(w);
}
}
return self;
}
subextWindowSubwindow {{{
Create a subwindow of Window with given Geometry.
win.subwindow(:x => 5, :y => 5) do |w| s.background = "#ffffff" end
VALUE
subextWindowSubwindow(VALUE self,
VALUE geometry)
{
VALUE ret = Qnil;
SubtlextWindow *w1 = NULL;
Data_Get_Struct(self, SubtlextWindow, w1);
if(w1)
{
SubtlextWindow *w2 = NULL;
subextSubtlextConnect(NULL); ///< Implicit open connection
ret = subextWindowInstantiate(geometry);
Data_Get_Struct(ret, SubtlextWindow, w2);
if(w2)
{
/* Yield to block if given */
if(rb_block_given_p())
rb_yield_values(1, w2->instance);
XReparentWindow(display, w2->win, w1->win, 0, 0);
}
}
return ret;
}