The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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");

CAVEATS

Beginning with Mac OS 10.6 Snow Leopard, pasteboards could contain multiple items. Until I upgrade, this package can only access the first item. If your interest is in writing a droplet (that is, an application that processes files which are dropped on it), see the droplet documentation.

This module is in general 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.

On the other hand, it is (or at least may be) convenient to get the text types encoded and decoded properly off the pasteboard. This is what the encode attribute is for. It is false by default because it appears not to work as one would hope under older versions of Mac OS. It also does not cover com.apple.traditional-mac-plain-text because the encoding of this appears to change, and I have been unable to find documentation (or to figure out on my own) which encoding to expect. Caveat user.

Any functionality that involves any character set other than the system's native character set is disabled on versions of Perl before 5.8.4.

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 pasteboards, 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. All methods (or subroutines) that place data on or retrieve data from a pasteboard take the flavor as an argument. This argument 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.

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. If you want to get a status back, you will need to call

 Mac::Pasteboard->set (fatal => 0);

If the attempt to instantiate an object fails, the status is available from

 Mac::Pasteboard->get ('status');

Starting with version 0.012_01 you can pass desired attributes as arguments -- the same name/value pairs that get passed to set(). These come after the pasteboard name if any, but there is no need to specify an explicit undef if you want to default the name but specify attributes; new() will figure it out based on whether the number of arguments is odd or even.

$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 in a given item more than once.

$encoding = $pb->flavor_encoding( $flavor );

This method returns the Unicode encoding of the given flavor, or the default flavor if no flavor is given. If the encoding is unknown, it returns undef.

You can actually call this as a static method, but if you do so you must provide a defined and non-empty value for $flavor.

In fact, this is driven by a table of flavors for which the flavors are known. This table is given under encode, below.

@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.

This method can also be called statically (that is, as Mac::Pasteboard->get ($name)), in which case it returns the static value of the attribute, if any.

($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

$encode = pbencode ();

$old_encode = pbencode ( $new_encode );

this convenience subroutine (b<not> method) returns the encode setting for the system pasteboard. if the argument is defined and not c<''>, the argument becomes the new encode setting and the old encode setting is returned.

$encode = pbencode_find ();

$old_encode = pbencode_find ( $new_encode );

this convenience subroutine (b<not> method) returns the encode setting for the 'find' pasteboard. if the argument is defined and not c<''>, the argument becomes the new encode setting and the old encode setting is returned.

$default_flavor = pbflavor ();

$old_default_flavor = pbflavor ( $new_default_flavor );

this convenience subroutine (b<not> method) returns the default data flavor for the system pasteboard. if the argument is defined and not c<''>, the argument becomes the new default flavor and the old default flavor is returned.

$default_flavor = pbflavor_find ();

$old_default_flavor = pbflavor_find ( $new_default_flavor );

this convenience subroutine (b<not> method) returns the default data flavor for the 'find' pasteboard. if the argument is defined and not c<''>, the argument becomes the new default flavor and the old default flavor is returned.

($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.

This method can also be called statically (that is, as Mac::Pasteboard->set ($name => $value ...)). If an attribute does something useful when set statically, its description will say so. Setting other attributes statically is unsupported, at least in the sense that the author makes no representation what will happen if you do set them, and does not promise that whatever happens when you do this will not change in the future.

$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

The types of the attributes are specified in parentheses after their names. Boolean attributes are interpreted in the Perl sense - that is, undef, 0 and '' are false, and anything else is true.

This class supports the following attributes:

encode (boolean)

This attribute specifies whether or not certain flavors are to be encoded into and decoded from the pasteboard. Supported flavors and the encodings used are:

    public.utf8-plain-text           UTF-8
    public.utf16-plain-text          UTF-16LE
    public.utf16-external-plain-text UTF-16

Flavor com.apple.traditional-mac-plain-text (the initial default flavor) is not supported by this attribute because the normal encoding is undocumented (ASCII? MacRoman? MacSomething depending on locale?). When it has wide characters to handle it seems to get upgraded to UTF-16LE, but how to tell when this is done is also undocumented.

The default value of this attribute is defaultEncode.

default_flavor (string)

This attribute stores the name of the default flavor to use if a flavor is not specified in the copy() or paste() call. The default value of this attribute is defaultFlavor().

fatal (boolean)

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

This attribute can be set statically, in which case it controls whether static methods throw an exception on a pasteboard error. Currently, only new() is affected by this; pbcopy() and friends are subroutines, not static methods.

Setting this statically does not affect the default value of this attribute in an instantiated object.

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.

This name may not be the name you used to create the pasteboard, even if you used one of the built-in names. But unless you created the pasteboard using name kPasteboardUniqueName, the name will be equivalent. That is,

 my $pb1 = Mac::Pasteboard->new();
 my $pb2 = Mac::Pasteboard->new(
     $pb1->get('name'));

gives two handles to the same clipboard.

requested_name (string, readonly)

This attribute reports the name passed to new().

status (dualvar)

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

The static attribute contains the status of the last static method to operate on a pasteboard. Currently, this means the last call to new().

EXPORT

The pbcopy(), pbcopy_find(), pbpaste(), and pbpaste_find() subroutines are exported by default. In addition, tag ':all' exports everything, and tag ':const' exports all constants except those which must be exported explicitly (currently only coreFoundationUnknownErr). 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 in 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. If you get it in use, it probably 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.

coreFoundationUnknownErr

This constant represents the unknown error, not just an unknown error. One would think you would never get this from Apple's code, but it appears that you will get this error if the caller does not have access to the desktop. For example, you can get this error in a script running over an ssh connection, or in a cron job.

This constant is not exported with the :const tag, because there are other places it could potentially come from. If you want it, you will need to import it explicitly. It is not a dualvar -- it just represents the number of the error, which is -4960.

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 module 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.

Other Exports

defaultEncode

This constant specifies the default value of the encode attribute. This is true under macOS 10.15 Catalina and later, and false under earlier versions.

BUGS

Please report bugs either through https://github.com/trwyant/perl-Mac-Pasteboard/issues/ 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.

The pbpaste and pbcopy executables themselves are available, and described by their respective man pages.

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, 2011-2021 by Thomas R. Wyant, III

This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5.10.0. For more details, see the full text of the licenses in the directory LICENSES.

This program 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.