NAME

Mac::Pasteboard - Manipulate Mac OS X clipboards/pasteboards.

SYNOPSIS

To acquire text from the system clipboard, replacing it with your own:

use Mac::Pasteboard;
my $old_text = pbpaste();
pbcopy ("Hello, sailor!\n");

or equivalently, using the object-oriented interface,

use Mac::Pasteboard;
my $pb = Mac::Pasteboard->new ();
my $old_text = $pb->paste ();
$pb->clear ();
$pb->copy ("Hello, sailor!\n");

CAVEAT

This release is for evaluation only. It is early-alpha code at this point. Some of the code (that requiring Mac OS 10.4 or above) has never been executed. And the author makes no commitment whatsoever concerning the stability of the interface. Have fun.

DESCRIPTION

This XS module accesses Mac OS X pasteboards, which can be thought of as clipboards with bells and whistles. Under Mac OS X, the system clipboard is simply a special case of a pasteboard. In the following documentation, 'clipboard' refers to the system clipboard, and 'pasteboard' refers to pasteboards in general.

This module uses the Pasteboard interface, which was introduced in Mac OS 10.3 (a.k.a. 'Panther'), so it requires Mac OS 10.3 or better to run.

The simple case of placing plain text onto and reading it from the system clipboard is accomplished by subroutines pbcopy() and pbpaste() respectively. These correspond roughly to the command-line executables of the same name, and are exported by default. If this is all you are interested in, you can stop reading here. The rest of this section describes the bells and whistles associated with a Mac OS X pasteboard.

A Mac OS X pasteboard contains zero or more data items, each of which is capable of holding one or more flavors of data. The system defines a couple, including the system clipboard, named 'com.apple.pasteboard.clipboard'. The system clipboard is the default taken if new() is called without arguments.

Data items are identified by an item id which is provided by the creator of the item, and which (the documentation says) should only be interpreted by the creator. Item flavors may be duplicated between items but not within items. The item id is an attribute of the Mac::Pasteboard object, with the default chosen so that you should not need to worry about it unless you explicitly want more than one item on a pasteboard.

A flavor is a Uniform Type Identifier which describes the semantics of the data with which it is associated. In practice any string can be used, but you probably want to stick to the system-declared flavors if it is important to you that other software understand your data. The "SEE ALSO" section contains a link to a reference for Uniform Type Identifiers which includes a description of all the system-declared UTIs. The desired flavor can be passed to any method (or subroutine) that places data on or retrieves data from the pasteboard, but defaults to 'com.apple.traditional-mac-plain-text'.

Data may be placed on a pasteboard only by the owner of that pasteboard. Ownership is acquired by clearing the pasteboard. In general, the owner of a pasteboard may either place data directly on to it, or place a promise of data to be generated when the data are actually requested. This module does not support placing a promise onto the pasteboard. It will retrieve data promised by another application, but can not specify a paste location for that data; it is simply returned verbatim.

This module is ignorant of the semantics implied by the system-declared flavors, and makes no attempt to enforce them. In plainer English, it is up to the user of this module to ensure that the specified flavor is actually appropriate to the data it is used to describe. For example, if you store some data on the pasteboard as flavor 'public.jpeg', it is up to you to make sure that the data are, in fact, a valid JPEG image.

METHODS

Some of the methods are documented as returning a status. This status is a dualvar, whose numeric value is the Mac OS error encountered, and whose string value is a description of the error similar to that produced by the Mac::Error 'macerror' script. Errors other than the documented pasteboard error will be described as 'Unknown error' unless Mac::Error is installed and the error is known to that module.

Note, however, that by default the fatal attribute is true, which means an error will result in an exception. If fatal is false, the status will be false for success and true for failure.

The following methods are provided:

$pb = Mac::Pasteboard->new ($name)

This method creates a new pasteboard object, connected to the pasteboard of the given name, creating the pasteboard if necessary. If called with no argument, you get the system clipboard, a.k.a. "kPasteboardClipboard", a.k.a. 'com.apple.pasteboard.clipboard'. Passing undef to new() is not equivalent to calling it with no arguments at all, since undef is the encoding for "kPasteboardUniqueName".

Note that an error in creating a new pasteboard will cause an exception, since the fatal attribute defaults to 1.

$status = $pb->clear ()

This method clears the pasteboard. You must clear the pasteboard before adding data to it.

$clone = $pb->clone ()

This method clones the pasteboard object.

$status = $pb->copy ($data, $flavor, $flags)

This method puts the given data on the pasteboard, identifying it as being of the given flavor, and assigning the given pasteboard flags, which are the bitwise 'or' (a.k.a. the '|' operator) of the individual flavor flags. If $flags is omitted, kPasteboardFlavorNoFlags is used. If $flavor is omitted, undefined, or the empty string, the default flavor is used.

The pasteboard is not cleared prior to this operation; any other data of other flavors remain on the pasteboard.

If the id attribute is undef, the data are placed in the item whose id is 1. Otherwise, the data are placed in the item with the given id. It is an error to attempt to place a given flavor on a given item more than once.

@names = $pb->flavor_flag_names ($flags)

This method (or subroutine) interprets its last argument as flavor flags, and returns the names of the flags set. If no recognized flags are set, you get an empty list.

If called in scalar context you get back the names joined with ', ', or 'kPasteboardFlavorNoFlags' if there are none.

%tags = $pb->flavor_tags ($flavor)

This method (or subroutine) interprets its last argument as a flavor name, and returns the preferred tags associated with the flavor in a hash. The hash will have zero or more of the following keys:

extension: the preferred file name extension for the flavor;
mime: the preferred MIME type for the flavor;
pboard: the preferred NSPBoard type for the flavor;
os: the preferred 4-byte Mac OS document type for the flavor.

If called in scalar context, you get back a reference to the hash.

@flavors = $pb->flavors ($conforms_to)

This method returns the list of data flavors conforming to the given flavor currently on the pasteboard. If $conforms_to is omitted or undef, you get all flavors. If the id attribute is defined, you get only flavors from the corresponding pasteboard item; otherwise you get all conforming flavors. If you turn off the fatal attribute, you will get an empty list if an error occurs, and you will need to check the status attribute so see if the operation actually succeeded.

The return is a list of anonymous hashes, each containing the following keys:

flags: the flavor flags;
flavor: the flavor name;
id: the pasteboard item ID.

If called in scalar context, you get a reference to the list.

The "SEE ALSO" section has a link to the Uniform Type Identifiers Overview, which deals with the notion of type conformance.

$value = $pb->get ($name)

This method returns the value of the given attribute. An exception is thrown if the attribute does not exist.

($data, $flags) = $pb->paste ($flavor)

If the id attribute is defined, this method returns the data of the given flavor from that pasteboard id, and the associated flavor flags; otherwise it returns the data from the last instance of that flavor found, and the associated flavor flags. If no such flavor data is found, an exception is thrown if the missing_ok attribute is false, or undef is returned for $data if missing_ok is true.

You test the $flags value for individual flags by using the bitwise 'and' operator ('&'). For example:

$flags & kPasteboardFlavorSystemTranslated
  and print "This data provided by Translation Services\n";

If called in scalar context, you get $data.

@data = $pb->paste_all ($conforms_to)

This method returns all flavors of data on the pasteboard which conform to the given flavor. If $conforms_to is omitted or undef, all flavors of data are returned. If the id attribute is defined, only data from that pasteboard item are returned; otherwise everything accessible is returned.

The return is a list of anonymous hashes, each having the following keys:

data: the flavor data;
flags: the flavor flags;
flavor: the flavor name;
id: the pasteboard item ID.

If called in scalar context, you get a reference to the list.

The "SEE ALSO" section has a link to the Uniform Type Identifiers Overview, which deals with the notion of type conformance.

pbcopy ($data, $flavor, $flags)

This convenience subroutine (not method) clears the system clipboard and then copies the given data to it. All three arguments are optional (the prototype being (;$$$). If $data is undef, the value of $_ is used. If $flavor is undef, the default flavor is used. If $flags is undef, kPasteboardFlavorNoFlags is used.

In other words, this subroutine is more-or-less equivalent to the 'pbcopy' executable.

pbcopy_find ($data, $flavor, $flags)

This convenience subroutine (not method) clears the 'find' pasteboard and then copies the given data to it. All three arguments are optional (the prototype being (;$$$). If $data is undef, the value of $_ is used. If $flavor is undef, the default flavor is used. If $flags is undef, kPasteboardFlavorNoFlags is used.

In other words, this subroutine is more-or-less equivalent to

$ pbcopy -pboard find

($data, $flags) = pbpaste ($flavor)

This convenience subroutine (not method) retrieves the given flavor of data from the system clipboard, and its associated flavor flags. The flavor is optional, the default being the default flavor. If the given flavor is not found undef is returned for $data.

The functionality is equivalent to calling paste() on an object whose id attribute is undef.

If called in scalar context, you get $data.

In other words, this subroutine is more-or-less equivalent to the 'pbpaste' executable.

($data, $flags) = pbpaste_find ($flavor)

This convenience subroutine (not method) retrieves the given flavor of data from the 'find' pasteboard, and its associated flavor flags. The flavor is optional, the default being the default flavor. If the given flavor is not found undef is returned for $data.

The functionality is equivalent to calling paste() on an object whose id attribute is undef.

If called in scalar context, you get $data.

In other words, this subroutine is more-or-less equivalent to

$ pbpaste -pboard find

$pb = $pb->set ($name => $value ...)

This method sets the values of the given attributes. More than one attribute can be set at a time. An exception is thrown if the attribute does not exist, or if the attribute is read-only. The object is returned, so that calls can be chained.

$flags = $pb->synch ()

This method synchronizes the local copy of the pasteboard with the global pasteboard, and returns the synchronization flags. This should be called on your behalf when needed, but it is exposed because one of the flags returned says whether the calling process owns the pasteboard. For example:

$pb->synch & kPasteboardClientIsOwner
    or $pb->clear ();

to take ownership of the pasteboard (by clearing it) if it is not already owned by the process. Note that kPasteboardClientIsOwner is not imported by default.

@names = $pb->synch_flag_names ($flags)

This method (or subroutine) interprets its last argument as synchronization flags (i.e. as the return from the synch() method), and returns the names of the flags set. If none are set, you get an empty list.

If called in scalar context you get back the names joined with ', ', or an empty string if there are none, since there is no manifest constant for synchronization flags that corresponds to 'kPasteboardFlavorNoFlags'.

ATTRIBUTES

This class supports the following attributes:

fatal (boolean)

If this attribute is true, any pasteboard error throws an exception. If false, error codes are returned to the caller.

The default is 1 (i.e. true).

id (integer)

This attribute supplies the id for data to be copied to or pasted from the pasteboard. In addition to a non-negative integer, it can be set to undef. See copy() and paste() for the effects of this attribute on their action. In most cases you will not need to change this.

The default is undef.

missing_ok (boolean)

If this attribute is true, paste() returns undef if the required flavor is missing, rather than throwing an exception if 'fatal' is true. The pbpaste() subroutine sets this true for the object it manufactures to satisfy its request.

The default is 0 (i.e. false).

name (string, readonly)

This attribute reports the actual name assigned to the pasteboard. Under Panther (Mac OS 10.3) it is the name passed to new (), or the name of the system pasteboard if no name was passed in. Under Tiger (Mac OS 10.4) and above, the actual name is retrieved once the pasteboard is created. If this name cannot be retrieved you get the same result as under Panther.

status (dualvar)

This attribute contains the status of the last operation. You can set this with an integer; the dualvar will be generated.

EXPORT

The pbcopy(), pbcopy_find(), pbpaste(), and pbpaste_find() subroutines are exported by default. In addition, tag ':all' exports everything, and tag ':const' exports constants. Constants are also accessible by &Mac::Pasteboard::constant_name. The following constants are defined:

Error codes

badPasteboardFlavorErr

This constant represents the error number returned when a flavor is not found on the pasteboard. It is not a dualvar -- it just represents the number of the error, which is -25133.

duplicatePasteboardFlavorErr

This constant represents the error number returned when an attempt is made to place on a pasteboard item a flavor that is already there. It is not a dualvar -- it just represents the number of the error, which is -25134.

badPasteboardIndexErr

This constant represents the error number returned when the code indexes off the end of the pasteboard. As such, it represents a bug in this module, and should be reported as such. It is not a dualvar -- it just represents the number of the error, which is -25131.

badPasteboardItemErr

This constant represents the error number returned when the user requests data from a non-existent item ID. It is not a dualvar -- it just represents the number of the error, which is -25132.

badPasteboardSyncErr

This constant represents the error returned when the user tries to fetch stale data from the pasteboard. Because this module is supposed to synchronize before fetching, it represents either a bug or a race condition. It is not a dualvar -- it just represents the number of the error, which is -25130.

noPasteboardPromiseKeeperErr

This constant represents the error returned when the user tries place promised data on the pasteboard without first registering a promise keeper callback. This package does not support promised data. This constant is not a dualvar -- it just represents the number of the error, which is -25136.

notPasteboardOwnerErr

This constant represents the error returned when the user tries place data on the pasteboard without first becoming its owner by clearing it. It is not a dualvar -- it just represents the number of the error, which is -25135.

Flavor flags

kPasteboardFlavorNoFlags

This pasteboard flavor flag is really a value, to be used if no flags are set.

kPasteboardFlavorNotSaved

This pasteboard flavor flag indicates that the flavor's data is volatile, and should not be saved.

kPasteboardFlavorPromised

This pasteboard flavor flag indicates that the flavor's data is promised. This module does not support creating promised data.

kPasteboardFlavorRequestOnly

This pasteboard flavor flag indicates that the flavor must be requested explicitly; scanning for available flavors will not find it.

kPasteboardFlavorSenderOnly

This pasteboard flavor flag indicates that the flavor's data are only available to the process that placed it on the pasteboard.

Oddly enough, the 'pbpaste' executable seems to be able to find such data. But the Pasteboard Peeker demo application can not, so I am pretty sure this is working OK. Unfortunately I was unable to find the source for pbpaste online, so I am unable to verify what's going on.

kPasteboardFlavorSenderTranslated

This pasteboard flavor flag indicates that the flavor's data has been translated in some way by the process that placed it on the clipboard, and it will not be saved by the Finder in clipping files.

kPasteboardFlavorSystemTranslated

This pasteboard flavor flag indicates that the flavor's data must be translated by the Translation Manager. This flag cannot be set programmatically, and the Finder will not save this data in clipping files.

Pasteboard and flavor names

defaultFlavor

This constant represents the name of the default flavor, 'com.apple.traditional-mac-plain-text'.

kPasteboardClipboard

This constant represents the name of the system clipboard, 'com.apple.pasteboard.clipboard'.

kPasteboardFind

This constant represents the name of the find pasteboard, 'com.apple.pasteboard.find'.

kPasteboardUniqueName

This constant specifies that a unique name be generated for the pasteboard. Under Mac OS 10.4 (Tiger) or above, the generated name will be available in the name attribute; under Mac OS 10.3 (Panther), the generated name is unavailable, and the name attribute will be undef.

The value of this constant is documented as (CFStringRef) NULL, so it is represented in Perl by undef.

Synchronization flags

kPasteboardClientIsOwner

This synchronization flag is true if the caller is the owner of the pasteboard.

kPasteboardModified

This synchronization flag indicates that the pasteboard has been modified since the last time this program accessed it, and the local copy of the pasteboard has been synchronized.

BUGS

Please report bugs either through http://rt.cpan.org/ or by mail to the author.

SEE ALSO

The Clipboard module by Ryan King will access text on the clipboard under most operating systems. Under Mac OS X, it shells out to the pbpaste and pbcopy executables. You can also shell out to these yourself if your script requires $^O eq 'darwin'.

The Pasteboard Manager Reference is available online at http://developer.apple.com/documentation/Carbon/Reference/Pasteboard_Reference/Reference/reference.html. See also the Pasteboard Manager Programming Guide at http://developer.apple.com/documentation/Carbon/Conceptual/Pasteboard_Prog_Guide/.

The Uniform Type Identifiers Overview is available online at http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/.

AUTHOR

Thomas R. Wyant, III, wyant at cpan dot org

COPYRIGHT AND LICENSE

Copyright (C) 2008 by Thomas R. Wyant, III. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available.