 2012/05/17
|
Last update 1999/02/20
TPJ: Issue_05_X
- README
- Xproto2.perl
- clickwindow.pl
- xhello.pl
- extra-Xproto.h
- xatomhash.pl
- names
- parse-xheader.pl
- reqs
- wmm.pl
- xauth.pl
- xbase.pl
- xbeep.pl
- xdpyinfo.pl
- xerror.pl
- xint.perl
- xlsfont.pl
- xwdhead.pl
- xwininfo.c
- xwininfo.pl
- More Samples on X
Download README
|
Back in late 1991, I wrote an X library for perl. This wasn't a bindi\
|
|
ng
|
|
to the C Xlib; this was a raw implementation of the X protocol.
|
|
|
|
It got some small amount of use around MIT; I never got around to
|
|
posting it widely, but got feedback from a few people.
|
|
perl5 has some clever new features, which should make it easier to
|
|
provide a clean "interface" than the old code had, and easier to
|
|
set up good abstractions internally.
|
|
Now that I've had time to read through the Perl5 edition of the Camel
|
|
Book, it's time to begin... [eichin:19961101.0337EST]
|
|
|
|
discoveries:
|
|
* attempted to speed up the load of the converted Xproto.
|
|
perl *without* -w, user time:
|
|
.cooked file: 0.5s [original mechanism]
|
|
indiv. assign: 1.1s [first modification]
|
|
flattened assign: 0.52s, but more variance(?) [optimized a bit]
|
|
Note, however, that this *appears* to be *slower* than
|
|
parsing the proto file. Perhaps that shouldn't be a surprise...
|
|
So a win might be to store a binary format instead?
|
|
Problem is that these are all variable length strings; switching to a
|
|
split on ^@ gave about the same time range.
|
|
|
|
in perl5, we should be able to say:
|
|
my($output) = &xlibconvert("xConnSetupPrefix",$reply)
|
|
$success = $output->{"success"};
|
|
this would make $output blessed? or perhaps we say
|
|
my($output) = Xlib->new(type=>"xConnSetupPrefix",data=>$repl\
|
|
y);
|
|
all output needs to be, though, is a hash... ie. convert can
|
|
do the unpack *and* stuff the fields into the hash (and perl4 could
|
|
have probably handled this too, if &xlibconvert explicitly returned
|
|
a hash...) so xlibconvert just returns a hashref, which also happens
|
|
to contain the "packof" and "sizeof" fields. However, this only helps
|
|
with the few cases where we read now, though it would make it easier
|
|
to write more of them (as we'd need to for event handling.) We need a
|
|
better syntax for generating protocol messages, if we can...
|
|
|
|
x_beep just does:
|
|
print XFD pack($xpackof{"xBellReq"},$defines{"X_Bell"},$percentage,1\
|
|
);
|
|
we could put the $defines into a namespace directly; in fact, the X
|
|
defines are a useful set themselves, and could just become X::Bell and
|
|
the like. (maybe def:: for the others? or just make them raw values?)
|
|
so, step 1:
|
|
print XFD pack($xpackof{"xBellReq"},X::Bell,$percentage,1);
|
|
we can also, at least, define xpack as
|
|
sub xpack { my $typ=shift; pack($packof{$typ},@_); }
|
|
and then say
|
|
print XFD &xpack("xBellReq",X::Bell,$percentage,1);
|
|
which, with a name space and actual functions, could instead become
|
|
print XFD X::xBellReq(X::Bell,$percentage,1);
|
|
Then note that most of these include their *own* verb at the
|
|
beginning, there should be a clever way to instead say
|
|
print XFD X::xBellReq($percentage,1);
|
|
and now we're getting somewhere.
|
|
|
|
[eichin:19961105.0458EST]
|
|
[done] All uses of xsizeof/sizeof are in bytes -- so drop the *8 /8 al\
|
|
together.
|
|
Many use the $lll self-measuring trick, which could be generalized?
|
|
|
|
[eichin:19961106.1304EST]
|
|
[done] auth is way simple - perhaps we can just implement it next?
|
|
should fix "mismatch" code so it doesn't complain as much gratuitously
|
|
add more synonyms
|
|
[done] implement something like GetResReq/GetEmptyReq (for one arg/no \
|
|
args)
|
|
instead of forcing stuff into extra-Xproto.h?
|
|
[eichin:19961108.0113EST]
|
|
[done] finish off "xdpyinfo" features -- store xopendisplay output, an\
|
|
d then
|
|
parse it seperately...
|
|
perhaps a master data queue? or at least *some* way to handle events? \
|
|
[done]
|
|
(maybe just a hook that prints them at first...)
|
|
[eichin:19961109.1630EST]
|
|
milestones:
|
|
hello world (createwindow, gc, font) [done]
|
|
query-tree (start on wmm!) [done]
|
|
|
|
[eichin:19961117.1841EST]
|
|
request list: determine full protocol coverage based on request names
|
|
(up to 1/3 by morning...)
|
|
|
|
[eichin:19961118.1349EST]
|
|
idea from ken: calculate the length in Req subs directly? we *can*...[\
|
|
done]
|
|
[eichin:19961119.0351EST]
|
|
what about elisp, anyway? :-)
|
|
|
|
[eichin:19961120.0102EST]
|
|
how about a tie'd hash for atom name lookups? [done]
|
|
[eichin:19961120.1221EST]
|
|
now do the *reverse* as well -- what's a perl "isnumber"? that way we
|
|
can use the same data to go both ways... [done]
|
|
[eichin:19970227.0155EST]
|
|
Renamed .perl files to .pl since emacs handles that extension consiste\
|
|
ntly
|
|
now. Leave .perl for generated files for now. Add Makefile for relea\
|
|
se.
|
| Issue_05_X2. Xproto2.perl
|
Xproto2.perl
| Issue_05_X3. clickwindow.pl
|
Download clickwindow.pl
|
#!perl
|
|
#$xlib::debug = 1;
|
|
#$xlib::debugpkt = 1;
|
|
require "./xbase.pl";
|
|
# require "./xatomhash.pl";
|
|
$xopen = xlib::x_open_display($ENV{"DISPLAY"});
|
|
$fc = xlib::joincolor(65535,0,0);
|
|
$bc = xlib::joincolor(0,0,0);
|
|
$curs = xlib::x_createfontcursor($xopen, $XC::crosshair, $fc, $bc);
|
|
sub xx {
|
|
# $stat = xlib::xungrabpointer($xopen, 0); # time now
|
|
$stat = xlib::xgrabpointer($xopen,
|
|
0, # owner-events false
|
|
&xlib::defaultroot($xopen), # grabw
|
|
$X::defines{"ButtonPressMask"} |
|
|
$X::defines{"ButtonReleaseMask"},
|
|
$X::defines{"GrabModeSync"},
|
|
$X::defines{"GrabModeAsync"},
|
|
&xlib::defaultroot($xopen),
|
|
# conf window none (vs root?)
|
|
$curs, # cursor none
|
|
$X::defines{"CurrentTime"} # time now
|
|
);
|
|
# print "grabstat: $stat\n";
|
|
&xlib::xallowevents($xopen,
|
|
$X::defines{"SyncPointer"},
|
|
$X::defines{"CurrentTime"});
|
|
}
|
|
xx();
|
|
$SIG{"ALRM"} = $SIG{"INT"} = sub {
|
|
xlib::x_closedisplay($xopen);
|
|
exit;
|
|
};
|
|
alarm(30);
|
|
#print "waiting (30s)... $stat\n";
|
|
print "click on a window to toggle backing store...\n";
|
|
$xlib::handler{"ButtonRelease"} =
|
|
$xlib::handler{"ButtonPress"} = sub {
|
|
my $rep = xlib::xlibconvert("keyButtonPointer", $xopen->{"readq\
|
|
ueue"});
|
|
# xlib::debugxlib($rep);
|
|
# printf "child: 0x%x\n", $xchild = $rep->{"child"};
|
|
$xchild = $rep->{"child"};
|
|
};
|
|
$st = xlib::handle_event($xopen);
|
|
$ch1 = $xchild;
|
|
#print "event: $st, child $xchild\n";
|
|
xx();
|
|
$st = xlib::handle_event($xopen);
|
|
$ch2 = $xchild;
|
|
#print "event: $st, child $xchild\n";
|
|
# button press, button release, double check that they have the same c\
|
|
hild...
|
|
$stat = xlib::xungrabpointer($xopen, 0); # time now
|
|
if ($ch1 != $ch2) {
|
|
die "different windows, aborting on user request";
|
|
}
|
|
|
|
sub query_eval {
|
|
my ($d,$w,$sub)=@_;
|
|
&$sub($d,$w);
|
|
my @lf = &xlib::x_querytree($d, $w);
|
|
shift @lf; # lose the rep, we just want the\
|
|
kids
|
|
my $i;
|
|
for $i (@lf) {
|
|
query_eval($d,$i,$sub);
|
|
}
|
|
}
|
|
sub toggle_backingstore { # disp, win
|
|
my ($d,$w) = @_;
|
|
printf "toggling 0x%x (%d):", $w, $w;
|
|
my $attrs = xlib::x_get_window_attributes($d,$w);
|
|
if ($attrs->{"backingStore"} == $X::defines{"NotUseful"}) {
|
|
print "setting to Always\n";
|
|
$stat = xlib::x_change_window_attributes($d, $w,
|
|
$X::defines{"CWBackingSto\
|
|
re"},
|
|
$X::defines{"Always"});
|
|
} else {
|
|
print "setting to NotUseful\n";
|
|
$stat = xlib::x_change_window_attributes($d, $w,
|
|
$X::defines{"CWBackingSto\
|
|
re"},
|
|
$X::defines{"NotUseful"})\
|
|
;
|
|
}
|
|
}
|
|
query_eval($xopen,$ch1,\&toggle_backingstore);
|
Download xhello.pl
|
#!/usr/bin/perl
|
|
require "./xbase.pl";
|
|
$xopen = &xlib::x_open_display($ENV{"DISPLAY"});
|
|
die $xlib::status if not defined $xopen;
|
|
|
|
$fnt = xlib::x_openfont($xopen, "fixed");
|
|
$win = xlib::x_create_window($xopen, 8,
|
|
xlib::defaultroot($xopen),
|
|
100, 200, 300, 400, 5,
|
|
$X::defines{"InputOutput"},
|
|
$X::defines{"CopyFromParent"},
|
|
$X::defines{"CWBackPixel"}
|
|
| $X::defines{"CWEventMask"},
|
|
$xlib::root_white,
|
|
$X::defines{"ButtonPressMask"}
|
|
|$X::defines{"ButtonReleaseMask"}
|
|
|$X::defines{"ExposureMask"}
|
|
|$X::defines{"KeyPressMask"}
|
|
);
|
|
$gc = xlib::x_create_gc($xopen, $win,
|
|
$X::defines{"GCForeground"}
|
|
| $X::defines{"GCBackground"}
|
|
| $X::defines{"GCFont"},
|
|
$xlib::root_black, $xlib::root_white, $fnt);
|
|
#printf "fnt %x win %x gc %x\n", $fnt,$win,$gc;
|
|
#sleep 1;
|
|
$st = xlib::x_clear_area($xopen, $win, 0, 0,0,0,0);
|
|
$xlib::handler{"Expose"} = sub {
|
|
xlib::x_imagetext8($xopen, $win, $gc, 50, 75, "hello world");
|
|
};
|
|
$xlib::handler{"KeyPress"} = sub {
|
|
my $rep = xlib::xlibconvert("keyButtonPointer", $xopen->{"readq\
|
|
ueue"});
|
|
xlib::debugxlib($rep);
|
|
};
|
|
|
|
xlib::x_mapwindow($xopen, $win);
|
|
while(defined($st = xlib::handle_event($xopen))) { # assume error for \
|
|
now?
|
|
print "event: $st\n";
|
|
}
|
|
xlib::x_closedisplay($xopen);
|
| Issue_05_X5. extra-Xproto.h
|
extra-Xproto.h
| Issue_05_X6. xatomhash.pl
|
Download xatomhash.pl
|
#
|
|
# use getatomname or internatom depending on the value looked up, but
|
|
# cache both
|
|
package XATOM;
|
|
use Tie::Hash;
|
|
|
|
sub TIEHASH {
|
|
my ($name, $d) = @_;
|
|
my $self={}; bless $self;
|
|
$self->{"display"} = $d;
|
|
$self->{"cache"} = {};
|
|
return $self;
|
|
}
|
|
|
|
sub FETCH {
|
|
my $self = shift;
|
|
my $key = shift;
|
|
my $r = $self->{"cache"}->{$key};
|
|
if (! defined($r)) {
|
|
if ($key =~ /^\d*$/) {
|
|
$r = xlib::x_getatomname($self->{"display"},$key);
|
|
} else {
|
|
$r = xlib::x_internatom($self->{"display"},
|
|
$X::defines{"xTrue"},$key);
|
|
}
|
|
|
|
$self->{"cache"}->{$key} = $r;
|
|
$self->{"cache"}->{$r} = $key;
|
|
}
|
|
return $r;
|
|
}
|
|
sub EXISTS {
|
|
my $self = shift;
|
|
my $key = shift;
|
|
return exists $self->{"cache"}->{$key};
|
|
}
|
|
sub STORE {
|
|
my $self = shift;
|
|
my ($key, $value) = @_; # value irrelevant
|
|
my $a = xlib::x_internatom($self->{"display"},$X::defines{"xFal\
|
|
se"}, $key);
|
|
$self->{"cache"}->{$a} = $key;
|
|
return $self->{"cache"}->{$key} = $a;
|
|
}
|
|
sub DELETE {
|
|
my $self = shift;
|
|
my ($key, $value) = @_;
|
|
# delete $self->{"refs"}->{$key};
|
|
# can't actually delete something...
|
|
-1;
|
|
}
|
|
sub FIRSTKEY {
|
|
my $self = shift;
|
|
my $a = scalar keys %{$self->{"cache"}};
|
|
return each %{$self->{"cache"}};
|
|
}
|
|
sub NEXTKEY {
|
|
my $self = shift;
|
|
my $lastkey = shift;
|
|
return each %{$self->{"cache"}};
|
|
}
|
|
sub DESTROY {
|
|
my $self = shift;
|
|
}
|
|
1;
|
Download names
|
internal:
|
|
xlibconvert
|
|
debugxlib [ but exported anyway ]
|
|
xpack [ only used in x_open_display ]
|
|
split_display [ could export... ]
|
|
next_resource_id
|
|
extend_queue
|
|
skipevent
|
|
xqueueconvert
|
|
x_real_put_image
|
|
network:
|
|
mkport
|
|
mkport_unix
|
|
serverprint
|
|
other:
|
|
min
|
|
meta:
|
|
x_washwindow
|
|
x_get_one
|
|
x_reply
|
|
x_iter_raw
|
|
x_iter
|
|
genvec
|
|
genvec2
|
|
genvecstr
|
|
xpoly1
|
|
xpoly2
|
|
x_ungrab
|
|
exported:
|
|
handle_event
|
|
xdebugdisplay [but only for xdpyinfo?]
|
|
xlib::
|
|
default::
|
|
root defaultroot
|
|
rootdepth defaultrootdepth
|
|
window::
|
|
destroy x_destroywindow
|
|
destroysubs x_destroysubwindows
|
|
map x_mapwindow
|
|
mapsubs x_mapsubwindows
|
|
unmap x_unmapwindow
|
|
unmapsubs x_unmapsubwindows
|
|
configure x_configurewindow
|
|
getgeometry x_get_geometry
|
|
reparent x_reparentwindow
|
|
circulate x_circulatewindow
|
|
create x_create_window
|
|
list x_querytree
|
|
set_background_pixmap x_set_window_background_p\
|
|
ixmap
|
|
attributes::
|
|
get x_get_window_attributes
|
|
change x_change_window_attribut\
|
|
es
|
|
clear x_clear_area
|
|
saveset x_changesaveset
|
|
translate TranslateCoords [pending]
|
|
pixmap::
|
|
create x_create_pixmap
|
|
copyarea CopyArea [pending]
|
|
copyplane CopyPlane [pending]
|
|
image::
|
|
put x_put_image
|
|
get GetImage [pending]
|
|
free FreePixmap [pending]
|
|
poly::
|
|
arcs xpolyarcs
|
|
fillarcs xpolyfillarcs
|
|
rects xpolyrects
|
|
fillrects xpolyfillrects
|
|
segments xpolysegments
|
|
points xpolypoints
|
|
lines xpolylines
|
|
fill FillPoly [pending]
|
|
selection::
|
|
setowner xsetselectionowner
|
|
getowner xgetselectionowner
|
|
convert xconvertselection
|
|
property::
|
|
change x_changeproperty
|
|
delete x_deleteproperty
|
|
get x_getproperty
|
|
list x_listproperties
|
|
rotate RotateProperties [pending]
|
|
font::
|
|
getpath x_getfontpath
|
|
setpath SetFontPath [pending]
|
|
list x_listfonts
|
|
close CloseFont [pending]
|
|
query QueryFont [pending]
|
|
queryextents QueryTextExtents [pending]
|
|
open x_openfont
|
|
text::
|
|
poly8 PolyText8 [pending]
|
|
poly16 PolyText16 [pending]
|
|
image8 x_imagetext8
|
|
image16 ImageText16 [pending]
|
|
atom::
|
|
getname x_getatomname
|
|
intern x_internatom
|
|
pointer::
|
|
grab xgrabpointer
|
|
ungrab xungrabpointer
|
|
changegrab xchangeactivepointergrab
|
|
query xquerypointer
|
|
getmapping x_get_pointer_mapping
|
|
setmapping SetPointerMapping [pending]
|
|
warp WarpPointer [pending]
|
|
getcontrol GetPointerControl [pending]
|
|
changecontrol ChangePointerControl [pending]
|
|
GC::
|
|
free FreeGC [pending]
|
|
change ChangeGC [pending]
|
|
copy CopyGC [pending]
|
|
create x_create_gc
|
|
setdashes SetDashes [pending]
|
|
setcliprects SetClipRectangles [pending]
|
|
colormap::
|
|
create CreateColormap [pending]
|
|
free FreeColormap [pending]
|
|
copyandfree CopyColormapAndFree [pending]
|
|
install InstallColormap [pending]
|
|
uninstall UninstallColormap [pending]
|
|
listinstalled ListInstalledColormaps [pending]
|
|
color::
|
|
# may use a hash, or at least combine allocs
|
|
alloc AllocColor [pending]
|
|
allocnamed AllocNamedColor [pending]
|
|
alloccells AllocColorCells [pending]
|
|
allocplanes AllocColorPlanes [pending]
|
|
free FreeColors [pending]
|
|
store StoreColors [pending]
|
|
storenamed StoreNamedColor [pending]
|
|
query QueryColors [pending]
|
|
lookup LookupColor [pending]
|
|
cursor::
|
|
create CreateCursor [pending]
|
|
createglyph CreateGlyphCursor [pending]
|
|
free FreeCursor [pending]
|
|
recolor RecolorCursor [pending]
|
|
bestize QueryBestSize [pending]
|
|
access::
|
|
change ChangeHosts [pending]
|
|
list ListHosts [pending]
|
|
set SetAccessControl [pending]
|
|
screensaver::
|
|
set SetScreenSaver [pending]
|
|
get GetScreenSaver [pending]
|
|
force ForceScreenSaver [pending]
|
|
key::
|
|
grab xgrabkeyboard
|
|
grab xgrabkey
|
|
grab xgrabbutton
|
|
ungrab xungrabkeyboard
|
|
ungrab xungrabbutton
|
|
ungrab xungrabkey
|
|
getmapping x_get_keyboard_mapping
|
|
getmapping x_get_modifier_mapping
|
|
setmapping SetModifierMapping [pending]
|
|
getcontrol x_get_keyboard_control
|
|
getfocus x_get_input_focus
|
|
setfocus SetInputFocus [pending]
|
|
getmotion GetMotionEvents [pending]
|
|
changemapping ChangeKeyboardMapping [pending]
|
|
changecontrol ChangeKeyboardControl [pending]
|
|
query QueryKeymap [pending]
|
|
beep x_beep
|
|
connection::
|
|
setmode SetCloseDownMode [pending]
|
|
kill KillClient [pending]
|
|
open x_open_display
|
|
close x_closedisplay
|
|
grab xgrabserver
|
|
ungrab xungrabserver
|
|
extensions::
|
|
list x_listextensions
|
|
query QueryExtension [pending]
|
|
event::
|
|
xsendevent
|
|
xallowevents
|
| Issue_05_X8. parse-xheader.pl
|
Download parse-xheader.pl
|
#!perl
|
|
$xsizeof{"int"} = 4;
|
|
$xsizeof{"char"} = 1;
|
|
$xsizeof{"BYTE"} = 1;
|
|
$xsizeof{"BOOL"} = 1;
|
|
$xsizeof{"long"} = 4;
|
|
$xsizeof{"CARD8"} = 1;
|
|
$xsizeof{"CARD16"} = 2;
|
|
$xsizeof{"CARD32"} = 4;
|
|
$xsizeof{"INT8"} = 1;
|
|
$xsizeof{"INT16"} = 2;
|
|
$xsizeof{"INT32"} = 4;
|
|
# oops, X11R4 is missing one...
|
|
# X11R6 has it though.
|
|
# $xsizeof{"xGetModifierMappingReply"} = 256;
|
|
$xpackof{"int"} = "L";
|
|
$xpackof{"char"} = "C";
|
|
$xpackof{"BYTE"} = "C";
|
|
$xpackof{"BOOL"} = "C";
|
|
$xpackof{"long"} = "L";
|
|
$xpackof{"CARD8"} = "C";
|
|
$xpackof{"CARD16"} = "S";
|
|
$xpackof{"CARD32"} = "L";
|
|
$xpackof{"INT8"} = "C";
|
|
$xpackof{"INT16"} = "S";
|
|
$xpackof{"INT32"} = "L";
|
|
# these are stored in %xpad in case we decide we want to be general la\
|
|
ter on
|
|
# but for now we copy it all into %xpackof anyhow.
|
|
for $i ("", 1..3) {
|
|
$xpad{"BYTE pad$i"} = "x";
|
|
}
|
|
$xpad{"BYTE bpad"} = "x";
|
|
$xpad{"CARD8 pad"} = "x";
|
|
$xpad{"CARD8 pad1"} = "x";
|
|
$xpad{"CARD16 pad"} = "x2";
|
|
$xpad{"CARD16 pad1"} = "x2";
|
|
$xpad{"CARD16 pad2"} = "x2";
|
|
# these are mostly Xevent subfields...
|
|
for $i ("", "00", 1..7) {
|
|
$xpad{"CARD32 pad$i"} = "x4";
|
|
}
|
|
for $i (keys %xpad) { $xpackof{$i} = $xpad{$i}; }
|
|
$incomment = 0;
|
|
sub fropcomment { # $incomment
|
|
my($incomment) = @_;
|
|
s/\/\*.*\*\///g;
|
|
if(/\*\//) {
|
|
$incomment = 0;
|
|
s/^.*\*\///;
|
|
}
|
|
next if $incomment;
|
|
if(/\/\*/) {
|
|
$incomment = 1;
|
|
s/\/\*.*//;
|
|
}
|
|
}
|
|
|
|
# walk XPROTO file and fill in any defines, xsizeof, xtypeof, requests
|
|
# we come across, sometimes calling process_struct to help
|
|
sub munchproto {
|
|
while(<XPROTO>) {
|
|
$incomment = &fropcomment($incomment);
|
|
|
|
if(/\#if defined\(\_\_cplusplus\) \|\| defined\(c\_plusplus\)/\
|
|
) {
|
|
while(<XPROTO>) {
|
|
last if (/\#else/);
|
|
}
|
|
}
|
|
next if(/\#else/);
|
|
next if(/\#endif/);
|
|
next if(/\#undef/);
|
|
next if(/\#ifdef NEED_EVENTS/);
|
|
next if(/\#ifdef NEED_REPLIES/);
|
|
next if(/\#ifndef XPROTO_H/);
|
|
next if(/\#include/); # maybe do these some other time.
|
|
$eventing=1 if(/^\#define KeyPress/);
|
|
$eventing=0 if(/^\#define LASTEvent/);
|
|
|
|
if(/^\#define (\w+)$/) {
|
|
$defines{$1} = 1;
|
|
print "# defined flag $1\n";
|
|
next;
|
|
}
|
|
|
|
if(/^\#define sz_(\w+) (\d+)$/) {
|
|
$xsizeof{$1} = $2;
|
|
print "# processed size $1\n";
|
|
next;
|
|
}
|
|
|
|
if(/^\#define (\w+) CARD(\d+)$/) {
|
|
$xtypeof{$1} = "CARD".$2;
|
|
$xsizeof{$1} = $2/8;
|
|
print "# processed type $1\n";
|
|
next;
|
|
}
|
|
if(/^\#define (\w+)\s+(\d+)L?\s*$/) {
|
|
$defines{$1} = $2;
|
|
print "# defined flag $1 = $2\n";
|
|
my ($s,$t) = ($1,$2);
|
|
if(/^\#define X\_/) {
|
|
$requests[$t] = $s;
|
|
print "# request $t maps to $s\n";
|
|
}
|
|
if ($eventing) {
|
|
$events[$t] = $s;
|
|
print "# event code $t maps to $s\n";
|
|
}
|
|
$eventing=0 if(/^\#define LASTEvent/);
|
|
next;
|
|
}
|
|
if(/^\#define (\w+)\s+(0x[0-9a-fA-F]+)\s*$/) {
|
|
$defines{$1} = oct($2);
|
|
print "# defined flag $1 = $2\n";
|
|
next;
|
|
}
|
|
if(/^\#define (\w+)\s+\(1L?<<(\d+)\)\s*$/) {
|
|
$defines{$1} = 2**$2;
|
|
print "# defined flag $1 = $defines{$1} (2**$2)\n";
|
|
next;
|
|
}
|
|
if(/^typedef CARD(\d+) (\w+);/) {
|
|
$xtypeof{$2} = "CARD".$1;
|
|
$xsizeof{$2} = $1/8;
|
|
print "# processed type $2\n";
|
|
next;
|
|
}
|
|
|
|
if(/^typedef struct \{/) {
|
|
&process_struct();
|
|
next;
|
|
}
|
|
if(/^typedef struct _(\w+) \{/) {
|
|
&process_struct();
|
|
next;
|
|
}
|
|
|
|
if(/^typedef (\w+) (\w+);/) {
|
|
$xtypeof{$2} = $xtypeof{$1};
|
|
$xsizeof{$2} = $xsizeof{$1};
|
|
print "# processed type $2 (alias of $1)\n";
|
|
$xalias{$2} = $1;
|
|
next;
|
|
}
|
|
|
|
# print;
|
|
}
|
|
}
|
|
|
|
# process_struct: walk XPROTO when we've got a typedef struct to work \
|
|
on
|
|
# handle some unions, filling in xsizeof and xtypeof only. skip comme\
|
|
nts
|
|
# and WORD64 code.
|
|
sub process_struct {
|
|
my($typ,$siz) = ([],0);
|
|
while(<XPROTO>) {
|
|
$incomment = &fropcomment($incomment);
|
|
if(/\#if defined\(\_\_cplusplus\) \|\| defined\(c\_plusplus\)/\
|
|
) {
|
|
while(<XPROTO>) {
|
|
last if (/\#else/);
|
|
}
|
|
}
|
|
if(/\#ifdef WORD64/) {
|
|
while(<XPROTO>) {
|
|
last if (/\#else/);
|
|
}
|
|
}
|
|
next if(/\#else/);
|
|
next if(/\#endif/);
|
|
s/ +B16//g;
|
|
s/ B32//g;
|
|
last if(/\} (\w+)\;/);
|
|
if(/union \{/) {
|
|
my($utt);
|
|
print "# handling Union\n";
|
|
while(<XPROTO>) {
|
|
local($in_union) = !defined($xtypeof{"mappingNotify"})\
|
|
;
|
|
$utt = $_;
|
|
if(/struct \{/) {
|
|
&process_struct();
|
|
}
|
|
last if($utt =~ /\} u\;/);
|
|
}
|
|
}
|
|
|
|
while(/(\w+)\s+(\w*)\,/) {
|
|
while(/(\w+)\s+(\w+)\,/) {
|
|
push(@$typ,"$1 $2");
|
|
$siz += $xsizeof{$1};
|
|
s/$2\,//;
|
|
}
|
|
last if (/(\w+)\s+(\w+)\;/);
|
|
$_ .= <XPROTO>;
|
|
s/\/\*.*\*\///g;
|
|
s/ +B16//g;
|
|
s/ B32//g;
|
|
}
|
|
if(/(\w+)\s+(\w+)\[(\d+)\]\;/) {
|
|
push(@$typ,"$1 $2 $3");
|
|
$siz += $xsizeof{$1}*$3;
|
|
}
|
|
if(/(\w+)\s+(\w+)\;/) {
|
|
push(@$typ,"$1 $2");
|
|
$siz += $xsizeof{$1};
|
|
}
|
|
}
|
|
m/\} (\w+);/;
|
|
my $t = $1;
|
|
print "# processed type $t\n";
|
|
|
|
if($t eq "xEvent") {
|
|
# xEvent is a "special" case...
|
|
# xsizeof is already set...
|
|
# and we don't really need xtypeof...
|
|
$typ = ["BYTE raw_bits 32"];
|
|
$siz = 32;
|
|
}
|
|
if($siz != $xsizeof{$t}) {
|
|
print "### mismatch: @$typ, $siz, $t, $xsizeof{$t}\n";
|
|
}
|
|
if ($in_union == 1) {
|
|
if ($t eq "u") {
|
|
if (!defined($xtypeof{"mappingNotify"})) {
|
|
print "SETTING union_u to @$typ/$siz\n";
|
|
$union_u_typeof = $typ;
|
|
$union_u_sizeof = $siz;
|
|
} else {
|
|
$in_union = 0;
|
|
}
|
|
} else {
|
|
print "ADDING @$union_u_typeof to $t\n";
|
|
print "WAS @$typ...\n";
|
|
if ($$typ[0] eq "CARD32 pad00") {
|
|
splice(@$typ,0,1,@$union_u_typeof);
|
|
}
|
|
print "IS NOW @$typ...\n";
|
|
print "SIZ is $siz\n";
|
|
}
|
|
}
|
|
$xtypeof{$t} = join(":",@$typ);
|
|
$xsizeof{$t} = $siz;
|
|
}
|
|
# munchkeys: walk all xtypeof and generate xpackof
|
|
sub munchkeys {
|
|
for $typ (keys %xtypeof) {
|
|
print "Walking: $typ -- ";
|
|
&walk_type($typ);
|
|
$ss = length(pack($xpackof{$typ},0));
|
|
print "$xpackof{$typ}, $xsizeof{$typ} $ss\n";
|
|
if($ss != $xsizeof{$typ}) {
|
|
print "MISMATCH: $xtypeof{$typ}\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
# walk_type: given a type that's in xtypeof, generate xpackof
|
|
# *and* modify xtypeof by dropping pad fields
|
|
sub walk_type {
|
|
my($typ) = @_;
|
|
return if $xpackof{$typ} ne ""; # already done
|
|
return if !defined($xtypeof{$typ}); # not doable
|
|
my($xele,$save_1,$save_3);
|
|
my $xnew = [];
|
|
for $xele (split(/\:/,$xtypeof{$typ})) {
|
|
if($xele =~ /^(\w+) (\w+)$/) {
|
|
$save_1 = $1;
|
|
# allow preloads for "special" names like "BYTE pad"
|
|
if($xpackof{$xele} ne "") {
|
|
# assume a "whole line" subst means padding,
|
|
# and we drop the field. Might change this later.
|
|
$save_1 = $xele;
|
|
} else {
|
|
push(@$xnew,$xele);
|
|
}
|
|
if($xpackof{$save_1} eq "") {
|
|
&walk_type($save_1);
|
|
}
|
|
$xpackof{$typ} .= $xpackof{$save_1};
|
|
} elsif($xele =~ /^(\w+) (\w+) (\d+)$/) {
|
|
$save_1 = $1; $save_3 = $3;
|
|
# allow preloads for "special" names like "BYTE pad 3"
|
|
if($xpackof{"$1 $2"} ne "") {
|
|
# assume a "whole line" subst means padding,
|
|
# and we drop the field. Might change this later.
|
|
$save_1 = "$1 $2";
|
|
} else {
|
|
push(@$xnew,$xele);
|
|
}
|
|
if($xpackof{$save_1} eq "") {
|
|
&walk_type($save_1);
|
|
}
|
|
$xpackof{$typ} .= $xpackof{$save_1}.$save_3;
|
|
} elsif($xele =~ /^(\w+)$/) {
|
|
# it can't really recurse here, can it?
|
|
# maybe if something is typedef xCharInfo.
|
|
push(@$xnew,$xele);
|
|
$xpackof{$typ} .= $xpackof{$1};
|
|
} else {
|
|
die "bad element of $typ: $xele ($xtypeof{$typ})";
|
|
}
|
|
}
|
|
$xtypeof{$typ} = join(":",@$xnew);
|
|
}
|
|
for $fn ("/usr/include/X11/Xproto.h", "/usr/include/X11/Xprotostr.h",
|
|
"extra-Xproto.h", "/usr/include/X11/X.h",
|
|
"/usr/include/X11/cursorfont.h") {
|
|
open(XPROTO,"< $fn") || die "Couldn't open $fn: $@";
|
|
&munchproto;
|
|
close XPROTO;
|
|
}
|
|
# X.h to actually to pick up *Mask, GC* and the like...
|
|
|
|
&munchkeys;
|
|
|
|
open(PERLOUT,">Xproto2.perl") || die "couldn't open Xproto2.perl: $\
|
|
@";
|
|
open(LISPOUT,">Xproto2.el") || die "couldn't open Xproto2.el: $@";
|
|
print PERLOUT "package X;\n";
|
|
print PERLOUT "\%xpackof = (\n";
|
|
print LISPOUT "(setq xpackof '(\n";
|
|
for $xtype (sort keys %xpackof) {
|
|
print PERLOUT qq{"$xtype", "$xpackof{$xtype}",\n};
|
|
print LISPOUT qq{("$xtype" "$xpackof{$xtype}")\n};
|
|
}
|
|
print PERLOUT "); # xpackof\n";
|
|
print LISPOUT ")) ; xpackof\n";
|
|
print PERLOUT "\%xtypeof = (\n";
|
|
print LISPOUT "(setq xtypeof '(\n";
|
|
for $xtype (sort keys %xtypeof) {
|
|
print PERLOUT qq{"$xtype", "$xtypeof{$xtype}", \n};
|
|
print LISPOUT qq{("$xtype" (};
|
|
for (split(/\:/,$xtypeof{$xtype})) {
|
|
m/(\w+) ?(\w+)?/;
|
|
print LISPOUT qq{("$2" $1) };
|
|
$result{$2} = shift @fields;
|
|
}
|
|
print LISPOUT qq{))\n};
|
|
# print LISPOUT qq{("$xtype" "$xtypeof{$xtype}")\n};
|
|
}
|
|
print PERLOUT "); # xtypeof\n";
|
|
print LISPOUT ")) ; xtypeof\n";
|
|
print PERLOUT "\%xsizeof = (\n";
|
|
print LISPOUT "(setq xsizeof '(\n";
|
|
for $xtype (sort keys %xtypeof) {
|
|
print PERLOUT qq{"$xtype", $xsizeof{$xtype},\n};
|
|
print LISPOUT qq{("$xtype" $xsizeof{$xtype})\n};
|
|
}
|
|
print PERLOUT "); # xsizeof\n";
|
|
print LISPOUT ")) ; xsizeof\n";
|
|
print PERLOUT "\%defines = (\n";
|
|
print LISPOUT "(setq xdefines '(\n";
|
|
for $def (sort keys %defines) {
|
|
print PERLOUT qq{"$def", $defines{$def},\n};
|
|
print LISPOUT qq{("$def" $defines{$def})\n};
|
|
}
|
|
print PERLOUT "); # defines\n";
|
|
print LISPOUT ")) ; xdefines\n";
|
|
|
|
print PERLOUT "sub pad4 { ((\$_[0]+3)>>2)<<2; }\n";
|
|
print PERLOUT qq{sub xpad { my \$l=pad4(\$_[0])-\$_[0]; "\\0" x \$l; }\
|
|
\n};
|
|
%xsubs=();
|
|
for $def (sort keys %defines) {
|
|
next if $def !~ /^X_/;
|
|
($j = $def) =~ s/^X_//;
|
|
print PERLOUT qq{\$$j = $defines{$def};\n};
|
|
# don't need X:: scoping in these copies...
|
|
my $req = "x${j}Req";
|
|
if (defined $xpackof{$req}) {
|
|
if ($xalias{$req} eq "xResourceReq") {
|
|
print PERLOUT qq{sub $req { pack(\$xpackof{"$req"},\$$j,2,\
|
|
\@_);}\n};
|
|
$xsubs{$req} = $req;
|
|
print PERLOUT "sub new$req { $req(\@_); }\n";
|
|
$xsubs{"new$req"} = "new$req";
|
|
} elsif ($xalias{$req} eq "xReq") {
|
|
print "GOTONE: xReq $j/$req isn't fake\n";
|
|
print PERLOUT qq{sub $req { pack(\$xpackof{"$req"},\$$j,0,\
|
|
1);}\n};
|
|
} else {
|
|
my @fields = split(/\:/,$xtypeof{$req});
|
|
if ($fields[1] eq "CARD16 length") {
|
|
print PERLOUT
|
|
qq{sub $req { pack(\$xpackof{"$req"},\$$j,\@_);}\n\
|
|
};
|
|
} elsif ($fields[2] eq "CARD16 length") {
|
|
print PERLOUT
|
|
qq{sub $req { pack(\$xpackof{"$req"},\$$j,\$_[1],\\
|
|
$_[0],\@_[2..\$#_]);}\n};
|
|
} else {
|
|
print "$req failed: ".join(":",@fields)."\n";
|
|
die;
|
|
}
|
|
my $fl = scalar(@fields)-2; # -length, -reqType, so points to extra
|
|
print PERLOUT "sub new$req { my \$l=\$_[$fl]; my \$x=$req(0,\@_).\$l; \
|
|
$req(pad4(length(\$x))/4,\@_).\$l.xpad(length(\$x)); }\n";
|
|
$xsubs{$req} = $req;
|
|
$xsubs{"new$req"} = "new$req";
|
|
}
|
|
} elsif ($xalias{$j} eq "xReq") {
|
|
print PERLOUT qq{sub $req { pack(\$xpackof{"$j"},\$$j,0,1);}\n\
|
|
};
|
|
$xsubs{$req} = $req;
|
|
print PERLOUT "sub new$req { $req(\@_); }\n";
|
|
$xsubs{"new$req"} = "new$req";
|
|
}
|
|
}
|
|
print PERLOUT "\%xsubs = (\n";
|
|
for $subs (sort keys %xsubs) {
|
|
print PERLOUT qq{"$subs" => \\&$subs,\n};
|
|
}
|
|
print PERLOUT ");\n";
|
|
for $def (sort keys %defines) {
|
|
print PERLOUT qq{\$requests[$defines{$def}] = "$def";\n} if $def =\
|
|
~ /^X_/;
|
|
}
|
|
{
|
|
print PERLOUT "\@xevents = (\"";
|
|
print PERLOUT join(qq{\",\"}, @events);
|
|
print PERLOUT "\"); # xevents\n";
|
|
}
|
|
print PERLOUT "package XC;\n";
|
|
for $def (sort keys %defines) {
|
|
next if $def !~ /^XC_(.*)$/;
|
|
print PERLOUT "\$$1 = $defines{$def};\n";
|
|
}
|
|
print PERLOUT "1;\n";
|
|
close PERLOUT;
|
|
close LISPOUT;
|
Download reqs
|
$requests[1] = "X_CreateWindow"; [done]
|
|
$requests[2] = "X_ChangeWindowAttributes"; [done]
|
|
$requests[3] = "X_GetWindowAttributes"; [done]
|
|
$requests[4] = "X_DestroyWindow"; [done]
|
|
$requests[5] = "X_DestroySubwindows"; [done]
|
|
$requests[6] = "X_ChangeSaveSet"; [done]
|
|
$requests[7] = "X_ReparentWindow"; [done]
|
|
$requests[8] = "X_MapWindow"; [done]
|
|
$requests[9] = "X_MapSubwindows"; [done]
|
|
$requests[10] = "X_UnmapWindow"; [done]
|
|
$requests[11] = "X_UnmapSubwindows"; [done]
|
|
$requests[12] = "X_ConfigureWindow"; [done]
|
|
$requests[13] = "X_CirculateWindow"; [done]
|
|
$requests[14] = "X_GetGeometry"; [done]
|
|
$requests[15] = "X_QueryTree"; [done]
|
|
$requests[16] = "X_InternAtom"; [done]
|
|
$requests[17] = "X_GetAtomName"; [done]
|
|
$requests[18] = "X_ChangeProperty"; [done]
|
|
$requests[19] = "X_DeleteProperty"; [done]
|
|
$requests[20] = "X_GetProperty"; [done]
|
|
$requests[21] = "X_ListProperties"; [done]
|
|
$requests[22] = "X_SetSelectionOwner"; [done]
|
|
$requests[23] = "X_GetSelectionOwner"; [done]
|
|
$requests[24] = "X_ConvertSelection"; [done]
|
|
$requests[25] = "X_SendEvent"; [done]
|
|
$requests[26] = "X_GrabPointer"; [done]
|
|
$requests[27] = "X_UngrabPointer"; [done]
|
|
$requests[28] = "X_GrabButton"; [done]
|
|
$requests[29] = "X_UngrabButton"; [done]
|
|
$requests[30] = "X_ChangeActivePointerGrab"; [done]
|
|
$requests[31] = "X_GrabKeyboard"; [done]
|
|
$requests[32] = "X_UngrabKeyboard"; [done]
|
|
$requests[33] = "X_GrabKey"; [done]
|
|
$requests[34] = "X_UngrabKey"; [done]
|
|
$requests[35] = "X_AllowEvents"; [done]
|
|
$requests[36] = "X_GrabServer"; [done]
|
|
$requests[37] = "X_UngrabServer"; [done]
|
|
$requests[38] = "X_QueryPointer"; [done]
|
|
$requests[39] = "X_GetMotionEvents";
|
|
$requests[40] = "X_TranslateCoords";
|
|
$requests[41] = "X_WarpPointer";
|
|
$requests[42] = "X_SetInputFocus";
|
|
$requests[43] = "X_GetInputFocus"; [done]
|
|
$requests[44] = "X_QueryKeymap";
|
|
$requests[45] = "X_OpenFont"; [done]
|
|
$requests[46] = "X_CloseFont";
|
|
$requests[47] = "X_QueryFont";
|
|
$requests[48] = "X_QueryTextExtents";
|
|
$requests[49] = "X_ListFonts"; [done]
|
|
$requests[50] = "X_ListFontsWithInfo";
|
|
$requests[51] = "X_SetFontPath";
|
|
$requests[52] = "X_GetFontPath"; [done]
|
|
$requests[53] = "X_CreatePixmap"; [done]
|
|
$requests[54] = "X_FreePixmap";
|
|
$requests[55] = "X_CreateGC"; [done]
|
|
$requests[56] = "X_ChangeGC";
|
|
$requests[57] = "X_CopyGC";
|
|
$requests[58] = "X_SetDashes";
|
|
$requests[59] = "X_SetClipRectangles";
|
|
$requests[60] = "X_FreeGC";
|
|
$requests[61] = "X_ClearArea"; [done]
|
|
$requests[62] = "X_CopyArea";
|
|
$requests[63] = "X_CopyPlane";
|
|
$requests[64] = "X_PolyPoint"; [done]
|
|
$requests[65] = "X_PolyLine"; [done]
|
|
$requests[66] = "X_PolySegment"; [done]
|
|
$requests[67] = "X_PolyRectangle"; [done]
|
|
$requests[68] = "X_PolyArc"; [done]
|
|
$requests[69] = "X_FillPoly";
|
|
$requests[70] = "X_PolyFillRectangle"; [done]
|
|
$requests[71] = "X_PolyFillArc"; [done]
|
|
$requests[72] = "X_PutImage"; [done]
|
|
$requests[73] = "X_GetImage";
|
|
$requests[74] = "X_PolyText8";
|
|
$requests[75] = "X_PolyText16";
|
|
$requests[76] = "X_ImageText8"; [done]
|
|
$requests[77] = "X_ImageText16";
|
|
$requests[78] = "X_CreateColormap";
|
|
$requests[79] = "X_FreeColormap";
|
|
$requests[80] = "X_CopyColormapAndFree";
|
|
$requests[81] = "X_InstallColormap";
|
|
$requests[82] = "X_UninstallColormap";
|
|
$requests[83] = "X_ListInstalledColormaps";
|
|
$requests[84] = "X_AllocColor";
|
|
$requests[85] = "X_AllocNamedColor";
|
|
$requests[86] = "X_AllocColorCells";
|
|
$requests[87] = "X_AllocColorPlanes";
|
|
$requests[88] = "X_FreeColors";
|
|
$requests[89] = "X_StoreColors";
|
|
$requests[90] = "X_StoreNamedColor";
|
|
$requests[91] = "X_QueryColors";
|
|
$requests[92] = "X_LookupColor";
|
|
$requests[93] = "X_CreateCursor";
|
|
$requests[94] = "X_CreateGlyphCursor";
|
|
$requests[95] = "X_FreeCursor";
|
|
$requests[96] = "X_RecolorCursor";
|
|
$requests[97] = "X_QueryBestSize";
|
|
$requests[98] = "X_QueryExtension";
|
|
$requests[99] = "X_ListExtensions"; [done]
|
|
$requests[100] = "X_ChangeKeyboardMapping";
|
|
$requests[101] = "X_GetKeyboardMapping"; [done]
|
|
$requests[102] = "X_ChangeKeyboardControl";
|
|
$requests[103] = "X_GetKeyboardControl"; [done]
|
|
$requests[104] = "X_Bell"; [done]
|
|
$requests[105] = "X_ChangePointerControl";
|
|
$requests[106] = "X_GetPointerControl";
|
|
$requests[107] = "X_SetScreenSaver";
|
|
$requests[108] = "X_GetScreenSaver";
|
|
$requests[109] = "X_ChangeHosts";
|
|
$requests[110] = "X_ListHosts";
|
|
$requests[111] = "X_SetAccessControl";
|
|
$requests[112] = "X_SetCloseDownMode";
|
|
$requests[113] = "X_KillClient";
|
|
$requests[114] = "X_RotateProperties";
|
|
$requests[115] = "X_ForceScreenSaver";
|
|
$requests[116] = "X_SetPointerMapping";
|
|
$requests[117] = "X_GetPointerMapping"; [done]
|
|
$requests[118] = "X_SetModifierMapping";
|
|
$requests[119] = "X_GetModifierMapping"; [done]
|
|
$requests[127] = "X_NoOperation";
|
Download wmm.pl
|
#!perl
|
|
require "./xbase.pl";
|
|
require "./xatomhash.pl";
|
|
$xopen = &xlib::x_open_display($ENV{"DISPLAY"});
|
|
die $xlib::status if not defined $xopen;
|
|
tie %xatom, XATOM, $xopen;
|
|
# features:
|
|
# list all (id, name) [done]
|
|
# walk tree doing something
|
|
# move, resize, map/unmap (by id, by name?)
|
|
# select window with click
|
|
sub getwinname {
|
|
my ($d,$w) = @_;
|
|
# $atom_wm_name = xlib::x_internatom($d,$X::defines{"xTrue"},"WM_NA\
|
|
ME")
|
|
# if ! defined($atom_wm_name);
|
|
# die if $atom_wm_name == 0;
|
|
my @x = xlib::x_getproperty($d,$X::defines{"xFalse"}, $w,$xatom{"W\
|
|
M_NAME"},
|
|
$X::defines{"AnyPropertyType"}, 0,255)\
|
|
;
|
|
return $x[1];
|
|
}
|
|
|
|
sub list_all {
|
|
my $d = shift;
|
|
my $debug = shift;
|
|
list_level($d, $xlib::root_window, $debug);
|
|
}
|
|
|
|
sub list_level {
|
|
my $d = shift;
|
|
my $w = shift;
|
|
my $debug = shift;
|
|
my @ret;
|
|
my @lf = &xlib::x_querytree($d, $w, $xlib::root_window);
|
|
shift @lf; # lose the rep, we just want the\
|
|
kids
|
|
for $i (@lf) {
|
|
# need one level deeper...
|
|
my $wn = getwinname($d, $i);
|
|
if ($wn eq "") {
|
|
my @l2 = &xlib::x_querytree($d, $i);
|
|
shift @l2; # lose the rep, we just want the\
|
|
kids
|
|
for $j (@l2) {
|
|
my $wn = getwinname($d, $j);
|
|
if ($wn ne "") {
|
|
printf "%x(%x): %s\n", $i, $j, $wn if $debug;
|
|
push(@ret, $i, $wn);
|
|
last;
|
|
}
|
|
}
|
|
} else {
|
|
printf "%x: %s\n", $i, $wn if $debug;
|
|
push(@ret, $i, $wn);
|
|
}
|
|
}
|
|
for $i (@lf) {
|
|
push(@ret, list_level($d, $i, $debug));
|
|
}
|
|
@ret;
|
|
}
|
|
@list = list_all($xopen,1);
|
|
print join(":",@list),"\n";
|
|
|
|
while(1) {
|
|
my $wid = shift @list;
|
|
my $wn = shift @list;
|
|
|
|
if ($wn =~ /studentloan/) {
|
|
print "changing $wn\n";
|
|
xlib::x_changeproperty($xopen,$X::defines{"PropModeReplace"},$\
|
|
wid,
|
|
$xatom{"WM_NAME"},$xatom{"STRING"},8,"h\
|
|
ello");
|
|
xlib::x_changeproperty($xopen,$X::defines{"PropModeReplace"},$\
|
|
wid,
|
|
$xatom{"WM_ICON_NAME"},$xatom{"STRING"}\
|
|
,
|
|
8,"hello icon");
|
|
}
|
|
last if scalar(@list) == 0;
|
|
}
|
|
xlib::handle_event($xopen);
|
Download xauth.pl
|
|
|
# 2 bytes Family value (second byte is as in pro\
|
|
tocol HOST)
|
|
# 2 bytes address length (always MSB first)
|
|
# A bytes host address (as in protocol HOST)
|
|
# 2 bytes display "number" length (always MSB fi\
|
|
rst)
|
|
# S bytes display "number" string
|
|
# 2 bytes name length (always MSB first)
|
|
# N bytes authorization name string
|
|
# 2 bytes data length (always MSB first)
|
|
# D bytes authorization data string
|
|
# define FamilyLocal (256) /* not part of X standard (i.e. X.h)\
|
|
*/
|
|
# define FamilyWild (65535)
|
|
# define FamilyNetname (254) /* not part of X standard */
|
|
# define FamilyKrb5Principal (253) /* Kerberos 5 principal name */
|
|
# define FamilyLocalHost (252) /* for local non-net authenticat\
|
|
ion */
|
|
# from X.h,
|
|
# "FamilyChaos", 2,
|
|
# "FamilyDECnet", 1,
|
|
# "FamilyInternet", 0,
|
|
$X::defines{"FamilyLocal"} = 256;
|
|
sub unpack_xauth_record { # $data
|
|
my ($data) = @_;
|
|
my ($family, $len, $addr, $disp, $authname, $authdata);
|
|
($family, $len, $data) = unpack("nna*", $data);
|
|
($addr, $data) = unpack("a$len a*", $data);
|
|
($len, $data) = unpack("na*", $data);
|
|
($disp, $data) = unpack("a$len a*", $data);
|
|
($len, $data) = unpack("na*", $data);
|
|
($authname, $data) = unpack("a$len a*", $data);
|
|
($len, $data) = unpack("na*", $data);
|
|
($authdata, $data) = unpack("a$len a*", $data);
|
|
return { "family" => $family,
|
|
"addr" => $addr,
|
|
"disp" => $disp,
|
|
"authname" => $authname,
|
|
"authdata" => $authdata,
|
|
"remainder" => $data};
|
|
}
|
|
|
|
sub parse_xauth_file {
|
|
my $xadb = ();
|
|
my $data;
|
|
{
|
|
my $xafile = defined($ENV{"XAUTHORITY"})?
|
|
$ENV{"XAUTHORITY"}: ($ENV{"HOME"}."/.Xauthority");
|
|
local *XAUTH;
|
|
open(XAUTH, "<$xafile") || return $xadb;
|
|
local $/ = undef;
|
|
$data = <XAUTH>;
|
|
close XAUTH;
|
|
}
|
|
while(length($data)) {
|
|
my $res = unpack_xauth_record($data);
|
|
my $tmprec = {};
|
|
$data = $res->{"remainder"};
|
|
foreach (sort keys %$res) {
|
|
next if /^remainder$/;
|
|
$tmprec->{$_} = $res->{$_};
|
|
}
|
|
push(@$xadb, $tmprec);
|
|
}
|
|
return $xadb;
|
|
}
|
|
sub debug_xauth_file {
|
|
my $xdb = parse_xauth_file();
|
|
foreach (@$xdb) {
|
|
my $res = $_;
|
|
foreach (sort keys %$res) {
|
|
if (/^addr$/ && length($res->{$_}) == 4) { #
|
|
print "$_: ",join(".",unpack("C4",$res->{$_})),"\n"\
|
|
;
|
|
next;
|
|
}
|
|
print "$_: ",unpack("H*",$res->{$_}),"\n"
|
|
if /^authdata$/;
|
|
next if /^authdata$/;
|
|
|
|
print "$_: $res->{$_}\n";
|
|
}
|
|
}
|
|
}
|
|
sub search_xauth_file { # display
|
|
my($displayname) = @_;
|
|
my $xdb = parse_xauth_file();
|
|
my ($family, $addr, $res);
|
|
# display cases:
|
|
# :0.* -- unix, so family = FamilyLocal, addr=`hostname`
|
|
# host:0.* -- inet, so family = FamilyInternet, addr = 4byte ip ad\
|
|
dr
|
|
my($node, $off, $screen);
|
|
($node, $off, $screen) = split_display($displayname);
|
|
if ($node eq "") {
|
|
# unix domain socket case
|
|
$family = $X::defines{"FamilyLocal"};
|
|
$addr = `hostname`; chomp $addr;
|
|
} else {
|
|
# tcp case
|
|
$family = $X::defines{"FamilyInternet"};
|
|
my ($name, $aliases, $type, $len, $thisaddr) = gethostbyname($\
|
|
node);
|
|
$addr = $thisaddr;
|
|
}
|
|
foreach $res (@$xdb) {
|
|
if ($res->{"family"} eq $family
|
|
&& $res->{"addr"} eq $addr) {
|
|
return $res;
|
|
}
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
# debug_xauth_file();
|
|
1;
|
Download xbase.pl
|
#!perl
|
|
package xlib;
|
|
|
|
require "./Xproto2.perl";
|
|
|
|
sub xlibconvert { # type, data
|
|
my ($typ, $data) = @_;
|
|
my %result;
|
|
my (@fields) = unpack($X::xpackof{$typ},$data);
|
|
|
|
for (split(/\:/,$X::xtypeof{$typ})) {
|
|
m/(\w+) (\w+)/;
|
|
$result{$2} = shift @fields;
|
|
}
|
|
# nice trick: roll the sizeof in here too...
|
|
$result{"sizeof"} = $X::xsizeof{$typ};
|
|
$result{"packof"} = $X::xpackof{$typ};
|
|
$result{"typeof"} = $X::xtypeof{$typ};
|
|
$result{"typ"} = $typ;
|
|
return \%result;
|
|
}
|
|
|
|
sub debugxlib { # value
|
|
my ($val) = @_;
|
|
print "$val->{typ}:\n";
|
|
for (split(/:/,$val->{"typeof"})) {
|
|
m/(\w+) (\w+)/;
|
|
print "\t$2: $val->{$2}\n";
|
|
}
|
|
1;
|
|
}
|
|
|
|
sub xpack { my $typ=shift; pack($X::xpackof{$typ},@_); }
|
|
|
|
use Socket qw(AF_INET PF_INET SOCK_STREAM INADDR_ANY AF_UNIX PF_UNIX);
|
|
sub mkport {
|
|
my($saddr,$port,$FD) = @_;
|
|
my $proto = (getprotobyname("tcp"))[2];
|
|
my $sin = Socket::sockaddr_in($port, $saddr);
|
|
socket($FD, PF_INET, SOCK_STREAM, $proto) || return "socket:$!";
|
|
connect($FD, $sin) || return "connect:$!";
|
|
select($FD); $| = 1; select(STDOUT); $| = 1;
|
|
return "OK";
|
|
}
|
|
sub mkport_unix {
|
|
my($path,$FD) = @_;
|
|
my $proto = 0; # *not* tcp...
|
|
my $sun = Socket::sockaddr_un($path);
|
|
socket($FD, PF_UNIX, SOCK_STREAM, $proto) || return "socket:$!";
|
|
connect($FD, $sun) || return "connect:$!";
|
|
select($FD); $| = 1; select(STDOUT); $| = 1;
|
|
return "OK";
|
|
}
|
|
sub split_display { # $disp var
|
|
my ($node, $dispnum, $off, $screen);
|
|
my ($displayname) = @_;
|
|
($node,$dispnum)=split(':',$displayname);
|
|
($off,$screen) = split('\.',$dispnum);
|
|
$screen = 0 if !defined($screen);
|
|
return ($node, $off, $screen);
|
|
}
|
|
|
|
require "./xauth.pl";
|
|
|
|
sub min { my($a,$b)=@_; ($a<$b) ? $a : $b; }
|
|
sub serverprint { # $d
|
|
my $d = shift;
|
|
print {$d->{"XFD"}} @_;
|
|
if ($debug || $debugpkt) {
|
|
print "seq: $xseqnum\n"; $xseqnum++;
|
|
printf("x request: ".("%02x " x min(128,length($_[0])))."\n",
|
|
unpack("C*",$_[0]));
|
|
print "x request length = ",length($_[0]),"\n";
|
|
}
|
|
}
|
|
|
|
sub x_open_display {
|
|
my($displayname) = @_;
|
|
my($node, $off, $screen, $base);
|
|
# local(XFD);
|
|
my($reply)="";
|
|
my $result = {};
|
|
my (@root, @pixmap_format);
|
|
|
|
($node, $off, $screen) = split_display($displayname);
|
|
$result->{"Screen"} = $screen;
|
|
print "x_open_display: n=$node, o=$off, s=$screen\n" if $debug;
|
|
if ($node eq "") {
|
|
# get a socket... /tmp/.X11-unix/X\d are unix domain sockets
|
|
my $path = "/tmp/.X11-unix/X$off";
|
|
$status = &mkport_unix($path,\*XFD);
|
|
} else {
|
|
($name, $aliases, $type, $len, $thisaddr) = gethostbyname($nod\
|
|
e);
|
|
$status = &mkport($thisaddr,$X::TCP_PORT+$off,\*XFD);
|
|
if($status ne "OK") { return undef; }
|
|
}
|
|
$result->{"XFD"} = \*XFD;
|
|
|
|
my $xauth = search_xauth_file($displayname);
|
|
# network byte order is MSB first
|
|
# byte "B" for MSB first, then CARD16 major, CARD16 minor,
|
|
# STRING8 auth prot name, STRING8 auth prot data
|
|
my $xauthname = defined($xauth)?$xauth->{"authname"}:"";
|
|
my $xauthdata = defined($xauth)?$xauth->{"authdata"}:"";
|
|
my $x= xpack("xConnClientPrefix",
|
|
unpack("S","lB")&255,
|
|
$X::PROTOCOL, $X::PROTOCOL_REVISION,
|
|
length($xauthname),
|
|
length($xauthdata),
|
|
0);
|
|
$x.= $xauthname;
|
|
$x .= "\0" x (&pad4(length($x))-length($x));
|
|
$x.= $xauthdata;
|
|
$x .= "\0" x (&pad4(length($x))-length($x));
|
|
|
|
$xseqnum = 0;
|
|
serverprint($result, $x);
|
|
print STDOUT "reading...\n" if $debug;
|
|
# "read" doesn't work anymore with 1024, though shorter vals are o\
|
|
k
|
|
# perhaps we should just read sizeof(xConnSetupPrefix)?
|
|
sysread(XFD,$reply,1024) || ($status = "read:$!" && return undef);
|
|
print STDOUT "done reading...\n" if $debug;
|
|
|
|
my($output) = &xlibconvert("xConnSetupPrefix",$reply);
|
|
$success = $output->{"success"};
|
|
if($success == 0) {
|
|
print "Proto Major: ", $output->{"majorVersion"},
|
|
" Proto Minor: ", $output->{"minorVersion"}, "\n";
|
|
$rlen = $output->{"lengthReason"};
|
|
$xlen = $output->{"sizeof"};
|
|
print "reason len: $rlen\n";
|
|
$reason = substr($reply,$xlen,$rlen);
|
|
$status = "open failed: $reason";
|
|
return undef;
|
|
} else {
|
|
$xlen = $output->{"sizeof"};
|
|
$output = &xlibconvert("xConnSetup", substr($reply, $xlen));
|
|
debugxlib($output) if $debug;
|
|
$result->{"setup"} = $output;
|
|
$xlen += $output->{"sizeof"};
|
|
$vlen = $output->{"nbytesVendor"};
|
|
$vendor = substr($reply, $xlen, $vlen);
|
|
print "Vendor: $vendor\n" if $debug;
|
|
$result->{"vendor"} = $vendor;
|
|
# ignore the rest for now...
|
|
# @output contains most of the fields...
|
|
$resource_id_base = $output->{"ridBase"};
|
|
$resource_id_mask = $output->{"ridMask"};
|
|
$resource_id_ctr = 1; # store this in $result too?
|
|
|
|
$max_request_size = $output->{"maxRequestSize"};
|
|
|
|
$nroots = $output->{"numRoots"};
|
|
$nformats = $output->{"numFormats"};
|
|
$base = &pad4($xlen+$vlen);
|
|
for $i (0..$nformats-1) {
|
|
$pixmap_format[$i] =
|
|
&xlibconvert("xPixmapFormat", substr($reply, $base));
|
|
debugxlib($pixmap_format[$i]) if $debug;
|
|
$base += $pixmap_format[$i]->{"sizeof"};
|
|
}
|
|
$result->{"Formats"} = \@pixmap_format;
|
|
# $rootbase = &pad4($xlen+$vlen)+$X::xsizeof{"xPixmapFormat"}*$n\
|
|
formats;
|
|
# just use the first root for now...
|
|
for $i (0..$nroots-1) {
|
|
$root[$i] = &xlibconvert("xWindowRoot", substr($reply,$base)\
|
|
);
|
|
$base += $root[$i]->{"sizeof"};
|
|
debugxlib($root[$i]) if $debug;
|
|
for $j (0..$root[$i]->{"nDepths"}-1) {
|
|
my $d = &xlibconvert("xDepth", substr($reply,$base));
|
|
debugxlib($d) if $debug;
|
|
$root[$i]->{"depth"}[$j] = $d;
|
|
$base += $d->{"sizeof"};
|
|
for $k (0..$d->{"nVisuals"}-1) {
|
|
my $v = &xlibconvert("xVisualType",substr($reply,$ba\
|
|
se));
|
|
debugxlib($v) if $debug;
|
|
$d->{"visual"}[$k] = $v;
|
|
$base += $v->{"sizeof"};
|
|
}
|
|
}
|
|
}
|
|
$result->{"readqueue"} = substr($reply,$base);
|
|
$result->{"Roots"} = \@root;
|
|
|
|
$root_window = $root[$screen]->{"windowId"};
|
|
$root_white = $root[$screen]->{"whitePixel"};
|
|
$root_black = $root[$screen]->{"blackPixel"};
|
|
|
|
print "Root Window: $root_window\n" if $debug;
|
|
return $result;
|
|
}
|
|
}
|
|
sub xdebugdisplay { # xopendisplay result
|
|
my $disp = shift;
|
|
my ($i, $j, $k);
|
|
my ($format, $root, $depth, $visual);
|
|
debugxlib($disp->{"setup"});
|
|
for $i (0..$disp->{"setup"}->{"numFormats"}-1) {
|
|
my $format = $disp->{"Formats"}[$i];
|
|
debugxlib($format);
|
|
}
|
|
for $i (0..$disp->{"setup"}->{"numRoots"}-1) {
|
|
my $root = $disp->{"Roots"}[$i];
|
|
print "Root $i\n";
|
|
debugxlib($root);
|
|
for $j (0..$root->{"nDepths"}-1) {
|
|
my $depth = $root->{"depth"}[$j];
|
|
print "Root $i Depth $j\n";
|
|
debugxlib($depth);
|
|
for $k (0..$depth->{"nVisuals"}-1) {
|
|
my $visual = $depth->{"visual"}[$k];
|
|
print "Root $i Depth $j Visual $k\n";
|
|
debugxlib($visual);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sub next_resource_id {
|
|
$resource_id_base | ($resource_id_mask & $resource_id_ctr++);
|
|
}
|
|
sub pad4 { (($_[0]+3)>>2)<<2; }
|
|
sub x_beep {
|
|
my ($d,$percentage) = @_;
|
|
serverprint($d,X::newxBellReq($percentage));
|
|
"OK";
|
|
}
|
|
sub x_washwindow {
|
|
my ($func, $d, $w) = @_;
|
|
serverprint($d, &{$X::xsubs{"x${func}Req"}}($w));
|
|
"OK"
|
|
}
|
|
sub x_destroywindow { x_washwindow("DestroyWindow", @_); }
|
|
sub x_destroysubwindows { x_washwindow("DestroySubwindows", @_); }
|
|
sub x_mapwindow { x_washwindow("MapWindow", @_); }
|
|
sub x_mapsubwindows { x_washwindow("MapSubwindows", @_); }
|
|
sub x_unmapwindow { x_washwindow("UnmapWindow", @_); }
|
|
sub x_unmapsubwindows { x_washwindow("UnmapSubwindows", @_); }
|
|
sub x_configurewindow {
|
|
my($d,$wind,$mask,@vals)=@_;
|
|
genvec2($d, "xConfigureWindowReq", "XID", [$wind,$mask], \@vals);
|
|
}
|
|
|
|
sub x_reparentwindow {
|
|
my ($d, $w, $p, $x, $y) = @_;
|
|
serverprint($d, X::newxReparentWindowReq($w,$p,$x,$y));
|
|
"OK"
|
|
}
|
|
|
|
sub x_circulatewindow {
|
|
my ($d, $dir, $w) = @_;
|
|
serverprint($d, X::newxCirculateWindowReq($dir,$w));
|
|
"OK"
|
|
}
|
|
|
|
sub x_changesaveset {
|
|
my ($d, $mode, $win) = @_;
|
|
serverprint($d, X::newxChangeSaveSetReq($mode,$win));
|
|
"OK";
|
|
}
|
|
|
|
sub x_clear_area {
|
|
my($d, $wind, $expose, $x,$y,$width,$height)=@_;
|
|
serverprint($d, X::newxClearAreaReq($expose,$wind, $x,$y,$width,$h\
|
|
eight));
|
|
"OK";
|
|
}
|
|
|
|
sub x_create_pixmap {
|
|
my($d,$draw, $depth, $width, $height)=@_;
|
|
my($ret);
|
|
# 4 is length -- fix it?
|
|
serverprint($d,X::newxCreatePixmapReq($depth, $ret = &next_resourc\
|
|
e_id,
|
|
$draw, $width, $height));
|
|
$ret;
|
|
}
|
|
sub x_create_gc {
|
|
my($d,$draw, $mask, @vals)=@_;
|
|
my($ret);
|
|
genvec2($d,"xCreateGCReq","XID", [$ret = &next_resource_id, $draw,\
|
|
$mask],
|
|
\@vals);
|
|
$ret;
|
|
}
|
|
sub x_put_image {
|
|
my($d,$draw,$gc,$format,$image,$destx,$desty,$width,$height,$lpad,\
|
|
$depth,$bpl)
|
|
= @_;
|
|
my($imm,$lns,$off_l,$off);
|
|
my($chunk_lines,$chunk_bytes);
|
|
my $overhead = $X::xsizeof{"xPutImageReq"};
|
|
my $maxreq = (4*$max_request_size)-$overhead;
|
|
$lns = $xh;
|
|
$off_l = 0;
|
|
$off = 0;
|
|
$chunk_lines = int($maxreq/$bpl);
|
|
$chunk_bytes = $bpl * $chunk_lines;
|
|
while(length($image)-$off > $maxreq) {
|
|
$imm = substr($image, $off, $chunk_bytes);
|
|
# print "imm: ",length($imm),"\n";
|
|
&xlib::x_real_put_image($d,$draw,$gc,$format,
|
|
$imm,$destx,$desty+$off_l,
|
|
$width,$chunk_lines,$lpad,$depth);
|
|
$off_l += $chunk_lines;
|
|
$off = $bpl * $off_l;
|
|
}
|
|
$off = $bpl * $off_l;
|
|
if (length($image)-$off > 0) {
|
|
$imm = substr($image, $off);
|
|
# print "imm trail: ",length($imm),"\n";
|
|
&xlib::x_real_put_image($d,$draw,$gc,$format,
|
|
$imm,$destx,$desty+$off_l,
|
|
$width,$height-$off_l,$lpad,$depth);
|
|
}
|
|
}
|
|
|
|
sub x_real_put_image {
|
|
my($d,$draw,$gc,$format,$image,$destx,$desty,$width,$height,$lpad,\
|
|
$depth)
|
|
= @_;
|
|
|
|
genvecstr($d, "xPutImageReq", [$format, $draw, $gc, $width, $heigh\
|
|
t,
|
|
$destx, $desty, $lpad, $depth], $im\
|
|
age);
|
|
"OK";
|
|
}
|
|
sub x_get_window_attributes {
|
|
my ($d,$w) = @_;
|
|
my ($rep,$q) = x_reply($d, "GetWindowAttributes", [$w]);
|
|
$rep;
|
|
}
|
|
sub x_change_window_attributes {
|
|
my $d = shift;
|
|
my ($win, $mask, @vals) = @_;
|
|
genvec2($d, "xChangeWindowAttributesReq", "XID", [$win,$mask], \@v\
|
|
als);
|
|
}
|
|
sub x_set_window_background_pixmap {
|
|
my($d,$wind,$pixmap)=@_;
|
|
x_change_window_attributes($d,$wind,$X::defines{"CWBackPixmap"},$p\
|
|
ixmap);
|
|
}
|
|
|
|
sub extend_queue {
|
|
my $d = shift;
|
|
my $l = shift;
|
|
while (length ($d->{"readqueue"}) < $l) {
|
|
my $data = "";
|
|
sysread($d->{"XFD"},$data,1024) || die "$! in extend_queue"\
|
|
;
|
|
$d->{"readqueue"} .= $data;
|
|
}
|
|
}
|
|
|
|
sub x_getatomname {
|
|
my ($d,$atom) = @_;
|
|
my ($rep,$q) = x_reply($d,"GetAtomName", [$atom]);
|
|
my $sl = $rep->{"nameLength"};
|
|
my $name; my $pl = pad4($sl)-$sl;
|
|
($name,$$q) = unpack("a$sl x$pl a*", $$q);
|
|
print "atom name: $name\n" if $debug;
|
|
$name;
|
|
}
|
|
|
|
sub x_internatom {
|
|
my ($d,$exists,$name) = @_;
|
|
genvecstr($d, "xInternAtomReq", [$exists,length($name)], $name);
|
|
handle_event($d);
|
|
my ($rep,$q) = xqueueconvert($d,"xInternAtomReply");
|
|
$rep->{"atom"};
|
|
}
|
|
|
|
sub x_getproperty {
|
|
my ($d,$flag,$win,$prop,$type,$loff,$llen) = @_;
|
|
my ($rep,$q) =
|
|
x_reply($d,"GetProperty", [$flag,$win,$prop,$type,$loff,$llen]\
|
|
);
|
|
my $f = $rep->{"format"}; # 0 8 16 32
|
|
my $sl = $rep->{"nItems"}*$f/8;
|
|
my $val; my $pl = pad4($sl)-$sl;
|
|
($val,$$q) = unpack("a$sl x$pl a*", $$q);
|
|
print "atom value: $val\n" if $debug && ($f eq 8);
|
|
return ($f, $val, $rep->{"propertyType"});
|
|
}
|
|
|
|
sub x_changeproperty {
|
|
my ($d,$mode,$win,$prop,$type,$form,@vals) = @_;
|
|
# for format=8, use a string, else a list
|
|
my $p = "CARD$form";
|
|
if ($form == 8) {
|
|
@vals = unpack("C*",$vals[0]);
|
|
}
|
|
genvec2($d,"xChangePropertyReq",$p,
|
|
[$mode,$win,$prop,$type,$form,scalar(@vals)], \@vals);
|
|
"OK";
|
|
}
|
|
|
|
sub x_deleteproperty {
|
|
my ($d, $w, $a) = @_;
|
|
serverprint($d, X::newxDeletePropertyReq($w,$a));
|
|
"OK";
|
|
}
|
|
|
|
sub x_getfontpath {
|
|
my ($d) = @_;
|
|
x_iter($d, "GetFontPath", "nPaths", "STRING8");
|
|
}
|
|
sub x_listfonts {
|
|
my ($d, $f) = @_;
|
|
x_iter($d,"ListFonts","nFonts","STRING8", [-1,length($f),$f]);
|
|
}
|
|
|
|
sub x_listextensions {
|
|
my ($d) = @_;
|
|
x_iter($d,"ListExtensions","nExtensions","STRING8");
|
|
}
|
|
sub x_get_geometry { # very much like GetWindowAttribut\
|
|
es...
|
|
my ($d,$w) = @_;
|
|
my ($rep,$q) = x_reply($d, "GetGeometry", [$w]);
|
|
$rep;
|
|
}
|
|
sub x_get_one {
|
|
my ($type, $d) = @_;
|
|
my ($rep,$q) = x_reply($d, $type);
|
|
$rep;
|
|
}
|
|
sub x_get_input_focus { x_get_one("GetInputFocus",@_); }
|
|
sub x_get_keyboard_control { x_get_one("GetKeyboardControl",@_); }
|
|
require "./xerror.pl";
|
|
sub handle_event {
|
|
my $d = shift;
|
|
my $rep;
|
|
my $q = \$d->{"readqueue"};
|
|
extend_queue($d, $X::xsizeof{"xEvent"});
|
|
$rep = xlibconvert("xGenericReply",$$q);
|
|
if ($rep->{"type"} == $X::Reply) {
|
|
print "reply: \n" if $debug;
|
|
debugxlib($rep) if $debug;
|
|
extend_queue($d, $X::xsizeof{"xEvent"}+4*$rep->{"length"});
|
|
# handle reply
|
|
return $rep->{"length"};
|
|
} elsif ($rep->{"type"} == $X::Error) {
|
|
# handle error
|
|
$rep = &xlibconvert("xError",$$q);
|
|
print "xerror: $X::ErrorList[$rep->{errorCode}]\n";
|
|
printf "xerror: resid %x\n", $rep->{"resourceID"};
|
|
print "major: $X::requests[$rep->{majorCode}]\n";
|
|
debugxlib($rep);
|
|
$$q = substr($$q,$rep->{"sizeof"});
|
|
return undef;
|
|
} else {
|
|
# process the event off the input queue and on to the event qu\
|
|
eue...
|
|
$rep = xlibconvert("u",$$q);
|
|
print "xevent: $X::xevents[$rep->{type}]\n" if $debug;
|
|
my $h = $handler{$X::xevents[$rep->{"type"}]};
|
|
&$h if (defined $h);
|
|
debugxlib($rep) if $debug || !defined($h);
|
|
skipevent($d, "xEvent");
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
sub skipevent { # tag
|
|
my ($d,$tag) = @_;
|
|
my $q = \$d->{"readqueue"};
|
|
$$q = substr($$q, $X::xsizeof{$tag});
|
|
print "event queue length: ",length($$q),"\n" if $debug;
|
|
}
|
|
|
|
sub xqueueconvert {
|
|
my ($d,$tag) = @_;
|
|
my $ret = xlibconvert($tag,$d->{"readqueue"});
|
|
debugxlib($rep) if $debug;
|
|
skipevent($d, $tag);
|
|
($ret, \$d->{"readqueue"});
|
|
}
|
|
|
|
sub defaultroot {
|
|
my $d = shift;
|
|
return $d->{"Roots"}[$d->{"Screen"}]->{"windowId"};
|
|
}
|
|
sub defaultrootdepth {
|
|
my $d = shift;
|
|
return $d->{"Roots"}[$d->{"Screen"}]->{"rootDepth"};
|
|
}
|
|
|
|
sub x_reply {
|
|
my ($d, $func, $args) = @_;
|
|
serverprint($d, &{$X::xsubs{"newx${func}Req"}}(@$args));
|
|
handle_event($d);
|
|
xqueueconvert($d,"x${func}Reply");
|
|
}
|
|
sub x_iter_raw {
|
|
my ($d, $func, $counter, $vtype, $args) = @_;
|
|
my ($rep,$q) = x_reply($d, $func, $args);
|
|
my ($val,$i,@ret);
|
|
for $i (1..$rep->{$counter}) {
|
|
if ($vtype eq "STRING8") {
|
|
my ($sl) = unpack("C",$$q);
|
|
($sl,$val,$$q) = unpack("C a$sl a*", $$q);
|
|
} else {
|
|
($val,$$q) = unpack($X::xpackof{$vtype}."a*", $$q);
|
|
}
|
|
print "$vtype: <$val>\n" if $debug;
|
|
push(@ret,$val);
|
|
}
|
|
return ($rep, @ret); # some reps have useful info...
|
|
}
|
|
|
|
sub x_iter {
|
|
my ($rep,@ret) = x_iter_raw(@_);
|
|
return @ret;
|
|
}
|
|
sub x_listproperties {
|
|
my ($d, $w) = @_;
|
|
x_iter($d, "ListProperties", "nProperties", "Atom", [$w]);
|
|
}
|
|
|
|
sub x_querytree {
|
|
my ($d, $root) = @_;
|
|
$root = defaultroot($d) if (!defined($root));
|
|
x_iter_raw($d, "QueryTree", "nChildren", "Window", [$root]);
|
|
}
|
|
|
|
sub x_get_keyboard_mapping {
|
|
my ($d, $first, $count) = @_;
|
|
x_iter_raw($d, "GetKeyboardMapping","length","KeySym", [$first,$co\
|
|
unt]);
|
|
}
|
|
sub x_get_modifier_mapping {
|
|
my ($d) = @_;
|
|
x_iter_raw($d, "GetModifierMapping","length","KeyCode");
|
|
}
|
|
|
|
sub x_get_pointer_mapping {
|
|
my ($d) = @_;
|
|
x_iter($d, "GetPointerMapping","nElts","CARD8");
|
|
}
|
|
sub x_imagetext8 {
|
|
my $d = shift;
|
|
my ($w, $gc, $x, $y, $string) = @_;
|
|
my $l = length($string);
|
|
genvecstr($d, "xImageText8Req", [$l,$w,$gc,$x,$y], $string);
|
|
"OK";
|
|
}
|
|
sub x_openfont {
|
|
my $d = shift;
|
|
my ($f) = (@_); # font name
|
|
my $l = length($f);
|
|
genvecstr($d, "xOpenFontReq", [$ret = &next_resource_id,$l], $f);
|
|
$ret;
|
|
}
|
|
sub splitcolor {
|
|
my ($c) = @_;
|
|
return ($$c[0],$$c[1],$$c[2]);
|
|
}
|
|
|
|
sub joincolor {
|
|
my ($r,$g,$b) = @_;
|
|
return [$r,$g,$b];
|
|
}
|
|
sub x_createfontcursor {
|
|
my ($d,$ch,$fore,$back) = @_;
|
|
if (!defined($d->{"cursorfont"})) {
|
|
$d->{"cursorfont"} = x_openfont($d,"cursor");
|
|
}
|
|
my $c = $d->{"cursorfont"};
|
|
my $cursor;
|
|
my ($fr,$fg,$fb) = splitcolor($fore);
|
|
my ($br,$bg,$bb) = splitcolor($back);
|
|
print "Fore($fore): $fr,$fg,$fb\n" if $debug;
|
|
print "Back($back): $br,$bg,$bb\n" if $debug;
|
|
serverprint($d,
|
|
&X::newxCreateGlyphCursorReq($cursor = &next_resource_\
|
|
id,
|
|
$c, # sourcefont
|
|
$c, # maskfont
|
|
$ch, # sourcechar
|
|
$ch+1, # maskchar
|
|
$fr, $fg, $fb,
|
|
$br, $bg, $bb));
|
|
$cursor;
|
|
}
|
|
|
|
sub x_closedisplay {
|
|
my $d = shift;
|
|
close $d->{"XFD"};
|
|
}
|
|
sub x_create_window {
|
|
my($d,$depth,$parent,$x,$y,$w,$h,$bwid,$class,$vis,$mask, @vals) =\
|
|
@_;
|
|
my($ret);
|
|
genvec2($d,"xCreateWindowReq","XID",
|
|
[$depth, $ret = &next_resource_id, $parent,
|
|
$x,$y,$w,$h,$bwid, $class, $vis, $mask], \@vals);
|
|
$ret;
|
|
}
|
|
|
|
sub genvec {
|
|
my ($type, @vals) = @_;
|
|
my $p = $X::xpackof{$type};
|
|
my $nvals = length(pack("C*",unpack($p," "x80)));
|
|
my $val = "";
|
|
while(1) {
|
|
my @v = splice(@vals,0,$nvals);
|
|
$val .= pack($p, @v);
|
|
last if scalar(@vals) <= 0;
|
|
}
|
|
return $val;
|
|
}
|
|
sub genvec2 {
|
|
my ($d, $req, $elem, $args, $vals) = @_;
|
|
my $val = genvec($elem, @$vals);
|
|
serverprint($d,&{$X::xsubs{"new$req"}}(@$args,$val));
|
|
"OK";
|
|
}
|
|
|
|
sub genvecstr {
|
|
my ($d, $req, $args, $val) = @_;
|
|
serverprint($d,&{$X::xsubs{"new$req"}}(@$args,$val));
|
|
"OK";
|
|
}
|
|
|
|
sub xpoly1 {
|
|
my ($req, $type, $d, $draw, $gc, @vals) = @_;
|
|
genvec2($d, "x${req}Req", "x$type", [$draw,$gc], \@vals);
|
|
}
|
|
sub xpolyarcs { xpoly1("PolyArc", "Arc", @_); }
|
|
sub xpolyfillarcs { xpoly1("PolyFillArc", "Arc", @_); }
|
|
sub xpolyrects { xpoly1("PolyRectangle", "Rectangle", @_); }
|
|
sub xpolyfillrects { xpoly1("PolyFillRectangle", "Rectangle", @_); }
|
|
sub xpolysegments { xpoly1("PolySegment", "Segment", @_); }
|
|
|
|
sub xpoly2 {
|
|
my ($req, $type, $d, $mode, $draw, $gc, @points) = @_;
|
|
genvec2($d,"x${req}Req", "x$type", [$mode,$draw,$gc], \@points);
|
|
}
|
|
sub xpolypoints { xpoly2("PolyPoint", "Point", @_); }
|
|
sub xpolylines { xpoly2("PolyLine", "Point", @_); }
|
|
sub xsetselectionowner {
|
|
my ($d,$owner,$selection,$time) = @_;
|
|
serverprint($d, X::newxSetSelectionOwner($owner,$selection,$time))\
|
|
;
|
|
"OK";
|
|
}
|
|
sub xgetselectionowner {
|
|
my ($d) = @_;
|
|
my ($rep,$q) = x_reply($d, "GetSelectionOwner");
|
|
$rep->{"owner"};
|
|
}
|
|
sub xconvertselection {
|
|
my ($d,$who,$selection,$target,$prop,$time) = @_;
|
|
serverprint($d,
|
|
X::newxConvertSelection($who,$selection,$target,$prop,$t\
|
|
ime));
|
|
"OK";
|
|
}
|
|
|
|
# calls this as
|
|
# should be: xsendevent($d,false,PointerWindow,0,X::newxWhatever(...))\
|
|
;
|
|
# xsendevent($d,false,PointerWindow,0,pack($X::xpackof{"selectionClear\
|
|
"},...));
|
|
sub xsendevent {
|
|
my ($d,$prop,$dest,$mask,$event) = @_;
|
|
serverprint($d, X::newxSendEventReq($prop,$dest,$mask,unpack("C32"\
|
|
,$event)));
|
|
"OK";
|
|
}
|
|
sub xgrabpointer {
|
|
my ($d,$owner,$gwind,$mask,$pmode,$kmode,$confw,$cursor,$time) = @\
|
|
_;
|
|
my ($rep,$q) = x_reply($d, "GrabPointer",
|
|
[$owner,$gwind,$mask,$pmode,$kmode,$confw,$\
|
|
cursor,$time]);
|
|
return $rep->{"status"};
|
|
}
|
|
sub xgrabkeyboard {
|
|
my ($d,$owner,$wind,$time,$pmode,$kmode) = @_;
|
|
my ($rep,$q) = x_reply($d, "GrabKeyboard",
|
|
[$owner,$wind,$time,$pmode,$kmode]);
|
|
return $rep->{"status"};
|
|
}
|
|
sub xgrabserver {
|
|
my ($d) = @_;
|
|
serverprint($d, X::xGrabServerReq());
|
|
"OK";
|
|
}
|
|
sub xgrabbutton {
|
|
my ($d,$owner,$grabw,$mask,$pmode,$kmode,$confw,$cursor,$button,$m\
|
|
ods)
|
|
= @_;
|
|
serverprint($d, X::newxGrabButtonReq($owner,$grabw,$mask,$pmode,$k\
|
|
mode,$confw,$cursor,$button,$mods));
|
|
"OK";
|
|
}
|
|
sub xgrabkey {
|
|
my ($d,$owner,$grabw,$mods,$key,$pmode,$kmode) = @_;
|
|
serverprint($d, X::xGrabKeyReq($owner,$grabw,$mods,$key,$pmode,$km\
|
|
ode));
|
|
"OK";
|
|
}
|
|
|
|
sub x_ungrab {
|
|
my ($func, $d, @args) = @_;
|
|
serverprint($d, &{$X::xsubs{"newxUngrab${func}Req"}}(@args));
|
|
"OK";
|
|
}
|
|
sub xungrabpointer { x_ungrab("Pointer", @_); } # time
|
|
sub xungrabkeyboard { x_ungrab("Keyboard", @_); } # time
|
|
sub xungrabbutton { x_ungrab("Button", @_); } # button,window,mods
|
|
sub xungrabkey { x_ungrab("Key", @_); } # keycode,window,mods
|
|
sub xungrabserver { x_ungrab("Server", @_); } # nothing
|
|
sub xallowevents {
|
|
my ($d,$mode,$time) = @_;
|
|
serverprint($d, X::newxAllowEventsReq($mode,$time));
|
|
"OK";
|
|
}
|
|
sub xchangeactivepointergrab {
|
|
my ($d, $cursor, $time, $mask) = @_;
|
|
serverprint($d, X::newxChangeActivePointerGrabReq($cursor,$time,$m\
|
|
ask));
|
|
"OK";
|
|
}
|
|
sub xquerypointer { # just like x_get_geometry
|
|
my ($d, $w) = @_;
|
|
my ($rep,$q) = x_reply($d, "QueryPointer", [$w]);
|
|
$rep;
|
|
}
|
|
1;
|
Download xbeep.pl
|
#!perl
|
|
require "./xbase.pl";
|
|
$xopen = &xlib::x_open_display($ENV{"DISPLAY"});
|
|
die $xlib::status if not defined $xopen;
|
|
|
|
print &xlib::x_beep($xopen,25),"\n";
|
|
xlib::x_closedisplay($xopen);
|
| Issue_05_X14. xdpyinfo.pl
|
Download xdpyinfo.pl
|
#!perl
|
|
require "./xbase.pl";
|
|
$xopen = &xlib::x_open_display($ENV{"DISPLAY"});
|
|
die $xlib::status if not defined $xopen;
|
|
|
|
&xlib::xdebugdisplay($xopen);
|
|
print "remaining in queue: ",length($xopen->{"readqueue"}),"\n";
|
|
@le = &xlib::x_listextensions($xopen);
|
|
print "extensions: ", join("\n name: ",@le), "\n";
|
|
close $xopen->{"XFD"};
|
Download xerror.pl
|
#/*
|
|
# * descriptions of errors in Section 4 of Protocol doc (pp. 350-351);\
|
|
more
|
|
# * verbose descriptions are given in the error database
|
|
# */
|
|
# static Const char * Const _XErrorList[] = {
|
|
@X::ErrorList = (
|
|
"no error",
|
|
"BadRequest",
|
|
"BadValue",
|
|
"BadWindow",
|
|
"BadPixmap",
|
|
"BadAtom",
|
|
"BadCursor",
|
|
"BadFont",
|
|
"BadMatch",
|
|
"BadDrawable",
|
|
"BadAccess",
|
|
"BadAlloc",
|
|
"BadColor",
|
|
"BadGC",
|
|
"BadIDChoice",
|
|
"BadName",
|
|
"BadLength",
|
|
"BadImplementation",
|
|
);
|
xint.perl
Download xlsfont.pl
|
#!perl
|
|
require "./xbase.pl";
|
|
$xopen = &xlib::x_open_display($ENV{"DISPLAY"});
|
|
die $xlib::status if not defined $xopen;
|
|
|
|
$xlib::debugpkt = 1;
|
|
@lf = &xlib::x_listfonts($xopen,shift);
|
|
print "fontnames: ", join("\n name: ",@lf), "\n";
|
|
|
|
close $xopen->{"XFD"};
|
Download xwdhead.pl
|
#!perl
|
|
package xlib;
|
|
|
|
# read(XWDFILE,$dat,$X::xsizeof{"XWDFileHeader"}) || return "read:$!\
|
|
";
|
|
# read(XWDFILE,$win_nam, $xwddat->{"header_size"} - $xwddat->{\
|
|
"sizeof"})
|
|
# read(XWDFILE,$xwd_colors, $X::xsizeof{"xColorItem"} * $xwddat->\
|
|
{"ncolors"})
|
|
# read(XWDFILE,$xwd_image, $xwddat->{"bytes_per_line"} * $xwd_ima\
|
|
ge_height)
|
|
sub getxwd_read {
|
|
my($fname) = @_;
|
|
open(XWDFILE,$fname) || die "getxwd_read: $fname: $!";
|
|
sub xread {
|
|
my $v=""; my $sz = shift;
|
|
read(XWDFILE,$v,$sz) || die "xread: $!";
|
|
return $v;
|
|
}
|
|
getxwd_core(\&xread);
|
|
}
|
|
|
|
sub getxwd_str {
|
|
my($xwdbits)=@_;
|
|
my $ptr = 0;
|
|
sub xsubstr {
|
|
my $sz = shift;
|
|
my $v = substr($xwdbits,$ptr,$sz);
|
|
$ptr += $sz;
|
|
return $v;
|
|
}
|
|
getxwd_core(\&xsubstr);
|
|
}
|
|
|
|
sub getxwd_core {
|
|
my($readfn)=@_;
|
|
my($dat) = "";
|
|
$win_nam="";
|
|
$xwd_colors="";
|
|
$xwd_image="";
|
|
$dat = &$readfn($X::xsizeof{"XWDFileHeader"});
|
|
$xwddat = xlibconvert("XWDFileHeader",$dat);
|
|
|
|
if ($X::defines{"XWD_FILE_VERSION"} !=
|
|
$xwddat->{"file_version"}) {
|
|
$X::xpackof{"XWDFileHeader"} =~ s/L/N/g;
|
|
$xwddat = xlibconvert("XWDFileHeader",$dat);
|
|
if ($X::defines{"XWD_FILE_VERSION"} !=
|
|
$xwddat->{"file_version"}) {
|
|
return "xwud: XWD file format version missmatch.";
|
|
}
|
|
}
|
|
if ($xwddat->{"header_size"} < $xwddat->{"sizeof"}) {
|
|
return "xwud: XWD header size is too small.";
|
|
}
|
|
$win_nam = &$readfn($xwddat->{"header_size"} - $xwddat->{"si\
|
|
zeof"});
|
|
$xwd_image_width = $xwddat->{"pixmap_width"};
|
|
$xwd_image_height = $xwddat->{"pixmap_height"};
|
|
$xwd_image_depth = $xwddat->{"pixmap_depth"};
|
|
# coincidentally, XColorItem is the same as XColor...
|
|
$xwd_colors = &$readfn($X::xsizeof{"xColorItem"} * $xwddat->{"n\
|
|
colors"});
|
|
$xwd_image = &$readfn($xwddat->{"bytes_per_line"} * $xwd_image\
|
|
_height);
|
|
return "OK";
|
|
}
|
|
1;
|
Download xwininfo.c
|
/* $XConsortium: xwininfo.c,v 1.55 94/04/17 20:24:40 rws Exp $ */
|
|
/*
|
|
|
|
Copyright (c) 1987 X Consortium
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
a copy of this software and associated documentation files (the
|
|
"Software"), to deal in the Software without restriction, including
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be include\
|
|
d
|
|
in all copies or substantial portions of the Software.
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRES\
|
|
S
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
Except as contained in this notice, the name of the X Consortium shall
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
other dealings in this Software without prior written authorization
|
|
from the X Consortium.
|
|
|
|
*/
|
|
|
|
/*
|
|
* xwininfo.c - MIT Project Athena, X Window system window
|
|
* information utility.
|
|
*
|
|
*
|
|
* This program will report all relevant information
|
|
* about a specific window.
|
|
*
|
|
* Author: Mark Lillibridge, MIT Project Athena
|
|
* 16-Jun-87
|
|
*/
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Xos.h>
|
|
#include <X11/extensions/shape.h>
|
|
#include <X11/Xmu/WinUtil.h>
|
|
#include <stdio.h>
|
|
/* Include routines to handle parsing defaults */
|
|
#include "dsimple.h"
|
|
|
|
static char *window_id_format = "0x%lx";
|
|
|
|
/*
|
|
* Report the syntax for calling xwininfo:
|
|
*/
|
|
usage()
|
|
{
|
|
fprintf (stderr,
|
|
"usage: %s [-options ...]\n\n", program_name);
|
|
fprintf (stderr,
|
|
"where options include:\n");
|
|
fprintf (stderr,
|
|
" -help print this message\n");
|
|
fprintf (stderr,
|
|
" -display host:dpy X server to contact\n");
|
|
fprintf (stderr,
|
|
" -root use the root window\n");
|
|
fprintf (stderr,
|
|
" -id windowid use the window with the specified id\
|
|
\n");
|
|
fprintf (stderr,
|
|
" -name windowname use the window with the specified na\
|
|
me\n");
|
|
fprintf (stderr,
|
|
" -int print window id in decimal\n");
|
|
fprintf (stderr,
|
|
" -children print parent and child identifiers\n\
|
|
");
|
|
fprintf (stderr,
|
|
" -tree print children identifiers recursive\
|
|
ly\n");
|
|
fprintf (stderr,
|
|
" -stats print window geometry [DEFAULT]\n");
|
|
fprintf (stderr,
|
|
" -bits print window pixel information\n");
|
|
fprintf (stderr,
|
|
" -events print events selected for on window\\
|
|
n");
|
|
fprintf (stderr,
|
|
" -size print size hints\n");
|
|
fprintf (stderr,
|
|
" -wm print window manager hints\n");
|
|
fprintf (stderr,
|
|
" -shape print shape extents\n");
|
|
fprintf (stderr,
|
|
" -frame don't ignore window manager frames\n\
|
|
");
|
|
fprintf (stderr,
|
|
" -english print sizes in english units\n");
|
|
fprintf (stderr,
|
|
" -metric print sizes in metric units\n");
|
|
fprintf (stderr,
|
|
" -all -tree, -stats, -bits, -events, -wm, \
|
|
-size, -shape\n");
|
|
fprintf (stderr,
|
|
"\n");
|
|
exit (1);
|
|
}
|
|
|
|
/*
|
|
* pixel to inch, metric converter.
|
|
* Hacked in by Mark W. Eichin <eichin@athena> [eichin:19880619.\
|
|
1509EST]
|
|
*
|
|
* Simply put: replace the old numbers with string print calls.
|
|
* Returning a local string is ok, since we only ever get called to
|
|
* print one x and one y, so as long as they don't collide, they're
|
|
* fine. This is not meant to be a general purpose routine.
|
|
*
|
|
*/
|
|
#define getdsp(var,fn) var = fn(dpy, DefaultScreen(dpy))
|
|
int xp=0, xmm=0;
|
|
int yp=0, ymm=0;
|
|
int bp=0, bmm=0;
|
|
int english = 0, metric = 0;
|
|
void scale_init()
|
|
{
|
|
getdsp(yp, DisplayHeight);
|
|
getdsp(ymm, DisplayHeightMM);
|
|
getdsp(xp, DisplayWidth);
|
|
getdsp(xmm, DisplayWidthMM);
|
|
bp = xp + yp;
|
|
bmm = xmm + ymm;
|
|
}
|
|
#define MILE (5280*12)
|
|
#define YARD (3*12)
|
|
#define FOOT (12)
|
|
char *nscale(n, np, nmm, nbuf)
|
|
int n, np, nmm;
|
|
char *nbuf;
|
|
{
|
|
sprintf(nbuf, "%d", n);
|
|
if(metric||english) {
|
|
sprintf(nbuf+strlen(nbuf), " (");
|
|
}
|
|
if(metric) {
|
|
sprintf(nbuf+strlen(nbuf),"%.2f mm%s", ((double) n)*nmm/np, englis\
|
|
h?"; ":"");
|
|
}
|
|
if(english) {
|
|
double inch_frac;
|
|
Bool printed_anything = False;
|
|
int mi, yar, ft, inr;
|
|
inch_frac = ((double) n)*(nmm/25.4)/np;
|
|
inr = (int)inch_frac;
|
|
inch_frac -= (double)inr;
|
|
if(inr>=MILE) {
|
|
mi = inr/MILE;
|
|
inr %= MILE;
|
|
sprintf(nbuf+strlen(nbuf), "%d %s(?!?)",
|
|
mi, (mi==1)?"mile":"miles");
|
|
printed_anything = True;
|
|
}
|
|
if(inr>=YARD) {
|
|
yar = inr/YARD;
|
|
inr %= YARD;
|
|
if (printed_anything)
|
|
sprintf(nbuf+strlen(nbuf), ", ");
|
|
sprintf(nbuf+strlen(nbuf), "%d %s",
|
|
yar, (yar==1)?"yard":"yards");
|
|
printed_anything = True;
|
|
}
|
|
if(inr>=FOOT) {
|
|
ft = inr/FOOT;
|
|
inr %= FOOT;
|
|
if (printed_anything)
|
|
sprintf(nbuf+strlen(nbuf), ", ");
|
|
sprintf(nbuf+strlen(nbuf), "%d %s",
|
|
ft, (ft==1)?"foot":"feet");
|
|
printed_anything = True;
|
|
}
|
|
if (!printed_anything || inch_frac != 0.0 || inr != 0) {
|
|
if (printed_anything)
|
|
sprintf(nbuf+strlen(nbuf), ", ");
|
|
sprintf(nbuf+strlen(nbuf), "%.2f inches", inr+inch_frac);
|
|
}
|
|
}
|
|
if (english || metric) strcat (nbuf, ")");
|
|
return(nbuf);
|
|
}
|
|
char xbuf[BUFSIZ];
|
|
char *xscale(x)
|
|
int x;
|
|
{
|
|
if(!xp) {
|
|
scale_init();
|
|
}
|
|
return(nscale(x, xp, xmm, xbuf));
|
|
}
|
|
char ybuf[BUFSIZ];
|
|
char *yscale(y)
|
|
int y;
|
|
{
|
|
if(!yp) {
|
|
scale_init();
|
|
}
|
|
return(nscale(y, yp, ymm, ybuf));
|
|
}
|
|
char bbuf[BUFSIZ];
|
|
char *bscale(b)
|
|
int b;
|
|
{
|
|
if(!bp) {
|
|
scale_init();
|
|
}
|
|
return(nscale(b, bp, bmm, bbuf));
|
|
}
|
|
/* end of pixel to inch, metric converter */
|
|
/* This handler is enabled when we are checking
|
|
to see if the -id the user specified is valid. */
|
|
|
|
/* ARGSUSED */
|
|
bad_window_handler(disp, err)
|
|
Display *disp;
|
|
XErrorEvent *err;
|
|
{
|
|
char badid[20];
|
|
sprintf(badid, window_id_format, err->resourceid);
|
|
Fatal_Error("No such window with id %s.", badid);
|
|
exit (1);
|
|
}
|
|
|
|
main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
register int i;
|
|
int tree = 0, stats = 0, bits = 0, events = 0, wm = 0, size = 0, sh\
|
|
ape = 0;
|
|
int frame = 0, children = 0;
|
|
Window window;
|
|
|
|
INIT_NAME;
|
|
|
|
/* Open display, handle command line arguments */
|
|
Setup_Display_And_Screen(&argc, argv);
|
|
/* Get window selected on command line, if any */
|
|
window = Select_Window_Args(&argc, argv);
|
|
|
|
/* Handle our command line arguments */
|
|
for (i = 1; i < argc; i++) {
|
|
if (!strcmp(argv[i], "-help"))
|
|
usage();
|
|
if (!strcmp(argv[i], "-int")) {
|
|
window_id_format = "%ld";
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-children")) {
|
|
children = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-tree")) {
|
|
tree = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-stats")) {
|
|
stats = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-bits")) {
|
|
bits = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-events")) {
|
|
events = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-wm")) {
|
|
wm = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-frame")) {
|
|
frame = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-size")) {
|
|
size = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-shape")) {
|
|
shape = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-english")) {
|
|
english = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-metric")) {
|
|
metric = 1;
|
|
continue;
|
|
}
|
|
if (!strcmp(argv[i], "-all")) {
|
|
tree = stats = bits = events = wm = size = shape = 1;
|
|
continue;
|
|
}
|
|
usage();
|
|
}
|
|
/* If no window selected on command line, let user pick one the hard\
|
|
way */
|
|
if (!window) {
|
|
printf("\n");
|
|
printf("xwininfo: Please select the window about which you\n\
|
|
");
|
|
printf(" would like information by clicking the\n")\
|
|
;
|
|
printf(" mouse in that window.\n");
|
|
window = Select_Window(dpy);
|
|
if (window && !frame) {
|
|
Window root;
|
|
int dummyi;
|
|
unsigned int dummy;
|
|
if (XGetGeometry (dpy, window, &root, &dummyi, &dummyi,
|
|
&dummy, &dummy, &dummy, &dummy) &&
|
|
window != root)
|
|
window = XmuClientWindow (dpy, window);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Do the actual displaying as per parameters
|
|
*/
|
|
if (!(children || tree || bits || events || wm || size))
|
|
stats = 1;
|
|
|
|
/*
|
|
* make sure that the window is valid
|
|
*/
|
|
{
|
|
Window root;
|
|
int x, y;
|
|
unsigned width, height, bw, depth;
|
|
int (*old_handler)();
|
|
old_handler = XSetErrorHandler(bad_window_handler);
|
|
XGetGeometry (dpy, window, &root, &x, &y, &width, &height, &bw, &d\
|
|
epth);
|
|
XSync (dpy, False);
|
|
(void) XSetErrorHandler(old_handler);
|
|
}
|
|
printf("\nxwininfo: Window id: ");
|
|
Display_Window_Id(window, True);
|
|
if (children || tree)
|
|
Display_Tree_Info(window, tree);
|
|
if (stats)
|
|
Display_Stats_Info(window);
|
|
if (bits)
|
|
Display_Bits_Info(window);
|
|
if (events)
|
|
Display_Events_Info(window);
|
|
if (wm)
|
|
Display_WM_Info(window);
|
|
if (size)
|
|
Display_Size_Hints(window);
|
|
if (shape)
|
|
Display_Window_Shape(window);
|
|
printf("\n");
|
|
exit(0);
|
|
}
|
|
|
|
/*
|
|
* Lookup: lookup a code in a table.
|
|
*/
|
|
typedef struct {
|
|
long code;
|
|
char *name;
|
|
} binding;
|
|
|
|
static char _lookup_buffer[100];
|
|
|
|
char *LookupL(code, table)
|
|
long code;
|
|
binding *table;
|
|
{
|
|
char *name;
|
|
|
|
sprintf(_lookup_buffer, "unknown (code = %ld. = 0x%lx)", code,\
|
|
code);
|
|
name = _lookup_buffer;
|
|
while (table->name) {
|
|
if (table->code == code) {
|
|
name = table->name;
|
|
break;
|
|
}
|
|
table++;
|
|
}
|
|
return(name);
|
|
}
|
|
|
|
char *Lookup(code, table)
|
|
int code;
|
|
binding *table;
|
|
{
|
|
return LookupL((long)code, table);
|
|
}
|
|
/*
|
|
* Routine to display a window id in dec/hex with name if window has o\
|
|
ne
|
|
*/
|
|
Display_Window_Id(window, newline_wanted)
|
|
Window window;
|
|
Bool newline_wanted;
|
|
{
|
|
char *win_name;
|
|
printf(window_id_format, window); /* print id # in hex/dec\
|
|
*/
|
|
if (!window) {
|
|
printf(" (none)");
|
|
} else {
|
|
if (window == RootWindow(dpy, screen)) {
|
|
printf(" (the root window)");
|
|
}
|
|
if (!XFetchName(dpy, window, &win_name)) { /* Get window name \
|
|
if any */
|
|
printf(" (has no name)");
|
|
} else if (win_name) {
|
|
printf(" \"%s\"", win_name);
|
|
XFree(win_name);
|
|
} else
|
|
printf(" (has no name)");
|
|
}
|
|
|
|
if (newline_wanted)
|
|
printf("\n");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Display Stats on window
|
|
*/
|
|
static binding _window_classes[] = {
|
|
{ InputOutput, "InputOutput" },
|
|
{ InputOnly, "InputOnly" },
|
|
{ 0, 0 } };
|
|
static binding _map_states[] = {
|
|
{ IsUnmapped, "IsUnMapped" },
|
|
{ IsUnviewable, "IsUnviewable" },
|
|
{ IsViewable, "IsViewable" },
|
|
{ 0, 0 } };
|
|
static binding _backing_store_states[] = {
|
|
{ NotUseful, "NotUseful" },
|
|
{ WhenMapped, "WhenMapped" },
|
|
{ Always, "Always" },
|
|
{ 0, 0 } };
|
|
static binding _bit_gravity_states[] = {
|
|
{ ForgetGravity, "ForgetGravity" },
|
|
{ NorthWestGravity, "NorthWestGravity" },
|
|
{ NorthGravity, "NorthGravity" },
|
|
{ NorthEastGravity, "NorthEastGravity" },
|
|
{ WestGravity, "WestGravity" },
|
|
{ CenterGravity, "CenterGravity" },
|
|
{ EastGravity, "EastGravity" },
|
|
{ SouthWestGravity, "SouthWestGravity" },
|
|
{ SouthGravity, "SouthGravity" },
|
|
{ SouthEastGravity, "SouthEastGravity" },
|
|
{ StaticGravity, "StaticGravity" },
|
|
{ 0, 0 }};
|
|
static binding _window_gravity_states[] = {
|
|
{ UnmapGravity, "UnmapGravity" },
|
|
{ NorthWestGravity, "NorthWestGravity" },
|
|
{ NorthGravity, "NorthGravity" },
|
|
{ NorthEastGravity, "NorthEastGravity" },
|
|
{ WestGravity, "WestGravity" },
|
|
{ CenterGravity, "CenterGravity" },
|
|
{ EastGravity, "EastGravity" },
|
|
{ SouthWestGravity, "SouthWestGravity" },
|
|
{ SouthGravity, "SouthGravity" },
|
|
{ SouthEastGravity, "SouthEastGravity" },
|
|
{ StaticGravity, "StaticGravity" },
|
|
{ 0, 0 }};
|
|
static binding _visual_classes[] = {
|
|
{ StaticGray, "StaticGray" },
|
|
{ GrayScale, "GrayScale" },
|
|
{ StaticColor, "StaticColor" },
|
|
{ PseudoColor, "PseudoColor" },
|
|
{ TrueColor, "TrueColor" },
|
|
{ DirectColor, "DirectColor" },
|
|
{ 0, 0 }};
|
|
|
|
Display_Stats_Info(window)
|
|
Window window;
|
|
{
|
|
XWindowAttributes win_attributes;
|
|
XVisualInfo vistemplate, *vinfo;
|
|
XSizeHints hints;
|
|
int dw = DisplayWidth (dpy, screen), dh = DisplayHeight (dpy, screen\
|
|
);
|
|
int rx, ry, xright, ybelow;
|
|
int showright = 0, showbelow = 0;
|
|
Status status;
|
|
Window wmframe;
|
|
int junk;
|
|
long longjunk;
|
|
Window junkwin;
|
|
if (!XGetWindowAttributes(dpy, window, &win_attributes))
|
|
Fatal_Error("Can't get window attributes.");
|
|
vistemplate.visualid = XVisualIDFromVisual(win_attributes.visual);
|
|
vinfo = XGetVisualInfo(dpy, VisualIDMask, &vistemplate, &junk);
|
|
|
|
(void) XTranslateCoordinates (dpy, window, win_attributes.root,
|
|
-win_attributes.border_width,
|
|
-win_attributes.border_width,
|
|
&rx, &ry, &junkwin);
|
|
xright = (dw - rx - win_attributes.border_width * 2 -
|
|
win_attributes.width);
|
|
ybelow = (dh - ry - win_attributes.border_width * 2 -
|
|
win_attributes.height);
|
|
|
|
printf("\n");
|
|
printf(" Absolute upper-left X: %s\n", xscale(rx));
|
|
printf(" Absolute upper-left Y: %s\n", yscale(ry));
|
|
printf(" Relative upper-left X: %s\n", xscale(win_attributes.x));
|
|
printf(" Relative upper-left Y: %s\n", yscale(win_attributes.y));
|
|
printf(" Width: %s\n", xscale(win_attributes.width));
|
|
printf(" Height: %s\n", yscale(win_attributes.height));
|
|
printf(" Depth: %d\n", win_attributes.depth);
|
|
printf(" Visual Class: %s\n", Lookup(vinfo->class, _visual_class\
|
|
es));
|
|
printf(" Border width: %s\n", bscale(win_attributes.border_width));
|
|
printf(" Class: %s\n",
|
|
Lookup(win_attributes.class, _window_classes));
|
|
printf(" Colormap: 0x%lx (%sinstalled)\n",
|
|
win_attributes.colormap, win_attributes.map_installed ? "" : \
|
|
"not ");
|
|
printf(" Bit Gravity State: %s\n",
|
|
Lookup(win_attributes.bit_gravity, _bit_gravity_states));
|
|
printf(" Window Gravity State: %s\n",
|
|
Lookup(win_attributes.win_gravity, _window_gravity_states))\
|
|
;
|
|
printf(" Backing Store State: %s\n",
|
|
Lookup(win_attributes.backing_store, _backing_store_states)\
|
|
);
|
|
printf(" Save Under State: %s\n",
|
|
win_attributes.save_under ? "yes" : "no");
|
|
printf(" Map State: %s\n",
|
|
Lookup(win_attributes.map_state, _map_states));
|
|
printf(" Override Redirect State: %s\n",
|
|
win_attributes.override_redirect ? "yes" : "no");
|
|
printf(" Corners: +%d+%d -%d+%d -%d-%d +%d-%d\n",
|
|
rx, ry, xright, ry, xright, ybelow, rx, ybelow);
|
|
/*
|
|
* compute geometry string that would recreate window
|
|
*/
|
|
printf(" -geometry ");
|
|
|
|
/* compute size in appropriate units */
|
|
status = XGetWMNormalHints(dpy, window, &hints, &longjunk);
|
|
if (status && hints.flags & PResizeInc &&
|
|
hints.width_inc != 0 && hints.height_inc != 0) {
|
|
if (hints.flags & (PBaseSize|PMinSize)) {
|
|
if (hints.flags & PBaseSize) {
|
|
win_attributes.width -= hints.base_width;
|
|
win_attributes.height -= hints.base_height;
|
|
} else {
|
|
/* ICCCM says MinSize is default for BaseSize */
|
|
win_attributes.width -= hints.min_width;
|
|
win_attributes.height -= hints.min_height;
|
|
}
|
|
}
|
|
printf("%dx%d", win_attributes.width/hints.width_inc,
|
|
win_attributes.height/hints.height_inc);
|
|
} else
|
|
printf("%dx%d", win_attributes.width, win_attributes.height);
|
|
if (!(hints.flags&PWinGravity))
|
|
hints.win_gravity = NorthWestGravity; /* per ICCCM */
|
|
/* find our window manager frame, if any */
|
|
wmframe = window;
|
|
while (True) {
|
|
Window root, parent;
|
|
Window *childlist;
|
|
unsigned int ujunk;
|
|
|
|
status = XQueryTree(dpy, wmframe, &root, &parent, &childlist, &u\
|
|
junk);
|
|
if (parent == root || !parent || !status)
|
|
break;
|
|
wmframe = parent;
|
|
if (status && childlist)
|
|
XFree((char *)childlist);
|
|
}
|
|
if (wmframe != window) {
|
|
/* WM reparented, so find edges of the frame */
|
|
/* Only works for ICCCM-compliant WMs, and then only if the
|
|
window has corner gravity. We would need to know the origina\
|
|
l width
|
|
of the window to correctly handle the other gravities. */
|
|
XWindowAttributes frame_attr;
|
|
if (!XGetWindowAttributes(dpy, wmframe, &frame_attr))
|
|
Fatal_Error("Can't get frame attributes.");
|
|
switch (hints.win_gravity) {
|
|
case NorthWestGravity: case SouthWestGravity:
|
|
case NorthEastGravity: case SouthEastGravity:
|
|
case WestGravity:
|
|
rx = frame_attr.x;
|
|
}
|
|
switch (hints.win_gravity) {
|
|
case NorthWestGravity: case SouthWestGravity:
|
|
case NorthEastGravity: case SouthEastGravity:
|
|
case EastGravity:
|
|
xright = dw - frame_attr.x - frame_attr.width -
|
|
2*frame_attr.border_width;
|
|
}
|
|
switch (hints.win_gravity) {
|
|
case NorthWestGravity: case SouthWestGravity:
|
|
case NorthEastGravity: case SouthEastGravity:
|
|
case NorthGravity:
|
|
ry = frame_attr.y;
|
|
}
|
|
switch (hints.win_gravity) {
|
|
case NorthWestGravity: case SouthWestGravity:
|
|
case NorthEastGravity: case SouthEastGravity:
|
|
case SouthGravity:
|
|
ybelow = dh - frame_attr.y - frame_attr.height -
|
|
2*frame_attr.border_width;
|
|
}
|
|
}
|
|
/* If edge gravity, offer a corner on that edge (because the applica\
|
|
tion
|
|
programmer cares about that edge), otherwise offer upper left unl\
|
|
ess
|
|
some other corner is close to an edge of the screen.
|
|
(For corner gravity, assume gravity was set by XWMGeometry.
|
|
For CenterGravity, it doesn't matter.) */
|
|
if (hints.win_gravity == EastGravity ||
|
|
(abs(xright) <= 100 && abs(xright) < abs(rx)
|
|
&& hints.win_gravity != WestGravity))
|
|
showright = 1;
|
|
if (hints.win_gravity == SouthGravity ||
|
|
(abs(ybelow) <= 100 && abs(ybelow) < abs(ry)
|
|
&& hints.win_gravity != NorthGravity))
|
|
showbelow = 1;
|
|
|
|
if (showright)
|
|
printf("-%d", xright);
|
|
else
|
|
printf("+%d", rx);
|
|
if (showbelow)
|
|
printf("-%d", ybelow);
|
|
else
|
|
printf("+%d", ry);
|
|
printf("\n");
|
|
}
|
|
|
|
/*
|
|
* Display bits info:
|
|
*/
|
|
static binding _gravities[] = {
|
|
{ UnmapGravity, "UnMapGravity" }, /* WARNING: both of the\
|
|
se have*/
|
|
{ ForgetGravity, "ForgetGravity" }, /* the same value - see\
|
|
code */
|
|
{ NorthWestGravity, "NorthWestGravity" },
|
|
{ NorthGravity, "NorthGravity" },
|
|
{ NorthEastGravity, "NorthEastGravity" },
|
|
{ WestGravity, "WestGravity" },
|
|
{ CenterGravity, "CenterGravity" },
|
|
{ EastGravity, "EastGravity" },
|
|
{ SouthWestGravity, "SouthWestGravity" },
|
|
{ SouthGravity, "SouthGravity" },
|
|
{ SouthEastGravity, "SouthEastGravity" },
|
|
{ StaticGravity, "StaticGravity" },
|
|
{ 0, 0 } };
|
|
|
|
static binding _backing_store_hint[] = {
|
|
{ NotUseful, "NotUseful" },
|
|
{ WhenMapped, "WhenMapped" },
|
|
{ Always, "Always" },
|
|
{ 0, 0 } };
|
|
|
|
static binding _bool[] = {
|
|
{ 0, "No" },
|
|
{ 1, "Yes" },
|
|
{ 0, 0 } };
|
|
Display_Bits_Info(window)
|
|
Window window;
|
|
{
|
|
XWindowAttributes win_attributes;
|
|
|
|
if (!XGetWindowAttributes(dpy, window, &win_attributes))
|
|
Fatal_Error("Can't get window attributes.");
|
|
printf("\n");
|
|
printf(" Bit gravity: %s\n",
|
|
Lookup(win_attributes.bit_gravity, _gravities+1));
|
|
printf(" Window gravity: %s\n",
|
|
Lookup(win_attributes.win_gravity, _gravities));
|
|
printf(" Backing-store hint: %s\n",
|
|
Lookup(win_attributes.backing_store, _backing_store_hint));
|
|
printf(" Backing-planes to be preserved: 0x%x\n",
|
|
win_attributes.backing_planes);
|
|
printf(" Backing pixel: %d\n", win_attributes.backing_pixel);
|
|
printf(" Save-unders: %s\n",
|
|
Lookup(win_attributes.save_under, _bool));
|
|
}
|
|
|
|
/*
|
|
* Routine to display all events in an event mask
|
|
*/
|
|
static binding _event_mask_names[] = {
|
|
{ KeyPressMask, "KeyPress" },
|
|
{ KeyReleaseMask, "KeyRelease" },
|
|
{ ButtonPressMask, "ButtonPress" },
|
|
{ ButtonReleaseMask, "ButtonRelease" },
|
|
{ EnterWindowMask, "EnterWindow" },
|
|
{ LeaveWindowMask, "LeaveWindow" },
|
|
{ PointerMotionMask, "PointerMotion" },
|
|
{ PointerMotionHintMask, "PointerMotionHint" },
|
|
{ Button1MotionMask, "Button1Motion" },
|
|
{ Button2MotionMask, "Button2Motion" },
|
|
{ Button3MotionMask, "Button3Motion" },
|
|
{ Button4MotionMask, "Button4Motion" },
|
|
{ Button5MotionMask, "Button5Motion" },
|
|
{ ButtonMotionMask, "ButtonMotion" },
|
|
{ KeymapStateMask, "KeymapState" },
|
|
{ ExposureMask, "Exposure" },
|
|
{ VisibilityChangeMask, "VisibilityChange" },
|
|
{ StructureNotifyMask, "StructureNotify" },
|
|
{ ResizeRedirectMask, "ResizeRedirect" },
|
|
{ SubstructureNotifyMask, "SubstructureNotify" },
|
|
{ SubstructureRedirectMask, "SubstructureRedirect" },
|
|
{ FocusChangeMask, "FocusChange" },
|
|
{ PropertyChangeMask, "PropertyChange" },
|
|
{ ColormapChangeMask, "ColormapChange" },
|
|
{ OwnerGrabButtonMask, "OwnerGrabButton" },
|
|
{ 0, 0 } };
|
|
Display_Event_Mask(mask)
|
|
long mask;
|
|
{
|
|
long bit, bit_mask;
|
|
|
|
for (bit=0, bit_mask=1; bit<sizeof(long)*8; bit++, bit_mask <&\
|
|
lt;= 1)
|
|
if (mask & bit_mask)
|
|
printf(" %s\n",
|
|
LookupL(bit_mask, _event_mask_names));
|
|
}
|
|
|
|
/*
|
|
* Display info on events
|
|
*/
|
|
Display_Events_Info(window)
|
|
Window window;
|
|
{
|
|
XWindowAttributes win_attributes;
|
|
if (!XGetWindowAttributes(dpy, window, &win_attributes))
|
|
Fatal_Error("Can't get window attributes.");
|
|
|
|
printf("\n");
|
|
printf(" Someone wants these events:\n");
|
|
Display_Event_Mask(win_attributes.all_event_masks);
|
|
|
|
printf(" Do not propagate these events:\n");
|
|
Display_Event_Mask(win_attributes.do_not_propagate_mask);
|
|
printf(" Override redirection?: %s\n",
|
|
Lookup(win_attributes.override_redirect, _bool));
|
|
}
|
|
|
|
/* left out visual stuff */
|
|
/* left out colormap */
|
|
/* left out map_installed */
|
|
|
|
/*
|
|
* Display root, parent, and (recursively) children information
|
|
*/
|
|
Display_Tree_Info(window, recurse)
|
|
Window window;
|
|
int recurse; /* true if should show children's chi\
|
|
ldren */
|
|
{
|
|
display_tree_info_1(window, recurse, 0);
|
|
}
|
|
display_tree_info_1(window, recurse, level)
|
|
Window window;
|
|
int recurse;
|
|
int level; /* recursion level */
|
|
{
|
|
int i, j;
|
|
int rel_x, rel_y, abs_x, abs_y;
|
|
unsigned int width, height, border, depth;
|
|
Window root_win, parent_win;
|
|
unsigned int num_children;
|
|
Window *child_list;
|
|
XClassHint classhint;
|
|
|
|
if (!XQueryTree(dpy, window, &root_win, &parent_win, &child_list,
|
|
&num_children))
|
|
Fatal_Error("Can't query window tree.");
|
|
|
|
if (level == 0) {
|
|
printf("\n");
|
|
printf(" Root window id: ");
|
|
Display_Window_Id(root_win, True);
|
|
printf(" Parent window id: ");
|
|
Display_Window_Id(parent_win, True);
|
|
}
|
|
|
|
if (level == 0 || num_children > 0) {
|
|
printf(" ");
|
|
for (j=0; j<level; j++) printf(" ");
|
|
printf("%d child%s%s\n", num_children, num_children == 1 ? "" : "r\
|
|
en",
|
|
num_children ? ":" : ".");
|
|
}
|
|
for (i = (int)num_children - 1; i >= 0; i--) {
|
|
printf(" ");
|
|
for (j=0; j<level; j++) printf(" ");
|
|
Display_Window_Id(child_list[i], False);
|
|
printf(": (");
|
|
if(XGetClassHint(dpy, child_list[i], &classhint)) {
|
|
if(classhint.res_name) {
|
|
printf("\"%s\" ", classhint.res_name);
|
|
XFree(classhint.res_name);
|
|
} else
|
|
printf("(none) ");
|
|
if(classhint.res_class) {
|
|
printf("\"%s\") ", classhint.res_class);
|
|
XFree(classhint.res_class);
|
|
} else
|
|
printf("(none)) ");
|
|
} else
|
|
printf(") ");
|
|
|
|
if (XGetGeometry(dpy, child_list[i], &root_win,
|
|
&rel_x, &rel_y, &width, &height, &border, &depth)\
|
|
) {
|
|
Window child;
|
|
|
|
printf (" %ux%u+%d+%d", width, height, rel_x, rel_y);
|
|
if (XTranslateCoordinates (dpy, child_list[i], root_win,
|
|
0 ,0, &abs_x, &abs_y, &child)) {
|
|
printf (" +%d+%d", abs_x - border, abs_y - border);
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
if (recurse)
|
|
display_tree_info_1(child_list[i], 1, level+1);
|
|
}
|
|
|
|
if (child_list) XFree((char *)child_list);
|
|
}
|
|
|
|
/*
|
|
* Display a set of size hints
|
|
*/
|
|
Display_Hints(hints)
|
|
XSizeHints *hints;
|
|
{
|
|
long flags;
|
|
|
|
flags = hints->flags;
|
|
|
|
if (flags & USPosition)
|
|
printf(" User supplied location: %s, %s\n",
|
|
xscale(hints->x), yscale(hints->y));
|
|
|
|
if (flags & PPosition)
|
|
printf(" Program supplied location: %s, %s\n",
|
|
xscale(hints->x), yscale(hints->y));
|
|
|
|
if (flags & USSize) {
|
|
printf(" User supplied size: %s by %s\n",
|
|
xscale(hints->width), yscale(hints->height));
|
|
}
|
|
if (flags & PSize)
|
|
printf(" Program supplied size: %s by %s\n",
|
|
xscale(hints->width), yscale(hints->height));
|
|
if (flags & PMinSize)
|
|
printf(" Program supplied minimum size: %s by %s\n",
|
|
xscale(hints->min_width), yscale(hints->min_hei\
|
|
ght));
|
|
if (flags & PMaxSize)
|
|
printf(" Program supplied maximum size: %s by %s\n",
|
|
xscale(hints->max_width), yscale(hints->max_hei\
|
|
ght));
|
|
if (flags & PBaseSize) {
|
|
printf(" Program supplied base size: %s by %s\n",
|
|
xscale(hints->base_width), yscale(hints->base_h\
|
|
eight));
|
|
}
|
|
|
|
if (flags & PResizeInc) {
|
|
printf(" Program supplied x resize increment: %s\n",
|
|
xscale(hints->width_inc));
|
|
printf(" Program supplied y resize increment: %s\n",
|
|
yscale(hints->height_inc));
|
|
if (hints->width_inc != 0 && hints->height_inc != 0) {
|
|
if (flags & USSize)
|
|
printf(" User supplied size in resize increment\
|
|
s: %s by %s\n",
|
|
(xscale(hints->width / hints->width_inc\
|
|
)),
|
|
(yscale(hints->height / hints->height_i\
|
|
nc)));
|
|
if (flags & PSize)
|
|
printf(" Program supplied size in resize increm\
|
|
ents: %s by %s\n",
|
|
(xscale(hints->width / hints->width_inc\
|
|
)),
|
|
(yscale(hints->height / hints->height_i\
|
|
nc)));
|
|
if (flags & PMinSize)
|
|
printf(" Program supplied minimum size in resiz\
|
|
e increments: %s by %s\n",
|
|
xscale(hints->min_width / hints->width_\
|
|
inc), yscale(hints->min_height / hints->height_inc));
|
|
if (flags & PBaseSize)
|
|
printf(" Program supplied base size in resize i\
|
|
ncrements: %s by %s\n",
|
|
(xscale(hints->base_width / hints->widt\
|
|
h_inc)),
|
|
(yscale(hints->base_height / hints->hei\
|
|
ght_inc)));
|
|
}
|
|
}
|
|
|
|
if (flags & PAspect) {
|
|
printf(" Program supplied min aspect ratio: %s/%s\n",
|
|
xscale(hints->min_aspect.x), yscale(hints->min_\
|
|
aspect.y));
|
|
printf(" Program supplied max aspect ratio: %s/%s\n",
|
|
xscale(hints->max_aspect.x), yscale(hints->max_\
|
|
aspect.y));
|
|
}
|
|
if (flags & PWinGravity) {
|
|
printf(" Program supplied window gravity: %s\n",
|
|
Lookup(hints->win_gravity, _gravities));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Display Size Hints info
|
|
*/
|
|
Display_Size_Hints(window)
|
|
Window window;
|
|
{
|
|
XSizeHints *hints = XAllocSizeHints();
|
|
long supplied;
|
|
printf("\n");
|
|
if (!XGetWMNormalHints(dpy, window, hints, &supplied))
|
|
printf(" No normal window size hints defined\n");
|
|
else {
|
|
printf(" Normal window size hints:\n");
|
|
hints->flags &= supplied;
|
|
Display_Hints(hints);
|
|
}
|
|
|
|
if (!XGetWMSizeHints(dpy, window, hints, &supplied, XA_WM_ZOOM\
|
|
_HINTS))
|
|
printf(" No zoom window size hints defined\n");
|
|
else {
|
|
printf(" Zoom window size hints:\n");
|
|
hints->flags &= supplied;
|
|
Display_Hints(hints);
|
|
}
|
|
XFree((char *)hints);
|
|
}
|
|
|
|
Display_Window_Shape (window)
|
|
Window window;
|
|
{
|
|
Bool ws, bs;
|
|
int xws, yws, xbs, ybs;
|
|
unsigned int wws, hws, wbs, hbs;
|
|
|
|
if (!XShapeQueryExtension (dpy, &bs, &ws))
|
|
return;
|
|
printf("\n");
|
|
XShapeQueryExtents (dpy, window, &ws, &xws, &yws, &wws, &hws,
|
|
&bs, &xbs, &ybs, &wbs, &hbs);
|
|
if (!ws)
|
|
printf(" No window shape defined\n");
|
|
else {
|
|
printf(" Window shape extents: %sx%s",
|
|
xscale(wws), yscale(hws));
|
|
printf("+%s+%s\n", xscale(xws), yscale(yws));
|
|
}
|
|
if (!bs)
|
|
printf(" No border shape defined\n");
|
|
else {
|
|
printf(" Border shape extents: %sx%s",
|
|
xscale(wbs), yscale(hbs));
|
|
printf("+%s+%s\n", xscale(xbs), yscale(ybs));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Display Window Manager Info
|
|
*/
|
|
static binding _state_hints[] = {
|
|
{ DontCareState, "Don't Care State" },
|
|
{ NormalState, "Normal State" },
|
|
{ ZoomState, "Zoomed State" },
|
|
{ IconicState, "Iconic State" },
|
|
{ InactiveState, "Inactive State" },
|
|
{ 0, 0 } };
|
|
Display_WM_Info(window)
|
|
Window window;
|
|
{
|
|
XWMHints *wmhints;
|
|
long flags;
|
|
wmhints = XGetWMHints(dpy, window);
|
|
printf("\n");
|
|
if (!wmhints) {
|
|
printf(" No window manager hints defined\n");
|
|
return;
|
|
}
|
|
flags = wmhints->flags;
|
|
printf(" Window manager hints:\n");
|
|
if (flags & InputHint)
|
|
printf(" Client accepts input or input focus: %s\n",
|
|
Lookup(wmhints->input, _bool));
|
|
if (flags & IconWindowHint) {
|
|
printf(" Icon window id: ");
|
|
Display_Window_Id(wmhints->icon_window, True);
|
|
}
|
|
|
|
if (flags & IconPositionHint)
|
|
printf(" Initial icon position: %s, %s\n",
|
|
xscale(wmhints->icon_x), yscale(wmhints->icon_y\
|
|
));
|
|
|
|
if (flags & StateHint)
|
|
printf(" Initial state is %s\n",
|
|
Lookup(wmhints->initial_state, _state_hints));
|
|
}
|
| Issue_05_X20. xwininfo.pl
|
Download xwininfo.pl
|
#!/usr/bin/perl
|
|
# get libraries
|
|
require "./xbase.pl";
|
|
require "./xatomhash.pl";
|
|
# open the display
|
|
$xopen = &xlib::x_open_display($ENV{"DISPLAY"});
|
|
die $xlib::status if not defined $xopen;
|
|
# map atoms to properties
|
|
tie %xatom, XATOM, $xopen;
|
|
|
|
# print all atoms for window $w on display $d
|
|
sub printatoms {
|
|
my ($d, $w) = @_;
|
|
my @atoms = xlib::x_listproperties($d,$w);
|
|
for $i (@atoms) {
|
|
my $n = $xatom{$i};
|
|
my @x = xlib::x_getproperty($d,
|
|
$X::defines{"xFalse"}, $w, $i,
|
|
$X::defines{"AnyPropertyType"}, 0,255);
|
|
my $ptn = ($x[2]==0)?"*none*":($xatom{$x[2]});
|
|
printf "0x%x (%s)[$ptn]<%s>", $i, $n, $x[1];
|
|
}
|
|
print "\n";
|
|
}
|
|
# query display $d window $w for children;
|
|
# print info with indentation $n
|
|
sub query {
|
|
my ($d,$w,$n)=@_;
|
|
my @lf = &xlib::x_querytree($d, $w);
|
|
shift @lf; # lose the rep, we just want the ki\
|
|
ds
|
|
my $i;
|
|
for $i (@lf) {
|
|
printf("%s%x", " " x $n, $i);
|
|
printatoms($d,$i);
|
|
query($d,$i,$n+1);
|
|
}
|
|
}
|
|
# handle the top level directly
|
|
print "root: ";
|
|
printatoms($xopen,xlib::defaultroot($xopen));
|
|
# now recursively handle the children
|
|
query($xopen,undef,0);
|
|
|
|
# we're done.
|
|
xlib::x_closedisplay($xopen);
|
| Issue_05_X21. More Samples on X
|

Hipocrisy of the finest: "I agree that no single company can create all the hardware and software. Openness is central because it's the foundation of choice." -- Steve Balmer (Microsoft) blaming Apple regarding iPhone, February 18, 2009Last update 1999/02/20 
All Rights Reserved - (C) 1997 - 2009 by The Labs.Com |