#!/usr/bin/perl -w
# Copyright 2011 Kevin Ryde
# This file is part of X11-Protocol-Other.
#
# X11-Protocol-Other is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 3, or (at your option) any
# later version.
#
# X11-Protocol-Other is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with X11-Protocol-Other. If not, see <http://www.gnu.org/licenses/>.
# Usage: perl xfixes-selection.pl
#
# This is an example of using XFixesSelectSelectionInput() to listen for
# changes to selection ownership.
#
# With just the core protocol this sort of thing has to be done by polling
# GetSelectionOwner() periodically. If you're the selection owner you're
# notified of its loss with an event, but third parties like a cut-buffer
# display have to poll.
#
# The key part is merely $X->XFixesSelectSelectionInput() and the
# XFixesSelectionNotify events. The window creation and GetProperty()
# nonsense are only to retrieve the selection contents. If you're
# interested in selection changes then you probably want to fetch the
# selection contents at some point.
#
# The window supplied to XFixesSelectSelectionInput() doesn't have to be a
# client window. It seems to work to give $X->root. Is it's purpose in the
# protocol to let clients dispatch events to a widget? Or have multiple
# independent parts of a program listening or some such?
#
# The only selection data type supported here is "STRING". A real program
# might ask for "TEXT" to read either STRING or COMPOUND_TEXT. The ICCCM
# spec lists a lot of possible types, but how many are usefully generated by
# programs is another matter.
#
use strict;
use X11::Protocol;
use X11::AtomConstants;
# uncomment this to run the ### lines
#use Smart::Comments;
my $X = X11::Protocol->new;
if (! $X->init_extension('XFIXES')) {
print "XFIXES extension not available on the server\n";
exit 1;
}
my $receiver_window = $X->new_rsrc;
$X->CreateWindow ($receiver_window,
$X->root, # parent
'InputOutput', # class
0, # depth, from parent
'CopyFromParent', # visual
0,0, # x,y
1,1, # width,height
0, # border
event_mask => $X->pack_event_mask('PropertyChange'));
$X->XFixesSelectSelectionInput ($receiver_window, $X->atom('PRIMARY'), 0x07);
my %converts_in_progress;
$X->{'event_handler'} = sub {
my (%h) = @_;
### event_handler: \%h
if ($h{'name'} eq 'XFixesSelectionNotify') {
my $subtype = $h{'subtype'};
my $owner = $h{'owner'};
my $selection_atom = $h{'selection'}; # eg. "PRIMARY"
if ($owner ne 'None') { $owner = sprintf('0x%X',$owner); }
printf("%s %s, owner now %s\n",
$X->atom_name($selection_atom),
$subtype,
$owner);
# ask for selection value
if ($subtype eq 'SetSelectionOwner') {
$X->ConvertSelection ($selection_atom, # atom
$X->atom('STRING'), # type
$selection_atom, # destination
$receiver_window, # destination
$h{'time'});
$converts_in_progress{$selection_atom} = 1;
}
} elsif ($h{'name'} eq 'PropertyNotify'
&& $h{'state'} eq 'NewValue'
# only the selection property receives, not other property changes
&& $converts_in_progress{$h{'atom'}}) {
# selection value received
my ($value, $type, $format, $bytes_after)
= $X->GetProperty ($receiver_window,
$h{'atom'}, # property
'AnyPropertyType', # type
0, # offset
60/4, # length limit, in 4-byte chunks
1); # delete, now have received
### $value
print " value: \"",
$value,
($bytes_after ? " ..." : ""), # if longer than requested size
"\"\n";
}
};
for (;;) {
$X->handle_input;
}
exit 0;