New org.nspasteboard.RestoredType

69 views
Skip to first unread message

Brian Bucknam

unread,
Jun 8, 2013, 9:36:32 PM6/8/13
to nspast...@googlegroups.com
Hi folks,

I was hoping to attract a few more developers to this group before we started any discussions, but I was not able to get many people, and development of TextExpander touch 2.0 ended up proving the old maxim about the first 80% of a development project taking 80% of the time, and the last 20% of the project taking another 80% of the time!

At the request of Thomas Tempelmann, the next Mac release of TextExpander (4.0.6 or possibly 4.1) plans to include a new org.nspasteboard.RestoredType marker when restoring the pasteboard after a snippet expansion.
The TextExpander snippet expansion process goes like this:
1 - TE creates a copy of the current general pasteboard
2 - TE places the snippet expansion on the pasteboard. It is marked with:
  A - "org.nspasteboard.TransientType"
  B- "de.petermaurer.TransientPasteboardType" (historic equivalent of org.ns...TransientType)
  C - "org.nspasteboard.AutoGeneratedType"
3 - Command-V keystroke is generated to Paste in the snippet
4 - TE restores the pasteboard to the previous contents, but adds a couple of markers:
   A - "org.nspasteboard.TransientType"
   B - "org.nspasteboard.RestoredType"

2A, 2B, and 2C are all just empty data ([NSData data]) intended to serve only as markers.
As a side note, it might make sense for 2C (org.ns...AutoGeneratedType) to contain "TextExpander" or "TextExpander snippet expansion". That is, a string providing some indication of what process auto-generated the pasteboard.

The reasoning behind 4A (inclusion of TransientType on the restored pasteboard) is that simple-minded clipboard history utilities which ignore TransientType entries will thus also ignore the restored contents, thus avoiding multiple instances of the same content from appearing in the history. (TextExpander has included this for a couple years.)

This is similar to the reasoning for 4B, the new RestoredType marker. This marker clearly indicates that the current clipboard contents are, in fact, previous clipboard contents that have been restored.
Per Peter Maurer's suggestion, instead of just being an empty NSData marker, RestoredType contains [NSData dataWithBytes: &changeCount length: sizeof(int64_t)], where changeCount is from the pasteboard being restored.

Reason that discussion seems important:
Adding a RestoredType marker makes the origin and intent of the clipboard restoration clear to applications which support RestoredType, but some clipboard history applications might already be testing clipboard content to see if it matches other very recent clipboard content in order to avoid duplicate entries appearing in the history. Adding the RestoredType marker may make them decide the content does not match, thus resulting in duplicates appearing in the history -- exactly what RestoredType is intended to avoid.

So, additional opinions, options, or suggestions would be appreciated. The more compelling we can make adoption of these nspasteboard.org markers, the more developers will adopt them, and the overall experience of users of all our software should improve.

Thanks for your attention,
Brian Bucknam
Smile Software
--
Smile. Software that's just right.

Günther "gue" Blaschek

unread,
Jun 9, 2013, 6:59:38 AM6/9/13
to nspast...@googlegroups.com
Hi,

We at Ergonis software use the clipboard temporarily for both Typinator and PopChar. Whenever we learn of a new marker for transient clipboard contents, we implement that in order to increase our chances for compatibility with other utilities.

However, as a minimalist, I always look for simple solutions. I am therefore a bit troubled by the inflation of clipboard markers. I doubt that we need so many.

I would therefore suggest the following approach: Let us first understand the circumstances and requirements for all involved parties before we come up with solutions. In the moment, I am not sure that I understand all the requirements, so I would very much like to learn about them first.

As far as I understand the issue, two kinds of parties are involved:
  • Producers temporarily put something in the clipboard.
  • Consumers collect clipboard information.
I can imagine that some utilities act as both producers and consumers. I am not sure if we need a third category for those, or if it is sufficient for these utilities to play the roles of consumers and producers in different situations. If anyone knows more about that, please send input.

Let me start with explaining our needs for PopChar and Typinator. Both utilities fall in the "Producers" category. Typinator uses the clipboard in a more sophisticated way, so I will concentrate on that.

Typinator uses the clipboard to transfer expansions to a target application. The sequence is similar to what Brian described in his posting:
1. save contents of clipboard
2. send expansion:
   2a: fill clipboard with expansion
   2b: force the target application to perform a Paste command
3: restore clipboard (using the data saved in step 1)

In multi-part expansions, step 2 can occur multiple times in a row. Typinator restores the clipboard only once when it is done with an entire expansion sequence.

In steps 2a and 3, Typinator uses pasteboard flavors to tell other utilities that these are transient contents that were not caused by a human user.

What does Typinator need?
Typinator does not want other utilities to interfere with this process. In particular, the timing is sometimes crucial. When another utility starts fetching clipboard contents in the middle of such a sequence, this could lead to unwanted results.
The extra information that is provided by Typinator should be used by consumer utilities in the following way:
  • When they find any of the "transient flavors", Typinator expects them to do nothing. In particular, they should not fetch the actual clipboard data. This saves time and avoids extra inter-process communication caused by the callbacks to the pasteboard promise keepers.
  • Consumers should not expect that clipboards of types 2a and 3 always occur in pairs. They should simply ignore both.
  • For clipboard historians, there is no need to fetch any of these Typinator-generated clipboard contents, as they are either temporary or repetitions of previous clipboards. They should not show up in any clipboard history.

Dear fellow developers: Now I would very much like to learn about your requirements, in particular:

Producers:
  • What else do you use the clipboard for?
  • Are there any other patterns that differ significantly from what Brian and I described?
  • Do you save and restore the clipboard?
  • Which behavior do you expect of a consumer that finds your markers for transient content on the clipboard?
Consumers:
  • What do you use the clipboard for?
  • Do you also act as producers in certain situations?
  • Do you need to distinguish clipboard restoration from other uses (such as 2a and 3 above)?
  • Is it sufficient for you to know that a certain clipboard content is transient, or do you need further information?
  • In the latter case: What other information do you need about transient uses of the clipboard? 
If you have further relevant questions that I did not mention, please add them.



All the best,
Günther "gue" Blaschek, Ergonis Software

Peter Maurer

unread,
Jun 9, 2013, 12:39:07 PM6/9/13
to nspast...@googlegroups.com
Hi everyone,

first of all, thanks for the update, Brian, and thanks for hosting the list! I like the solution we ended up with regarding the restored type's payload, and we have a Butler update ready that will play nice with that new type.

As for the inflation of markers Günther mentioned, I have to admit I could have lived without the distinction between org.nspasteboard.TransientType and org.nspasteboard.AutoGeneratedType, for instance -- Butler treats those two as synonymous when acting as a consumer, as per Günther's definition.

But those two being synonymic also happens to be why I don't mind supporting org.nspasteboard.AutoGeneratedType -- we have a bunch of legacy types to look for anway, so adding one more item to the list doesn't really make a difference.

If we're worried that developers who are new to this might find all those types confusing, maybe it would help to open-source a NSPasteboard category that abstracts away from those types and solves the most common problems. Here's a very simplistic example:

@implementation NSPasteboard (NSPasteboardOrgAdditions)

- (BOOL)org_nspasteboard_isMarkedAsTransient {
static NSArray *singletonTransientTypes = nil;
if (!singletonTransientTypes) {
singletonTransientTypes = [[NSArray arrayWithObjects:
@"org.nspasteboard.TransientType",
@"org.nspasteboard.AutoGeneratedType",
@"com.typeit4me.clipping",
@"Pasteboard generator type",
@"de.petermaurer.TransientPasteboardType",
nil] retain];
}
return [[self types] containsObjectFromArray: singletonTransientTypes];
}

- (BOOL)org_nspasteboard_isRecordable {
return ![self org_nspasteboard_isMarkedAsTransient];
}

@end

In addition to that, there could also be category methods that let you mark pasteboards as transient while you generate them.

With a category like that, adding support for a previously unknown transient type, for instance (LaunchBar? Quicksilver? Alfred? Other apps?), would be as easy as one of us adding it to the category. Then everyone else would get it for free. On the other hand, someone would have to spend their time on setting up and maintaining that category's repo, so I'm not sure if the pros outweigh the cons.

Finally, here are my replies to Günther's questionnaire:

> Producers:
> • What else do you use the clipboard for?

Nothing else.

> • Are there any other patterns that differ significantly from what Brian and I described?

No.

> • Do you save and restore the clipboard?

Yes.

> • Which behavior do you expect of a consumer that finds your markers for transient content on the clipboard?

Ignore it, just like you said.

However, I realize that pasteboard history apps are probably the only ones that will look for those markers and behave as expected. If I had an app that checks the pasteboard for an applicable serial number, for instance, I wouldn't bother checking for transient types first. In fact, I might not even be aware of the concept of transient pasteboards.

> Consumers:
> • What do you use the clipboard for?

Record, convert, change transiently (=> cmd-v), restore/change permanently.

> • Do you also act as producers in certain situations?

Yes. The scenario is the same as the one you described for Typinator.

> • Do you need to distinguish clipboard restoration from other uses (such as 2a and 3 above)?

Aside from some very specific scenarios (I can think of only one right now: an external history recorder starting recording between steps 2a and 3), Butler should work fine with an app that marks restored pasteboards as transient.

However, my gut says that restored pasteboards should either not be marked at all (i.e., be an exact copy of the original one) or marked as restored, if need be. Marking something that might stay on the pasteboard indefinitely as transient strikes me as wrong.

(Yes, I do realize that "Pasteboard generator type" doesn't include the word "transient", but I think it's too late to change the name of org.nspasteboard.TransientType.)

> • Is it sufficient for you to know that a certain clipboard content is transient, or do you need further information?

That's sufficient for us.

Cheers,

Peter.

Peter N Lewis

unread,
Jun 9, 2013, 10:16:15 PM6/9/13
to nspast...@googlegroups.com
On 09/06/2013, at 9:36 , Brian Bucknam <br...@smilesoftware.com> wrote:
> 4 - TE restores the pasteboard to the previous contents, but adds a couple of markers:
> A - "org.nspasteboard.TransientType"

This seems complete wrong to me. The placed data is not transient in any way, it will stay there indefinitely. To say its transient means the org.nspasteboard.TransientType has no valid meaning.

> B - "org.nspasteboard.RestoredType"

And this seems entirely pointless to me. What's the goal? Any clipboard history app (consumer in Günther’s terminology) can easily detect that its the same clipboard, and indeed, all adding this attribute does is break that detection.

What's the point in adding attributes and muddying the definition of existing attributes.

On 10/06/2013, at 0:39 , Peter Maurer <pe...@manytricks.com> wrote:
> But those two being synonymic also happens to be why I don't mind supporting org.nspasteboard.AutoGeneratedType -- we have a bunch of legacy types to look for anway, so adding one more item to the list doesn't really make a difference.

And this seems wrong to me too. AutoGeneratedType and Transient are not interchangeable. Keyboard Maestro uses AutoGeneratedType when it uses Insert Text by Pasting, but the clipboard is not transient, it is set and left - that is the specified behaviour. If a clipboard history app treats it as transient, then the history will not match. If applications are going to treat AutoGeneratedType as equivalent to TransientType, then there is no sense in having AutoGeneratedType, and I will remove its use from Keyboard Maestro when setting the clipboard.

It seems to me that these types are not very well specified since different applications are using them in different ways, and this proposal makes this actively worse since it both further confuses the meaning of TransientType and adds a pointless new RestoredType which was already self evident from the matching clipboards.

To my mind the definition of the types should be:

org.nspasteboard.TransientType: this clipboard is being put on by an application solely for the purposes of pasting some text, and later the clipboard will be restored to the value that was on the clipboard before the action started. There may be a sequence of these TransientType clipboards placed and used before the clipboard is restored. Its value should not be recorded in clipboard history, and the clipboard will soon be restored so that the head of any clipboards without this mark will be restored to the clipboard. Ideally, clipboard history applications should not read the value of any data on the clipboard if this attribute exists. It is the responsibility of the clipboard history application to note that the restored clipboard is the same as the head already on the clipboard history and not duplicate the entry.

org.nspasteboard.AutoGeneratedType: this clipboard is being put on by an application for the purposes of pasting some text. The clipboard will retain this value. This value should be stored on the clipboard history as it will quite possibly end up as the system clipboard for some period of time. This entry should generally not affect any behaviour and is informational only. Which begs the question as to why we have it at all.

So, why do we have org.nspasteboard.AutoGeneratedType? It appears to have no purpose. It should not affect any application behaviour.

So I would propose we scrap org.nspasteboard.AutoGeneratedType, do not add org.nspasteboard.RestoredType, and strictly define what we mean by org.nspasteboard.RestoredType.

On 09/06/2013, at 18:59 , Günther gue Blaschek <gue...@gmail.com> wrote:
> • For clipboard historians, there is no need to fetch any of these Typinator-generated clipboard contents, as they are either temporary or repetitions of previous clipboards. They should not show up in any clipboard history.

In the absence of the org.nspasteboard.RestoredType attribute, it would not be possible to determine that the restored clipboard is a repetition of a previous clipboard without actually reading it. This is the only argument I can see for the org.nspasteboard.RestoredType, and to my mind is insufficient reason for it.

> Producers:
> • What else do you use the clipboard for?

Keyboard Maestro uses the clipboard for a vast variety of things, at the users semi-direction. It blurs all these lines - is it auto generated if the user explicitly sets the clipboard?

Keyboard Maestro *never* restores the clipboard, except if the user directs it explicitly to delete the current clipboard from the clipboard history. Why? Because restoring the clipboard cannot be done safely, there is always a race condition which is unavoidable. This is why Keyboard Maestro has a clipboard history, to embrace that race condition and give the user control over the process. I understand this does not work for text expansion application which must operate more automatically than Keyboard Maestro.

> • Are there any other patterns that differ significantly from what Brian and I described?

Definitely.

* Set the clipboard (with AutoGenerated flag, though I'm rethinking that now, and was always hesitant about its use).
* Paste.

> • Do you save and restore the clipboard?

Yes (save) No (restore).

> • Which behavior do you expect of a consumer that finds your markers for transient content on the clipboard?

I expect them to be ignored, but Keyboard Maestro never sets the transient attribute.

> Consumers:
> • What do you use the clipboard for?

Clipboard History, as well as reading the clipboard for a wide variety of purposes (extracting text or images, saving permanently, searching, changing).

> • Do you also act as producers in certain situations?

Yes.

> • Do you need to distinguish clipboard restoration from other uses (such as 2a and 3 above)?

No - its treated exactly the same as any other case where the clipboard is set to an identical previous value - the previous value is moved to the head of the history.

> • Is it sufficient for you to know that a certain clipboard content is transient, or do you need further information?

That is all I need to know.

Enjoy,
Peter.


--
Keyboard Maestro 6.0.1 now out - Syncing, Plug Ins, Styled Text, Browser Control & More.

Keyboard Maestro <http://www.keyboardmaestro.com/> Macros for your Mac
<http://www.stairways.com/> <http://download.keyboardmaestro.com/>






Peter Maurer

unread,
Jun 10, 2013, 3:17:18 AM6/10/13
to nspast...@googlegroups.com
Peter N Lewis <pe...@stairways.com.au> wrote:

>> But those two being synonymic also happens to be why I don't mind supporting org.nspasteboard.AutoGeneratedType -- we have a bunch of legacy types to look for anway, so adding one more item to the list doesn't really make a difference.
>
> And this seems wrong to me too. AutoGeneratedType and Transient are not interchangeable. Keyboard Maestro uses AutoGeneratedType when it uses Insert Text by Pasting, but the clipboard is not transient, it is set and left - that is the specified behaviour.

Good point. Turns out I had never understood what AutoGeneratedType was for, possibly because given the way Butler works, AutoGeneratedType is merely ornamental. When Butler changes the pasteboard permanently, we don't mark it with AutoGeneratedType as of now; we simply don't mark the pasteboard at all.

Anyway, I was probably the only one who misinterpreted AutoGeneratedType with regard to whether the pasteboard is permanent and should thus be recorded. And my faulty code for detecting transient pasteboards, which I just fixed, was never released. Thanks for setting me straight in the nick of time!

> ...a pointless new RestoredType which was already self evident from the matching clipboards.

Hehe, that was my original point of view on RestoredType when we started discussing this -- before this list existed, unfortunately. But it quickly became obvious that Brian and Thomas were going to stick to the agreement they had already come to, so I adapted by simply making Butler discard RestoredType before recording pasteboards or identifying duplicates.

Then, because the idea of another ornamental pasteboard type still bugged me, I suggested storing the change count for RestoredType instead of making it a zero-data marker -- long term, if people actually do this right, we'll indeed be able to save a few CPU cycles by comparing change counts, rather than compare pasteboards, whenever RestoredType is present. Is that worth making the standard more complicated? I don't know.

I have to admit, though, that I haven't started actively marking pasteboards with RestoredType yet, and will not do so in the immediate future -- as long as we don't know for sure that most pasteboard history apps can deal with that type when looking for duplicates, it's still a net negative in my book.

> So I would propose we scrap org.nspasteboard.AutoGeneratedType, do not add org.nspasteboard.RestoredType...

Fine by me, but like I said, I got the impression that that horse has already bolted. In the meantime, the semi-implementation approach (work around the new types when they're set, but don't set them) I went for may be standards poison, but on the bright side, if the new types do go away, nothing will break.

Cheers,

Peter.

Thomas Tempelmann

unread,
Jun 11, 2013, 5:41:44 AM6/11/13
to nspast...@googlegroups.com
Here are my answers to Günther¹s questions for my tool iClip:

> Producers:
> * What else do you use the clipboard for?

Put previously recorded contents back into the clipboard.

> * Are there any other patterns that differ significantly from what Brian and I
> described?

Huh, not sure.

> * Do you save and restore the clipboard?

Yes, when the user asks to paste a recording back into an app: We save the
current clipboard, fill a new clipboard (adding the TransientType flavor),
issue a Paste command by pressing cmd + V, give the app time to read the
clipboard, then restore the old contents (adding the RestoredType).

> * Which behavior do you expect of a consumer that finds your markers for
> transient content on the clipboard?

TransientType: ignore the clipboard contents entirely
RestoredType: If the app wants to avoid duplicates and has already recorded
earlier clipboard(s), it can skip re-examining the contents and assume
they're the same as the last ones.

> Consumers:
> * What do you use the clipboard for?

Record all contents as much as possible for later restoring at the user's
request.

> * Do you also act as producers in certain situations?

Yes, when restoring clipboards.

> * Do you need to distinguish clipboard restoration from other uses (such as 2a
> and 3 above)?

Yes. Several distinct cases:
1. User may ask to place a recorded clipping into the clipboard. In this
case, we simply place the contents in there, with only the "RestoredType"
marker.
2. User pastes into an app, as described already above.

> * Is it sufficient for you to know that a certain clipboard content is
> transient, or do you need further information?

I also like to know whenever the contents are not the result of a user's
Copy operation, e.g. if the contents are auto generated on the user's
request. In this case, we do not want to record the data because it's not
data the user would feel needs preserving.

Thomas


Thomas Tempelmann

unread,
Jun 11, 2013, 6:01:53 AM6/11/13
to nspast...@googlegroups.com
Sorry, this will be long. But then, I proposed this type, so I need to give
you all the thoughts I have on it.


Peter N. Lewis wrote:

>> 4 - TE restores the pasteboard to the previous contents, but adds a couple of
>> markers: A - "org.nspasteboard.TransientType"
>>
> This seems complete wrong to me. The placed data is not transient in any way,
> it will stay there indefinitely. To say its transient means the
> org.nspasteboard.TransientType has no valid meaning.
>
Brian explained why it's there: Because it prevents apps from blindly
re-examining the clipboard that had already been seen before. Of course, if
all apps would recognize the new "RestoredType", this "TransientType" would
not be necessary here.

Not that I think that we need to do it this way - I am just explaining again
what you didn't seem to have understood from Brian's original mail.

>> B - "org.nspasteboard.RestoredType"
>>
> And this seems entirely pointless to me. What's the goal? Any clipboard
> history app (consumer in Günther¹s terminology) can easily detect that its the
> same clipboard, and indeed, all adding this attribute does is break that
> detection.
And later:
> In the absence of the org.nspasteboard.RestoredType attribute, it would not be
> possible to determine that the restored clipboard is a repetition of a
> previous clipboard without actually reading it. This is the only argument I
> can see for the org.nspasteboard.RestoredType, and to my mind is insufficient
> reason for it.

As long as you think of a clipboard containing only small text clips, I
agree. But imagine it containing huge clips, e.g. Large Images, PDFs. Our
tools would have to read ALL flavors in order to tell if it's a duplicate.

In any case, I'm writing a tool that records EVERYTHING from a clipboard, in
order to restore it later (it's a clipboard recorder, iClip). And my tool
has to deal with possibly huge clipboard data.

In this case, such a marker would be more efficient than having to read the
entire clipboard contents again in order to detect duplicates. Agreed?

(Now that I read the rest of your mail I realize that Keyboard Maestro seems
to do the same as you state that it records images as well, for instance.
Haven't you run into cases where you wished you wouldn't have to read the
entire contents because they're getting huge?)


But then there's one more special case that you may not have considered yet
(but which I answered briefly in my response to Günter's questions):

My tool also adds the "RestoredType" marker when it restores a clipping (at
user's request) that is from ist recording history, i.e. it is not just the
same as the one before a transient clipboard.

This "restored" marker tells others that they've seen this clipboard
somewhere before and that it's NOT something new that the user just COPIED.

IMO, a clipboard recorder is meant to preserve the clips a user has
_created_ (i.e. mainly with the Copy command), so that he can later re-visit
and recover them. A clipboard that a user picks from such a recording
history is NOT a new clip in this sense, and this situation should be marked
in the clipboard accordingly, and therefore I proposed the new type.

In fact, the RestoredType is similar to the use of Keyboard Maestro's
AutoGeneratedType - it marks the contents as something old that was put
there not by a Copy. It's something that doesn't need saving as it can be
recovered by other means.


I also wonder: For apps that like to know if something _new_ (= copied by
user) appears in the clipboard without keeping a history of 100s of previous
clipboard contents, this marker will allow it to tell that this is not
something the user just copied, and thus may not need processing. I don't
know if such apps exist, maybe I'm unncessarily cautious here.


Lastly, no one is required to interpret "RestoredType". You can still employ
your own smart detection if you prefer (I wonder what makes you think that
this type "break that detection."? Peter Maurer originally thought the same,
and I didn't understand it then, either.) Adding this type is just a
courtesy to make it easier for other tools not to require to read the entire
clipboard data to detect dupes.

Thomas


Thomas Tempelmann

unread,
Jun 11, 2013, 6:02:07 AM6/11/13
to nspast...@googlegroups.com
On to the next topic, which I think is better discussed in a separate
thread.

Peter N. Lewis wrote:

> AutoGeneratedType and Transient are not interchangeable. Keyboard Maestro
> uses AutoGeneratedType when it uses Insert Text by Pasting, but the clipboard
> is not transient, it is set and left - that is the specified behaviour. If a
> clipboard history app treats it as transient, then the history will not match.
> If applications are going to treat AutoGeneratedType as equivalent to
> TransientType, then there is no sense in having AutoGeneratedType, and I will
> remove its use from Keyboard Maestro when setting the clipboard.

I'm writing such a clipboard history app. Currently, I treat them the same:
I simply ignore any clipboard with either of these types.

The reasoning for this is that my app wants to record a history of the
user's clipboards, i.e. what he actively copied into the clipboard. To me,
so far, auto generated clipboard content does not fall into this category.
Or should it?

Peter later writes:

> org.nspasteboard.AutoGeneratedType: this clipboard is being put on by an
> application for the purposes of pasting some text. The clipboard will retain
> this value. This value should be stored on the clipboard history as it will
> quite possibly end up as the system clipboard for some period of time. This
> entry should generally not affect any behaviour and is informational only.
> Which begs the question as to why we have it at all.
>
> So, why do we have org.nspasteboard.AutoGeneratedType? It appears to have no
> purpose. It should not affect any application behaviour.

Well - for my history tool, this AutoGeneratedType _does_ serve a purpose:
It tells me not to record it because it was not copied by the user and thus
I do not have to create a backup of it for the user. If the user needs this
one again, he can generate it again using the tool that generated it in the
first place.
Or is that impractical?

Thomas


Thomas Tempelmann

unread,
Jun 11, 2013, 6:11:10 AM6/11/13
to nspast...@googlegroups.com
I like to bring up another marker suggestion that I find much more important
than the discussion on the RestoredType and AutogeneratedType:

I (and many of our users) do not like to see their passwords in plain view
when they're copying them from tools such as 1password.

But how can a clipboard recorder such as iClip detect passwords?

So far, all it can do is to not record _anything_ from apps known to likely
put passwords into the clipboard.

But that doesn't work well at all:

Not only it will prevent recording of non-password data that such apps place
into the clipboard.

No, the real uglyness comes with 1password's browser extensions!

That's because the browser extensions run in the process of the browser,
meaning that I'd have to block recording anything from Safari, FF, Chrome
etc! That's just not practical.

Therefore, we need 1password and similar tools to add a marker that tells us
when we should treat the contents as private.

I suggest a "ConcealedType" for this purpose.

I've tried to raise awareness of this problem with the 1pw makers several
times in the past but they seem to be reluctant to do something about it,
claiming that there's no standard for this. That's where we can step in. If
we declare this a standard and show a list of apps that follow it, the 1pw
guys might be more inclined to adopt it, and hopefully others will do so as
well.

Your thoughts?


Peter Maurer

unread,
Jun 11, 2013, 10:30:27 AM6/11/13
to nspast...@googlegroups.com
Hi Thomas,

> (I wonder what makes you think that this type "break that detection."? Peter Maurer originally thought the same, and I didn't understand it then, either.)

Brian actually mentioned this in his introductory email -- he said:

>> ... some clipboard history applications might already be testing clipboard content to see if it matches other very recent clipboard content in order to avoid duplicate entries appearing in the history. Adding the RestoredType marker may make them decide the content does not match, thus resulting in duplicates appearing in the history -- exactly what RestoredType is intended to avoid.

In other words, history apps that rely on finding duplicates have to be aware of RestoredType in order to exclude RestoredType from the comparison. If they aren't aware of it and thus include RestoredType in the comparison, the original pasteboard (RestoredType not set) and the restored pasteboard (RestoredType) don't match. As a result, you end up with two history entries where there should only be one.

That's the downside I was talking about back then, anyway. And I'm guessing that's what my namesake had in mind, too. :)

Cheers,

Peter.

Thomas Tempelmann

unread,
Jun 11, 2013, 11:23:59 AM6/11/13
to nspast...@googlegroups.com
Peter Maurer wrote:

> In other words, history apps that rely on finding duplicates have to be aware
> of RestoredType in order to exclude RestoredType from the comparison. If they
> aren't aware of it and thus include RestoredType in the comparison, the
> original pasteboard (RestoredType not set) and the restored pasteboard
> (RestoredType) don't match. As a result, you end up with two history entries
> where there should only be one.

Ahh! Thank you for that explanation.

I always add these markers with the additional flag
"kPasteboardFlavorNotSaved", which, as I understood the docs, indicates that
these flavors are to be ignored - and my code that checks for dupes does not
include such flavors, therefore.

However, with the "simplified" Cocoa API, these flavors aren't available any
more, making this non-functional for apps that do not use the Carbon API, I
guess?

Damn.


Brian Bucknam

unread,
Jun 11, 2013, 3:26:45 PM6/11/13
to nspast...@googlegroups.com
Peter L. quoted me:
>> 4 - TE restores the pasteboard to the previous contents, but adds a couple of markers: 
>>    A - "org.nspasteboard.TransientType" 
Then wrote:
> This seems complete wrong to me.  The placed data is not transient in any way,
> it will stay there indefinitely.  To say its transient means the org.nspasteboard.TransientType
> has no valid meaning. 

I agree with this. The person who suggested that behavior is not in this group to defend the proposal, but I think I'll change the TextExpander code before release to not do that.


Then wrote (regarding  "org.nspasteboard.RestoredType" ):
> And this seems entirely pointless to me.  What's the goal?  Any clipboard history app
> (consumer in Günther’s terminology) can easily detect that its the same clipboard,
> and indeed, all adding this attribute does is break that detection. 
>
> What's the point in adding attributes and muddying the definition of existing
> attributes. 

I'm certainly not intending to muddy the definition of the existing attributes. However, what I am proposing is to mark the source and/or intention of the pasteboard contents more clearly, and doing that will likely require more attributes.
As Peter M. and Thomas T. have pointed out, "RestoredType" is useful to avoid reading ALL the pasteboard data in order to compare it to previous contents. (Now that TextExpander includes a crash reporting facility, we see that a significant fraction of crashes occur while we are trying to read or restore the pasteboard, or while other apps are inquiring about the state of a pasteboard that we don't actually "own.")


Peter L. wrote:
>org.nspasteboard.AutoGeneratedType: this clipboard is being put on by an application
> for the purposes of pasting some text.  The clipboard will retain this value.  This value
> should be stored on the clipboard history as it will quite possibly end up as the system
> clipboard for some period of time.  This entry should generally not affect any behaviour 
> and is informational only.  Which begs the question as to why we have it at all. 

From the nspasteboard.org site: @"org.nspasteboard.AutoGeneratedType": content was generated by an application; the user had no intention to Copy this content and may not expect to find it on the pasteboard.

That is exactly the intention of AutoGeneratedType -- the user may not expect to see it in a clipboard history. I certainly don't want TextExpander expansions showing in my clipboard history, and I'm happy that Keyboard Maestro's clipboard function doesn't show them :-) (Of course, they're also marked TransientType, which is more likely the reason why they don't show).

Cheers,
Brian

Brian Bucknam

unread,
Jun 11, 2013, 3:36:09 PM6/11/13
to nspast...@googlegroups.com
On Sunday, June 9, 2013 3:59:38 AM UTC-7, Günther "gue" Blaschek wrote:
I would therefore suggest the following approach: Let us first understand the circumstances and requirements for all involved parties before we come up with solutions. In the moment, I am not sure that I understand all the requirements, so I would very much like to learn about them first.
 
Makes sense. Your clear outline here helps provide a structure to analyze these proposals.

As far as I understand the issue, two kinds of parties are involved:
  • Producers temporarily put something in the clipboard.
  • Consumers collect clipboard information.
I can imagine that some utilities act as both producers and consumers. I am not sure if we need a third category for those, or if it is sufficient for these utilities to play the roles of consumers and producers in different situations. If anyone knows more about that, please send input.

I would just add that not every "producer" produces "temporary" contents.

 
Typinator uses the clipboard to transfer expansions to a target application. The sequence is similar to what Brian described in his posting:
1. save contents of clipboard
2. send expansion:
   2a: fill clipboard with expansion
   2b: force the target application to perform a Paste command
3: restore clipboard (using the data saved in step 1)

In multi-part expansions, step 2 can occur multiple times in a row. Typinator restores the clipboard only once when it is done with an entire expansion sequence.

In steps 2a and 3, Typinator uses pasteboard flavors to tell other utilities that these are transient contents that were not caused by a human user.

What does Typinator need?
Typinator does not want other utilities to interfere with this process. In particular, the timing is sometimes crucial. When another utility starts fetching clipboard contents in the middle of such a sequence, this could lead to unwanted results.

Well stated.
 
Producers:

TextExpander obviously produces and expects very similar things to Typinator.

 
Consumers:

See subsequent thread about proposed "TimeLimited" marker for a different model of production and consumption.

Thanks,
Brian

Peter N Lewis

unread,
Jun 12, 2013, 2:03:07 AM6/12/13
to nspast...@googlegroups.com
On 11/06/2013, at 18:01 , Thomas Tempelmann <tho...@irradiatedsoftware.com> wrote:
> (Now that I read the rest of your mail I realize that Keyboard Maestro seems
> to do the same as you state that it records images as well, for instance.
> Haven't you run into cases where you wished you wouldn't have to read the
> entire contents because they're getting huge?)

Nope - its never been an issue. It's only one of potentially dozens of clipboards stored, so to read one more makes little difference in practice.

> My tool also adds the "RestoredType" marker when it restores a clipping (at
> user's request) that is from ist recording history, i.e. it is not just the
> same as the one before a transient clipboard.
>
> This "restored" marker tells others that they've seen this clipboard
> somewhere before and that it's NOT something new that the user just COPIED.

See, at this point I'm confused as to what's the point. In this case, there is no guarantee I can avoid reading the clipboard.

> IMO, a clipboard recorder is meant to preserve the clips a user has
> _created_ (i.e. mainly with the Copy command), so that he can later re-visit
> and recover them. A clipboard that a user picks from such a recording
> history is NOT a new clip in this sense, and this situation should be marked
> in the clipboard accordingly, and therefore I proposed the new type.

OK, well, clearly I have a different view on this, and unless we can reconcile what we mean by a "clipboard history", I'm not sure we can come up with a useful specification for any of these flavours. At best we can try to identify them and leave it up to the history apps to choose what to do, which is hardly an ideal for a specification.

To my mind, if a user sets the clipboard to something, whether by copying or by selecting a snippet, or a previously saved clipboard, or reading an image to the clipboard or anything else, that is now the head of the clipboard history.

The only exception I would make would be if something is placed temporarily on the clipboard solely for the purpose of immediately pasting in and then removing from the clipboard. Ideally, this would never even touch the clipboard - ideally the value would be inserted directly into the application (as I believe Text Expander does in some situations?), but since there is no practical way to say to an application "paste this specific value" except by setting the clipboard and then pasting it, we are left with this issue to solve.

What do you expect the clipboard history to do if the user elects to paste a previous value? To my mind, that value moves (or duplicates, that would be a matter of personal preference) to the head of the history. The same would be true no matter how the clipboard is set (presuming again it is not transiently set and then restored).

So unless we can get some sort of agreement on what we mean by a clipboard history and its behaviour, I think we're going to be hard pressed to produce a useful specification.

> In fact, the RestoredType is similar to the use of Keyboard Maestro's
> AutoGeneratedType - it marks the contents as something old that was put
> there not by a Copy. It's something that doesn't need saving as it can be
> recovered by other means.

Yes, see I would not be expecting to use the RestoredType for this purpose. You could use the AutoGeneratedType, which, as far as I can see is informational only, and might as well not exist. But if you're meaning for some different behaviour to happen, then that is where we disagree and that's going to be difficult to resolve.

> I also wonder: For apps that like to know if something _new_ (= copied by
> user) appears in the clipboard without keeping a history of 100s of previous
> clipboard contents, this marker will allow it to tell that this is not
> something the user just copied, and thus may not need processing. I don't
> know if such apps exist, maybe I'm unncessarily cautious here.

Again, this sounds more like what I would think of as AutoGeneratedType.

> Lastly, no one is required to interpret "RestoredType". You can still employ
> your own smart detection if you prefer (I wonder what makes you think that
> this type "break that detection."? Peter Maurer originally thought the same,
> and I didn't understand it then, either.) Adding this type is just a
> courtesy to make it easier for other tools not to require to read the entire
> clipboard data to detect dupes.

It breaks the detection unless it is actively ignored. The clipboards are no longer identical, now they differ by this flavour. The only reason it doesn't immediately lead to disaster is that the TransientType is (erroneously IMHO) also included in the newly restored value, despite it not being transient.

I'm thinking of adding code to actively exclude and ignore all org.nspasteboard.* attributes so no future ones can trip up existing code.

On 11/06/2013, at 17:41 , Thomas Tempelmann <tho...@irradiatedsoftware.com> wrote:
>> * Do you need to distinguish clipboard restoration from other uses (such as 2a
>> and 3 above)?
>
> Yes. Several distinct cases:
> 1. User may ask to place a recorded clipping into the clipboard. In this
> case, we simply place the contents in there, with only the "RestoredType"
> marker.

Are you saying in the case where you place a saved clipboard (like a clipping or whatever you want to call it) on the clipboard, you add the RestoredType attribute? If that's the case, then I am completely at a loss as to the intended meanings of this attribute.

On 12/06/2013, at 3:26 , Brian Bucknam <br...@smilesoftware.com> wrote:
> (Now that TextExpander includes a crash reporting facility, we see that a significant fraction of crashes occur while we are trying to read or restore the pasteboard, or while other apps are inquiring about the state of a pasteboard that we don't actually "own.")

that sounds entirely likely.

> Peter L. wrote:
> >org.nspasteboard.AutoGeneratedType: this clipboard is being put on by an application
> > for the purposes of pasting some text. The clipboard will retain this value. This value
> > should be stored on the clipboard history as it will quite possibly end up as the system
> > clipboard for some period of time. This entry should generally not affect any behaviour
> > and is informational only. Which begs the question as to why we have it at all.
>
> From the nspasteboard.org site: @"org.nspasteboard.AutoGeneratedType": content was generated by an application; the user had no intention to Copy this content and may not expect to find it on the pasteboard.
>
> That is exactly the intention of AutoGeneratedType -- the user may not expect to see it in a clipboard history. I certainly don't want TextExpander expansions showing in my clipboard history, and I'm happy that Keyboard Maestro's clipboard function doesn't show them :-) (Of course, they're also marked TransientType, which is more likely the reason why they don't show).


Yes, I agree, my understanding of the type *as specified* is flawed. But I would content the *as specified* is more badly flawed for exactly the reason you state: if the clipboard is transient, its already marked that way.

The question is, if using a clipboard that is marked as AutoGeneratedType that is *not* marked as TransientType, what is the expect behaviour: when would a clipboard producer do this, and what is the expected behaviour of a clipboard history consumer (I like Günthers terms, but add "history" - is there any other type of "clipboard consumer" that cares about any of this?).

In Keyboard Maestro's case, as a clipboard producer, I never use TransientType as I never restore the clipboard, and I use AutoGeneratedType only in the case of Insert Text by Pasting.

As a clipboard history consumer, it is a good question as to what to do at this point. Keyboard Maestro currently would ignore it if anyone else did it (because it follows the specs better than my memory, and doesn't record entries that are marked AutoGeneratedType). However Keyboard Maestro itself doesn't ignore it because it is placed into the history when generated. And now thinking about it more deeply, I have, as stated, serious concerns about not recording a non-transient clipboard to the clipboard history, and the resulting disconnect between the head of the clipboard history and the current clipboard contents.

On 11/06/2013, at 17:41 , Thomas Tempelmann <tho...@irradiatedsoftware.com> wrote:
> I also like to know whenever the contents are not the result of a user's
> Copy operation, e.g. if the contents are auto generated on the user's
> request. In this case, we do not want to record the data because it's not
> data the user would feel needs preserving.

See, this is where I start to get concerned about the use of AutoGeneratedType.

The serious concern I have about this is that if it is not also transient (as it never is in Keyboard Maestro) then not storing it on the clipboard history means you have a current clipboard value that does not appear in your clipboard history. So if the user looks at your clipboard history, and see the last entry is "Fred", and then the press Command-V and instead get "Generated". That seems completely broken to me. Do others disagree - see no problem in the clipboard history being out of sync with the actual contents of the clipboard?

Now, if the auto generated entry is transient, then there isn't any problem, that situation wont remain. But in that case, the clipboard entry would (also) have the TransientType attribute. Which again begs the question, what's the point in the AutoGeneratedType?

So again, I will propose the following spec:

org.nspasteboard.TransientType:
* this clipboard is being put on by an application solely for the purposes of pasting some text.
* the user had no intention to Copy this content and may not expect to find it on the pasteboard.
* the clipboard will promptly be restored to the value that was on the clipboard before the (compound) action started.
* There may be a sequence of these TransientType clipboards placed and used before the clipboard is restored.
* Its value should not be recorded in clipboard history
* the clipboard will soon be restored so that the head of the clipboard history will be restored to the clipboard.
* Ideally, clipboard history applications should not read the value of any data on the clipboard if this attribute exists.
* To facilitate not reading the clipboard data, this attribute should be placed on the clipboard before others.
* It is the responsibility of the clipboard history application to note that the restored clipboard is the same as the head already on the clipboard history and not duplicate the entry.
* Ideally it must be marked with the kPasteboardFlavorNotSaved if at all possible.

org.nspasteboard.AutoGeneratedType: [deprecated - just ignore this flavour]
* this clipboard is being put on by an application for the purposes of pasting some text.
* it should be treated the same as any other clipboard entry by clipboard history applications.
` * This entry should generally not affect any behaviour and is informational only. Which begs the question as to why we have it at all.
* If desired, the AutoGeneratedType and TransientType can both be used, assuming the clipboard is indeed transient.
* Ideally it must be marked with the kPasteboardFlavorNotSaved if at all possible.

org.nspasteboard. RestoredType:
* this clipboard is being restored from its value moments ago.
* It is otherwise identical to the clipboard as it was before a sequence of one or more TransientType are placed on the clipboard.
* To facilitate not reading the clipboard data, this attribute should be placed on the clipboard before others.
* It must never be marked as a TransientType.
* For backward compatibility, it must be marked with the kPasteboardFlavorNotSaved if at all possible.

So TransientType and RestoredType are mutually exclusive.

Sorry, this is rather long.

Thomas Tempelmann

unread,
Jun 12, 2013, 3:17:38 AM6/12/13
to nspast...@googlegroups.com
Peter N. Lewis wrote:

>> Yes. Several distinct cases:
>> 1. User may ask to place a recorded clipping into the clipboard. In this
>> case, we simply place the contents in there, with only the "RestoredType"
>> marker.
>
> Are you saying in the case where you place a saved clipboard (like a clipping
> or whatever you want to call it) on the clipboard, you add the RestoredType
> attribute?

Yes

> If that's the case, then I am completely at a loss as to the
> intended meanings of this attribute.

It's a previously recordeed, i.e. restored, clipboard, i.e. not a genuinely
new one.

However, as I have recently added hashes for ALL recorded clippings, I do
not /need/ this RestoredType any more. So, if there's no consensus for it,
I'm okay with dropping it again.

> On 12/06/2013, at 3:26 , Brian Bucknam <br...@smilesoftware.com> wrote:
>> (Now that TextExpander includes a crash reporting facility, we see that a
>> significant fraction of crashes occur while we are trying to read or restore
>> the pasteboard, or while other apps are inquiring about the state of a
>> pasteboard that we don't actually "own.")
>
> that sounds entirely likely.

Maybe we should compare our algorithm for this in order to spot possible
errors in it? After all, we all want to have our tools peacefully co-exist
if possbile. Or are you suggesting that these crashes are due to bugs in OS
X that we cannot prevent at all?

Peter wrote:
> org.nspasteboard. RestoredType:
> * this clipboard is being restored from its value moments ago.
> * It is otherwise identical to the clipboard as it was before a sequence
> of one or more TransientType are placed on the clipboard.
> * To facilitate not reading the clipboard data, this attribute should be
> placed on the clipboard before others.

Why is this necessary? We can read all flavors without fetching their
contents, can't we? So ist position should not matter.

> * It must never be marked as a TransientType.
> * For backward compatibility, it must be marked with the
> kPasteboardFlavorNotSaved if at all possible.

Besides, we should also specify how identical contents should be detected:
1. ignore all "org.nspasteboard.*" types, or maybe even: ignore all types
with no content (not sure about this).
2. ignore all systemtranslated types (this one is hopefully obvious).

Thomas


Peter N Lewis

unread,
Jun 12, 2013, 3:52:10 AM6/12/13
to nspast...@googlegroups.com
On 12/06/2013, at 15:17 , Thomas Tempelmann <tho...@irradiatedsoftware.com> wrote:
> Or are you suggesting that these crashes are due to bugs in OS X that we cannot prevent at all?

Largely, yes. I'm sure the system pasteboard code is not actually multitasking safe in the presence of multiple changes to the clipboard and multiple apps reading it.

> Peter wrote:
>> org.nspasteboard. RestoredType:
>> * this clipboard is being restored from its value moments ago.
>> * It is otherwise identical to the clipboard as it was before a sequence
>> of one or more TransientType are placed on the clipboard.
>> * To facilitate not reading the clipboard data, this attribute should be
>> placed on the clipboard before others.
>
> Why is this necessary? We can read all flavors without fetching their contents, can't we? So ist position should not matter.

Yes, we can.

But my code already loops through multiple attempts, rereading the clipboard multiple times, each time, reading the items and the flavours, until it eventually gets a read that works without errors (or gives up) - I'm a bit loath to add just another loop, but I suppose it only has to look at the flavour key. OK, forget the part about the order.

>> * It must never be marked as a TransientType.
>> * For backward compatibility, it must be marked with the
>> kPasteboardFlavorNotSaved if at all possible.
>
> Besides, we should also specify how identical contents should be detected:
> 1. ignore all "org.nspasteboard.*" types, or maybe even: ignore all types
> with no content (not sure about this).
> 2. ignore all systemtranslated types (this one is hopefully obvious).

Well, I also ignore the kPasteboardFlavorSenderTranslated ones. Whether that's sensible or not, I couldn't say.

I agree, ignoring all org.nspasteboard seems sensible.

But then there is also a whole stack of other flavours to ignore if you want to avoid causing trouble in Adobe, Microsoft and other applications.

My current list includes:

dyn.ah62d4rv4gk8y2xwpnq
dyn.ah62d4rv4gk8y8wwqmq
dyn.agk8y2xwpnq
dyn.agk8y8wwqmq
dyn.ah62d4rv4gk81g7d3ru
dyn.agk81n65yru
com.adobe.illustrator.aicb
com.adobe.illustrator.hfs

Anyone have any others that cause problems?

Günther "gue" Blaschek

unread,
Jun 12, 2013, 4:10:47 AM6/12/13
to nspast...@googlegroups.com
My current "skip list" also contains the following types:
  dyn.agk8ywxw2ea
  dyn.ah62d4rv4gk8ycwndkk
  dyn.ah62d4rv4gu8zaxcxmuufa4dtsv1y24psqzggc8pfsk

Cheers,
gue

Thomas Tempelmann

unread,
Jun 12, 2013, 5:10:50 AM6/12/13
to nspast...@googlegroups.com
Günther Blaschek's types translated:

dyn.agk8ywxw2ea 'INX '
dyn.ah62d4rv4gk8ycwndkk 'AICB'
dyn.ah62d4rv4gu8zaxcxmuufa4dtsv1y24psqzggc8pfsk "PLSL PhotoLineLayer"

Thomas


Thomas Tempelmann

unread,
Jun 12, 2013, 6:42:15 AM6/12/13
to nspast...@googlegroups.com
BTW,
I wonder what you think about producers identifying themselves when they use
the org.nspasteboard "API", e.g. by adding their bundle ID (along with a
version code, perhaps) in the content of the special org.nspasteboard
type(s). It might help identifying and working around issues when it comes
to interpertation of how to handle it as a consumer.


Günther "gue" Blaschek

unread,
Jun 12, 2013, 8:04:16 AM6/12/13
to nspast...@googlegroups.com
I think it does not hurt. Typinator has been doing this in the past, anyway.
We introduced the "Pasteboard generator type" a couple of years ago and use it for both "transient" and "restored" content.
The clipboard data are not empty but contain the generator's (=Typinator's) name. This is also the meaning of the flavor: This is a pasteboard type for the "Pasteboard generator". We do not say anything about transient or restore, but just tell others who created this clipboard.

For transient, we use:
  "Pasteboard generator type" = "Typinator"
When we restore the original data, we append " (restore)":
  "Pasteboard generator type" = "Typinator (restore)"
However, I don't know if any consumer ever used this information.

Consumers: Can anybody of you tell us if this information would be helpful for you? Would you really want to introduce special cases based on the generator's identity?

gue

Peter Maurer

unread,
Jun 12, 2013, 3:10:55 PM6/12/13
to nspast...@googlegroups.com
> Consumers: Can anybody of you tell us if this information would be helpful for you? Would you really want to introduce special cases based on the generator's identity?

I don't think I would, but on the other hand, it wouldn't do any harm.

One very easy way to support additional, optional info would be taking advantage of NSPasteboard's serialization support and having the standard recommend using property lists, rather than storing manually created data values directly. For RestoredType, that would look roughly like this:

[[NSPasteboard generalPasteboard] setPropertyList: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger: restoredChangeCount], @"Change Count",
@"com.ergonis.Typinator", @"Agent",
nil] forType: @"org.nspasteboard.RestoredType"];

If a "producer" app preferred to stay anonymous, it would simply omit the "Agent" value:

[[NSPasteboard generalPasteboard] setPropertyList: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger: restoredChangeCount], @"Change Count",
nil] forType: @"org.nspasteboard.RestoredType"];

If, on the other hand, it wanted to share additional info, that wouldn't be a problem either:

[[NSPasteboard generalPasteboard] setPropertyList: [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger: restoredChangeCount], @"Change Count",
@"com.ergonis.Typinator", @"Agent",
@"Snippet Expansion Cleanup", @"Purpose",
@"Hi mom!", @"Secret Message",
nil] forType: @"org.nspasteboard.RestoredType"];

Too complicated?

Peter.

Thomas Tempelmann

unread,
Jun 12, 2013, 3:17:46 PM6/12/13
to Peter Maurer, nspast...@googlegroups.com
Peter Maurer wrote:

> One very easy way to support additional, optional info would be taking
> advantage of NSPasteboard's serialization support and having the standard
> recommend using property lists [...]
>
> Too complicated?

This require extra effort to handle with the Carbon API (which iClip still
prefers to use for its wider control over the flags etc.). But then, I have
already added support for reading plists from clipboard items anyway, so
it's not really an issue for me.

I support this proposal.

Thomas


Peter Maurer

unread,
Jun 12, 2013, 3:33:03 PM6/12/13
to nspast...@googlegroups.com
> This require extra effort to handle with the Carbon API...

Hehe, yeah, I felt slightly bad for iClip when I started writing this, but then I remembered that last time we discussed a similar issue, you told me including Cocoa stuff wouldn't be a problem. :)

Peter.

Brian Bucknam

unread,
Jun 12, 2013, 7:45:49 PM6/12/13
to nspast...@googlegroups.com
It seems like I am failing to communicate somehow, at least with Peter Lewis, and perhaps overall.

My feeling is that any specifications provided from NSPasteboard.org should specify the meaning of various markers, but cannot specify how any particular software treats clipboard content with the markers.

That is, I think the org.nspasteboard.* markers should signify source, intent, and other useful information about that instance of the pasteboard. If it can improve the user experience in some scenarios, or reduce developer difficulties, then it makes conforming to the specification worthwhile.

Thomas T. wrote, regarding the "RestoredType" marker:
>> This "restored" marker tells others that they've seen this clipboard 
>> somewhere before and that it's NOT something new that the user just COPIED. 

And Peter L. replied:
>See, at this point I'm confused as to what's the point.  In this case, there is no 
> guarantee I can avoid reading the clipboard. 

Assuming that you associated a changeCount with any given saved clipboard in a history, the "RestoredType" marker seems like it can, in fact, save you from asking for any other data in the pasteboard. One of us is missing something that the other knows? Or maybe your point is that, due to inter-process timing, the earlier 'read' of the clipboard might never have been complete?

Peter L.:
> What do you expect the clipboard history to do if the user elects to paste a
> previous value?  To my mind, that value moves (or duplicates, that would be a
> matter of personal preference) to the head of the history.  The same would be true
> no matter how the clipboard is set (presuming again it is not transiently set and
> then restored). 

Many clipboard history utilities allow you to paste the item "5 back in the history", then quickly restore the pasteboard. They visually present the clipboard history as "not having changed" at this point. 
But, of course, what has actually happened is a transient set, then restore.

Peter L.:
> So unless we can get some sort of agreement on what we mean by a clipboard
> history and its behaviour, I think we're going to be hard pressed to produce a
> useful specification. 

This is where I feel like we have a communication breakdown. If NSPasteboard.org specifies exactly how a clipboard history utility is to work, what is the point of having more than one such utility?
That is, I might prefer one that lets me Paste item 5 without (from the user's perspective) changing the order of "the history" (as described above), or I might not. Perhaps I would like one with an option to NOT ignore TextExpander snippets if I find myself re-using them often. Or some utility that counts how many time I copy or expand the word "cloud" and gives me a penalty score at the end of the day.
The point of NSPasteboard.org is that markers can be added with meta-data to make options such as those possible, and inter-operable with other software. How that data is treated is up to the "consumer".

Later, Peter L. proposed deprecating AutoGeneratedType, and proposed some decent specifications for TransientType and RestoredType.
I think his deprecation of AutoGeneratedType is based on this quote:
> The serious concern I have about this is that if it is not also transient (as it never is
> in Keyboard Maestro) then not storing it on the clipboard history means you have a
> current clipboard value that does not appear in your clipboard history.  So if the user
> looks at your clipboard history, and see the last entry is "Fred", and then the press
> Command-V and instead get "Generated".  That seems completely broken to me.  Do
> others disagree - see no problem in the clipboard history being out of sync with the
> actual contents of the clipboard? 

I will point out that TextExpander has an option to not restore the clipboard after snippet expansion. Those pasteboard entries should, by my way of thinking, be marked "AutoGeneratedType", but of course not marked TransientType.
Why can't I have a clipboard utility that excludes them from the history? The UI dilemma that you present is not that difficult -- specially highlight the current clipboard contents as being something that isn't going to appear in the history.

This is also getting too long, but I like that we have seen some good ideas, useful information, and we may have reached something like consensus on a few topics in this discussion.

Cheers,
Brian

Peter N Lewis

unread,
Jun 12, 2013, 10:33:37 PM6/12/13
to nspast...@googlegroups.com
On 13/06/2013, at 7:45 , Brian Bucknam <br...@smilesoftware.com> wrote:
> It seems like I am failing to communicate somehow, at least with Peter Lewis, and perhaps overall.

Perhaps it's just that we have some different views, and also that it requires a more explicit specification to be able to compare and contrast the results.

> My feeling is that any specifications provided from NSPasteboard.org should specify the meaning of various markers, but cannot specify how any particular software treats clipboard content with the markers.

I sort of agree in principle, but in practice, in my experience when writing specifications it's very hard to do this well because the meaning of something is tied to how it will be used.

For me to know what to mark with AutoGeneratedType in Keyboard Maestro, I need to know what it really means, and what influence that meaning will have on recipients. Keyboard Maestro places data on the clipboard in dozens of different ways, all at the direction of the user, and with a range of explicitly from "Insert Text by Pasting" (fairly implicit use of the clipboard) through to "Read a file into the clipboard" (very explicit).

Here's an example of where I run into problems unless the spec if really well defined. A user creates a macro active in the Finder, that when they press Control-C it reads the selected file into the clipboard. I'm pretty sure any user doing this would expect that clipboard to be treated exactly the same as if they had clicked into the name and pressed Command-C to copy the name.

The opposite end of the spectrum would be that the user is in Mail, and has a macro that creates a new message, inserts text by pasting into the to and subject field, and then deletes both clipboards. I'm sure the user would be perfectly happy if these chunks of text did not appear on any clipboard history.

I'm not going to offer the user the opportunity to make this choice themselves in every possible clipboard setting action, that would add impractical complexity. So the only option is for me to be able to make a guess as to what they are going to want to happen, and for that, I need to know what the results are going to be.

Now, perhaps this is impossible, perhaps there is no way to know what the results are going to be. If that's the case, that's fine, it just means I don't end up using the attributes and accept the consequences. For Keyboard Maestro, that's not a big deal, since it never restores the clipboard, and every time it sets the clipboard it is to at least some degree explicitly done so by the user, albeit indirectly.

> And Peter L. replied:
> >See, at this point I'm confused as to what's the point. In this case, there is no
> > guarantee I can avoid reading the clipboard.
>
> Assuming that you associated a changeCount with any given saved clipboard in a history, the "RestoredType" marker seems like it can, in fact, save you from asking for any other data in the pasteboard. One of us is missing something that the other knows? Or maybe your point is that, due to inter-process timing, the earlier 'read' of the clipboard might never have been complete?

I presumed these saved clippings exist for a significant amount of time, across reboots and the like, and therefore any change count would be unknowable. Even without a reboot, clipboard histories are generally finite, and clippings would easily exceed their lifetime on the clipboard history.

BTW, has anyone verified whether the clipboard change count is consistent across applications? The documentation doesn't appear entirely clear on this subject.

> I will point out that TextExpander has an option to not restore the clipboard after snippet expansion. Those pasteboard entries should, by my way of thinking, be marked "AutoGeneratedType", but of course not marked TransientType.
> Why can't I have a clipboard utility that excludes them from the history? The UI dilemma that you present is not that difficult -- specially highlight the current clipboard contents as being something that isn't going to appear in the history.

Fair enough, although that means it will be read, though I suppose reading could be deferred until it is needed.

It still leaves me with a hard decision as to what clipboards should be marked as AutoGeneratedType clipboards, and what clipboards are just the user copying to the clipboard in a different way than the usual select/Command-C.

Enjoy,

Thomas Tempelmann

unread,
Jun 13, 2013, 3:16:54 AM6/13/13
to nspast...@googlegroups.com
Peter N. Lewis wrote:

> BTW, has anyone verified whether the clipboard change count is consistent
> across applications? The documentation doesn't appear entirely clear on this
> subject.

I have. (I wrote a tool that monitors all 3 APIs concurrently, showing me
what each clipboard has in there at the same time).

The Cocoa API's changeCount is the same across all apps, while the
ScrapMgr's GetCurrentScrap isn't. And the Carbon API doesn't even give us
any counter - it just tells us if the pasteboard has changed since the last
time we checked.

Fortunately, the Cocoa API can be used concurrently along the other APIs,
even in a non-Cocoa app. Therefore, we could define that anyone supporting
the change counter in our markers must use the Cocoa API's function for
this.


Thomas Tempelmann

unread,
Jun 13, 2013, 3:26:20 AM6/13/13
to nspast...@googlegroups.com
Peter N. Lewis wrote:

> It still leaves me with a hard decision as to what clipboards should be marked
> as AutoGeneratedType clipboards, and what clipboards are just the user copying
> to the clipboard in a different way than the usual select/Command-C.

That's why I thought to add "RestoredType".

Both AutoGeneratedType and RestoredType are, while mutually exclusive,
serving the same purpose: Mark items that are not created by a user's
original Copy operation. Such marked items are coming from somewhere
"stored", i.e. they're not _new_ data.

In other words, clipboards having either of these markers can be brought
back, because there's some app (i.e. one of our tools) that can regenerate
that data and put it again into the clipboard.

On the other hand, if a user copies data from a document and closes the
document, that's _new_ data that the user cannot simply regenerate because
there's no clear "handle" for it.

Sure, if the user clears the clipboard history, those to-be-marked items are
gone as well, but that's a concious user decision.

Our two markers, however, tell other apps: Don't worry about preserving
this, we've already got a safe place for it.

I must admit that this info is only interesting to apps that record
clipboards, especially the RestoredType.

I still think that tools that generate macros or expand text should mark
their output with AutoGeneratedType, because I certainly do not want to
record those in iClip, even if they are not transient, i.e. even if they
stay in the clipboard. That is, because I think that, from the user's view,
a text expansion is not conciously a Copy operation, thus it's not something
he expects to appear in iClip's history. That's because iClip is meant to
preserve data he conciously put there, thru Copy, not by a side effect from
a macro expansion.

Thomas


Thomas Tempelmann

unread,
Jun 13, 2013, 3:46:39 AM6/13/13
to nspast...@googlegroups.com
The more I think about it, the less I personally see for the need of
RestoredType, because at least some of iClip's users want to re-order the
history list so that a recently pasted item gets moved to the top of the
list, which I've implemented in recent iClip betas now.

However, this would not work if another clipboard tool with a history such
as Keyboard Maestro would paste an item from its history, and if that pasted
clipboard would include the RestoredMarker.

That means I'll have to ignore the RestoredMarker anyway.

Does anyone else still see a practical use for this marker?

Well, maybe if we make it a standard that any tool should add his signature
to any clipboard content it creates, we'd still have a use for it. But we
could as well introduce an entirely new type for that instead. Though, I
don't see a big need for that atm. I'd be nicer if OSX added an API for
that, i.e. that it internally records the sender's bundle and/or process ID
but delivers that info thru a separate API, not as a flavor in the
clipboard.

Otherwise, let's just focus on the need for AutoGeneratedType and the new
ConcealedType.

Thomas


Peter Maurer

unread,
Jun 13, 2013, 4:43:54 AM6/13/13
to nspast...@googlegroups.com
Thomas wrote:

> The more I think about it, the less I personally see for the need of RestoredType, because at least some of iClip's users want to re-order the history list so that a recently pasted item gets moved to the top of the list, which I've implemented in recent iClip betas now.

Now that's an unexpected turn of events. You guys seemed so determined to go through with this, you even got us to release a Butler update that's mostly pointless now, in preparation for what I thought was an imminent TextExpander update. :D

Oh well. Like I said before, I can live without RestoredType just fine.

> Well, maybe if we make it a standard that any tool should add his signature to any clipboard content it creates, we'd still have a use for it.

Isn't that what AutoGenerated is for? We could just apply my suggestion regarding an optional property list to that -- or to any org.nspasteboard.* pasteboard really.

However, if we're talking about any pasteboard created in any app (including those created with user intent), then I think that's beyond NSPasteboard.org's scope. Just like you said, the OS could easily provide that service, if Apple thought that was worthwhile. (Personally, I kinda don't.)

Peter.

Thomas Tempelmann

unread,
Jun 13, 2013, 6:45:58 AM6/13/13
to nspast...@googlegroups.com
Peter Maurer wrote:

> Thomas wrote:
>> The more I think about it, the less I personally see for the need of
>> RestoredType, because at least some of iClip's users want to re-order the
>> history list so that a recently pasted item gets moved to the top of the
>> list, which I've implemented in recent iClip betas now.
>
> Now that's an unexpected turn of events. You guys seemed so determined to go
> through with this, you even got us to release a Butler update that's mostly
> pointless now, in preparation for what I thought was an imminent TextExpander
> update. :D

Well, iClip still uses RestoredType if the user doesn't have the preference
of keeping recently pasted clips at the top of the list, and with the
addition of including the Cocoa clipboard ID, it can still avoid having to
re-read the clipboard contents.

But I had the impression that there's a lot of dislike about this new type,
so I tried to row a little backwards. I'd rather focus on the ConcealedType,
which I find far more important to become an acceptable standard.

Thomas


Günther "gue" Blaschek

unread,
Jun 13, 2013, 7:43:20 AM6/13/13
to nspast...@googlegroups.com
Hi guys,

Sorry, this is getting long.
I have now passively followed the recent contributions for a while and have learned quite a lot.

In particular, my initial concern about "inflation" seems to be justified. Adding new flavors not only provides information, but also changes the meaning of a pasteboard's contents. A restored pasteboard then is no longer the same as the initial pasteboard. There is always a certain risk that such an addition breaks existing code.

We (=Ergonis) just want to insert a piece of text or a picture at the insertion point in the currently active application. In many cases, we can use other techniques that perform the insertion directly, but this does not always work. In those other cases, we have to use the pasteboard. For the user, this should be as transparent as possible, so we save and restore the pasteboard. Afterwards, the result of any previous (explicit) Copy operation should still be in effect. In an ideal world, nobody should ever notice that we temporarily (mis)used the pasteboard.

As far as I have seen now, clipboard historians are the only exception, as they record EVERY change to the pasteboard and therefore make even those temporary changes visible to the user. To avoid pollution of pasteboard histories, all we need is a mechanism to mark all those intermediate pasteboard changes such that they are ignored by historians -- as if they never had occurred in the first place. We don't even need to distinguish between "temporary use" and "restore". Any of the already existing flavors (including the newly suggested "TransientType") will serve this purpose. Mission accomplished.

For maintaining compatibility with other tools, we add all known flavors to the pasteboard as well. In order not to add duplicates, we remove other markers when we save the pasteboard. Of course, we remove only known markers. But it is essential to know which markers are important and what they mean. For every new marker that anyone introduces from now on, we would need to know whether we should simply save and restore it or whether it has special meaning. For example, when utility X adds a marker that says "restored by X", should we remove that and add "restored by Typinator" instead? This is why I am so concerned about every new addition.

About marking restored content: At first sight, it sounds reasonable to include a marker that says "same as Y", but I don't think that this is really necessary. Every decent clipboard history tool should detect duplicates, anyway. For example, I often copy/paste identical words or phrases. For example, I copy a variable name X from here to there, then another variable Y, then X again, and so on. X and Y get copied multiple times, but I would certainly not expect them to occur in the history multiple times. I would expect that a smart history tool finds the older item with the same contents and moves that to the end of the history.

When pasteboard content is marked as "auxiliary" (I'm using this term instead of the controversial terms "transient" and "auto-generated"), I believe that no history tool should capture that. It should also not reorder the history items because such an item already existed previously. In my opinion, such an "auxiliary marker" should tell any other tool to simply ignore the pasteboard change, as if it never had happened. This was the intended meaning of our "Pasteboard generator type" flavor.

There was also discussion about when to use "auto-generated". I think that this is the wrong question. When I trigger a script that copies something to the clipboard, the result would be "auto-generated". When I do the same with command-C, it would not be "auto-generated". But this is not the point. IMHO, the only thing that counts is the user's expectation: Will this action cause a change to the clipboard? Ideally, the user should be able to answer the question "What will I get when I type command-V?" at any time. It does not matter much if the clipboard was filled manually with a Copy command, by running a "copy this file to the clipboard" script, by a macro or service that puts a summary on the clipboard, or by restoring a previous version from the clipboard history. If this action was explicit and deliberate, the user will expect the change, no matter if the clipboard was "restored" or "auto-generated". And in my opinion, clipboard historians should also record such changes. In a strict sense, restoring a previous copy of the clipboard is no exception: When clipboard historian A restores a historic clipboard, it will be smart enough and move this item to the end of the history. When another historian B watches, it will recognize an already known clipboard content and handle that accordingly. From the perspective of B, the recall via A is the same as an explicit Paste by the user.

The previous discussion also raised the question which party should determine the meaning. Brian suggested to add markers just for information and leave it up to the consumer to give meaning to these markers. I don't agree with that. Typinator doesn't just say "Hi, it's me" or "Nice weather today". It announces that a certain pasteboard operation was "auxiliary" during an internal operation, because we currently have no other way except via the pasteboard. This is sort of an apology: "Sorry, we had to temporarily modify the pasteboard. Please ignore these changes and do not bother reading the contents.". We add the markers because we want to tell a knowing consumers how to handle that. This is not just information; we expect a certain reaction.

Ideally, we would love to use a private pasteboard, put our items on it and tell only the target application about it. In this way, we could use a 1:1 communication channel and avoid the "broadcast" that every other application sees. But unfortunately, there is currently no way to do this. Should we make a proposal to Apple to include such a feature? However, I currently do not see any way how this could be introduced such that it also works with older target applications.

To summarize:
  • I suggest that we drop "org.nspasteboard.AutoGeneratedType".
  • I propose to add "org.nspasteboard.TransientType" and define the meaning as "auxiliary clipboard change; was not meant to be publicly visible; ignore if possible". Specifically, this is a message from a producer to a consumer that this clipboard content should not be recorded in a history. IMHO, "org.nspasteboard.AuxiliaryType" would be a better name, but I think this is too late now.
I think that this would be sufficient.

Opinions?

PS: "ConcealedType" is a different topic. I'll comment on that separately.

All the best,
gue

Brian Bucknam

unread,
Jun 13, 2013, 1:53:54 PM6/13/13
to nspast...@googlegroups.com
On Thursday, June 13, 2013 4:43:20 AM UTC-7, Günther "gue" Blaschek wrote:
In particular, my initial concern about "inflation" seems to be justified. Adding new flavors not only provides information, but also changes the meaning of a pasteboard's contents. A restored pasteboard then is no longer the same as the initial pasteboard. There is always a certain risk that such an addition breaks existing code.

That is why we are having this discussion about the proposed "RestoredType".
 
As far as I have seen now, clipboard historians are the only exception, as they record EVERY change to the pasteboard and therefore make even those temporary changes visible to the user. To avoid pollution of pasteboard histories, all we need is a mechanism to mark all those intermediate pasteboard changes such that they are ignored by historians -- as if they never had occurred in the first place. We don't even need to distinguish between "temporary use" and "restore". Any of the already existing flavors (including the newly suggested "TransientType") will serve this purpose. Mission accomplished.

Actually, due to API limitations clipboard history utilities have to set up a timer and poll the pasteboard at intervals. An efficient implementation tests the pasteboard changeCount against the previous value to avoid extra work.
Depending on the polling interval, a Typinator or TextExpander expansion might entirely escape detection by the clipboard history utility, but of course the pasteboard changeCount will have changed. Thus the motivation for  "RestoredType": by checking for its presence, once again extra work (and risk of trying to read not-yet-completely-restored data) can be avoided.


For maintaining compatibility with other tools, we add all known flavors to the pasteboard as well. In order not to add duplicates, we remove other markers when we save the pasteboard. Of course, we remove only known markers. But it is essential to know which markers are important and what they mean. For every new marker that anyone introduces from now on, we would need to know whether we should simply save and restore it or whether it has special meaning. For example, when utility X adds a marker that says "restored by X", should we remove that and add "restored by Typinator" instead? This is why I am so concerned about every new addition.

I don't think the  "RestoredType" marker needs any "restored by" information. I do think that "AutoGeneratedType", much like "Pasteboard generator type", probably should provide some kind of "signature".

 
About marking restored content: At first sight, it sounds reasonable to include a marker that says "same as Y", but I don't think that this is really necessary. Every decent clipboard history tool should detect duplicates, anyway. For example, I often copy/paste identical words or phrases. For example, I copy a variable name X from here to there, then another variable Y, then X again, and so on. X and Y get copied multiple times, but I would certainly not expect them to occur in the history multiple times. I would expect that a smart history tool finds the older item with the same contents and moves that to the end of the history.

 The point of "RestoredType" was to allow quicker and safer detection of duplicates. What the clipboard history utility displays is up to its developer.

There was also discussion about when to use "auto-generated". I think that this is the wrong question. When I trigger a script that copies something to the clipboard, the result would be "auto-generated". When I do the same with command-C, it would not be "auto-generated". But this is not the point. IMHO, the only thing that counts is the user's expectation: Will this action cause a change to the clipboard? Ideally, the user should be able to answer the question "What will I get when I type command-V?" at any time. It does not matter much if the clipboard was filled manually with a Copy command, by running a "copy this file to the clipboard" script, by a macro or service that puts a summary on the clipboard, or by restoring a previous version from the clipboard history. If this action was explicit and deliberate, the user will expect the change, no matter if the clipboard was "restored" or "auto-generated".

I agree, and I think Peter Lewis is essentially saying the same thing.  AutoGeneratedType should be applied when the user does _not_ expect to get that content when pressing Command-V. It can be difficult for mere software to discern what the user is thinking or expecting, but it must do its best.
 

The previous discussion also raised the question which party should determine the meaning. Brian suggested to add markers just for information and leave it up to the consumer to give meaning to these markers. I don't agree with that. Typinator doesn't just say "Hi, it's me" or "Nice weather today". It announces that a certain pasteboard operation was "auxiliary" during an internal operation, because we currently have no other way except via the pasteboard. This is sort of an apology: "Sorry, we had to temporarily modify the pasteboard. Please ignore these changes and do not bother reading the contents.". We add the markers because we want to tell a knowing consumers how to handle that. This is not just information; we expect a certain reaction.

Your second and third sentences here seem to be serious mis-reading of my statement: "My feeling is that any specifications provided from NSPasteboard.org should specify the meaning of various markers, but cannot specify how any particular software treats clipboard content with the markers."

I completely agree with the rest of the paragraph: the whole point of the existing and proposed NSPasteboard.org markers is to add meaning and user intent to clipboard contents, and SUGGEST how clipboard utilities would most amenably handle such markers.


To summarize:
  • I suggest that we drop "org.nspasteboard.AutoGeneratedType".
Interesting, since it seems to have nearly identical meaning to "Pasteboard generator type" --- do you propose to drop its use as well?
  • I propose to add "org.nspasteboard.TransientType" and define the meaning as "auxiliary clipboard change; was not meant to be publicly visible; ignore if possible". Specifically, this is a message from a producer to a consumer that this clipboard content should not be recorded in a history. IMHO, "org.nspasteboard.AuxiliaryType" would be a better name, but I think this is too late now.
"org.nspasteboard.TransientType" has been on the www.nspasteboard.org site and in use for at least three years.
 
I think that this would be sufficient.

 "RestoredType" is newly proposed, so I guess this is another vote against that.

So it seems we don't have much consensus after all, and yet in other ways we seem to be saying the same things in a different way, so perhaps some kind of agreement can be reached.

Cheers,
Brian

Peter N Lewis

unread,
Jun 13, 2013, 9:54:53 PM6/13/13
to nspast...@googlegroups.com
On 14/06/2013, at 1:53 , Brian Bucknam <br...@smilesoftware.com> wrote:
> So it seems we don't have much consensus after all, and yet in other ways we seem to be saying the same things in a different way, so perhaps some kind of agreement can be reached.

OK, lets get back to basics then.

Here is my requirements for Keyboard Maestro as a clipboard consumer:

* I need to be able to detect and ignore items placed transiently on the clipboard.

* After any complete operation, I need the invariant: the current clipboard and the last non-transient clipboard are the same for all practical purposes.

Now, future versions of Keyboard Maestro will ignore all org.nspasteboard.* attributes in terms of comparisons, but past versions have not done so unless they are marked as kPasteboardFlavorNotSaved which you can't do except from Carbon.

Everything else flows from requiring that invariant to be maintained as far as I'm concerned:

* No clipboard should ever be marked as transient unless either a) it is about to be replaced by another clipboard; or b) it is the same as the previous non-transient clipboard. I don't like (b), but it's acceptable as it doesn't break the invariant - the current clipboard, albeit marked with transient, matches the last non-transient clipboard. It also means the clipboard wont be read, so it has a (pointless IMO) efficiency advantage. It's main advantage would be with the RestoredType discussed below.

* You can define and use org.nspasteboard.AutoGeneratedType any way you like, as long as the above TransientType is used appropriately. I don't have any need of it, and I will try to generate it appropriately, but it wont affect my clipboard history algorithm. As far as Keyboard Maestro's history is concerned, I don't care how something gets on the clipboard, if it's going to stay there long enough that the *user* might press Command-V and paste it, then it goes on the clipboard history.

* You can define and use org.nspasteboard.RestoredType any way you like, as long as the above TransientType is used appropriately. I don't have any need of it, and I will try to generate it appropriately. It will potentially break duplication detection of previous versions unless it has the kPasteboardFlavorNotSaved flag.

* If you use RestoredType when you restore a clipboard immediately after one or more TransientType, and if you can't mark it kPasteboardFlavorNotSaved, then it will break old versions of Keyboard Maestro's duplicate detection.

* If you use RestoredType when you restore some previously saved clipboard (clipping), and you aren't planning to immediately restore the clipboard to its previous state, then you really must not mark it as transient.

So, given all this, I suggest as spec:

org.nspasteboard.TransientType:
* this clipboard is being put on by an application solely for the purposes of pasting some text.
* the user had no intention to Copy this content and may not expect to find it on the pasteboard.
* the clipboard will promptly be restored to the value that was on the clipboard before the (compound) action started.
* There may be a sequence of these TransientType clipboards placed and used before the clipboard is restored.
* Its value should not be recorded in clipboard history.
* the clipboard will soon be restored so that the head of the clipboard history will be restored to the clipboard.
* Ideally, clipboard history applications should not read the value of any data on the clipboard if this attribute exists.
* The restored clipboard, after all other TransientType clipboards, should also be marked as TransientType.
* Ideally this flavour should be marked with the kPasteboardFlavorNotSaved if at all possible.

org.nspasteboard.AutoGeneratedType:
* this clipboard is being put on by an application, indirectly at the direction of the user.
* it may be treated the same or differently by clipboard history applications.
* If desired, the AutoGeneratedType and TransientType can both be used, assuming the clipboard is indeed transient.
* Ideally this flavour should be marked with the kPasteboardFlavorNotSaved if at all possible.

org.nspasteboard. RestoredType:
* this clipboard is being restored from a previous value.
* It is otherwise identical to the clipboard as it was at some previous time.
* It must be marked as a TransientType if and only if it is the clipboard being restored after a sequence of TransientType clipboards.
* Ideally this flavour should be marked with the kPasteboardFlavorNotSaved if at all possible.

It bastardises TransientType a little by using it in the case of the restored clipboard (but only when that restored clipboard is the immediately past non-transient clipboard). It's not how I would design a spec from the start, but it appears to work as a practical way of doing things while retaining the invariant and maximising backwards compatibility.

So scenarios for clipboard producers. Assuming the current clipboard is CURRENT, a past clipboard history entry is PAST, a previously saved clipboard is SAVED, an inserted text is INSERT. Added attributes are shown in brackets after a clipboard value (eg INSERT(TransientType)).

Typical text expansion:
Set clipboard to INSERT(TransientType,AutoGeneratedType), Command-V
Set clipboard to CURRENT(TransientType,RestoredType)

Text expansion without restore (eg Keyboard Maestro).
Set clipboard to INSERT(AutoGeneratedType), Command-V

Insertion from past clipboard history and then restoring the clipboard:
Set clipboard to PAST(TransientType,RestoredType), Command-V
Set clipboard to CURRENT(TransientType,RestoredType)

Insertion from past clipboard history without restoring the clipboard:
Set clipboard to PAST(RestoredType), Command-V

Insertion saved clipping and then restoring the clipboard:
Set clipboard to SAVED(TransientType,RestoredType), Command-V
Set clipboard to CURRENT(TransientType,RestoredType)

Insertion saved clipping without restoring the clipboard:
Set clipboard to SAVED(RestoredType), Command-V

Read File to the System Clipboard:
Set clipboard to VALUE() OR Set clipboard to VALUE(AutoGeneratedType)

Note: past clipboard and saved clipping are the same behaviour, though there may not be a changeCount available for the latter.

This isn't really the specification I'm after, but it seems to be what others want. For my purposes, as long as my invariant can be met I don't mind what other attributes are used or specified. For Keyboard Maestro, the only one that affects anything is the TransientType, and it's important that its behaviour meshes correctly with the invariant.

Anyway, again, this is long, but it's an attempt to get a summary and a spec. If we haven't got some level of consensus by this point, it may be heading towards time to admit defeat.

Peter Maurer

unread,
Jun 14, 2013, 3:47:06 AM6/14/13
to nspast...@googlegroups.com
> So, given all this, I suggest as spec: ...

Wow, thanks for taking the time to spell all of this out! Here's my vote for your suggestion. Speaking from the point of view of an app that has both a snippets-type feature and a pasteboard history, this will work for us.

I have one question, though -- you wrote:

> org.nspasteboard. RestoredType:
> ...
> * It must be marked as a TransientType if and only if it is the clipboard being restored after a sequence of TransientType clipboards.

Why? A restored pasteboard is not transient, so I'd rather not mark it as such.

I understand that in most cases, there's no harm done, as a typical pasteboard history app will just ignore the transient pasteboard(s) first, then ignore the restored pasteboard (because it's also marked as transient), and thus end up with the expected item at the top of its list again. And I understand that ignoring a pasteboard that's marked as transient is faster than doing a duplicate check.

But it just seems so wrong! Judging from your comments below the spec, it looks like you're making a concession to someone by including this bullet, but I must have lost track somewhere along the way: Who asked for this?

Typinator's "Pasteboard generator type" currently behaves like this (albeit with different content for the restored pasteboard, and a more fitting name for that kind of behavior), but I didn't get the impression that Günther insists on keeping it that way. Or did I miss something?

So if we could drop this one bullet from the spec, I'd be an even happier camper. But again, if there's a good reason to leave it in, then I'll accept grudgingly, lest we discuss RestoredType forever.

Peter.

Günther "gue" Blaschek

unread,
Jun 14, 2013, 3:52:19 AM6/14/13
to nspast...@googlegroups.com
Just a few comments on Brian's reply:

On Thursday, June 13, 2013 7:53:54 PM UTC+2, Brian Bucknam wrote:

[snip]

Actually, due to API limitations clipboard history utilities have to set up a timer and poll the pasteboard at intervals. An efficient implementation tests the pasteboard changeCount against the previous value to avoid extra work.
Depending on the polling interval, a Typinator or TextExpander expansion might entirely escape detection by the clipboard history utility, but of course the pasteboard changeCount will have changed. Thus the motivation for  "RestoredType": by checking for its presence, once again extra work (and risk of trying to read not-yet-completely-restored data) can be avoided.

Sorry, but I do not see the rationale for "RestoredType" here. It is true that clipboard changes may escape detection by a history utility, but this can happen only when they are immediately followed by another change (either another expansion within a sequence, or by a restore). What is the purpose of marking the last one (which will then stay on the clipboard for longer) specially?
When a historian misses one of the "transient" intermediate clipboard changes, this does not really hurt, as the producer doesn't want these changes to be recorded, so they will be marked as transient anyway. Marking the intermediate steps makes sense, but the last change will be here to stay, anyway.
Do I miss something here?
 
[snip]

There was also discussion about when to use "auto-generated". I think that this is the wrong question. When I trigger a script that copies something to the clipboard, the result would be "auto-generated". When I do the same with command-C, it would not be "auto-generated". But this is not the point. IMHO, the only thing that counts is the user's expectation: Will this action cause a change to the clipboard? Ideally, the user should be able to answer the question "What will I get when I type command-V?" at any time. It does not matter much if the clipboard was filled manually with a Copy command, by running a "copy this file to the clipboard" script, by a macro or service that puts a summary on the clipboard, or by restoring a previous version from the clipboard history. If this action was explicit and deliberate, the user will expect the change, no matter if the clipboard was "restored" or "auto-generated".

I agree, and I think Peter Lewis is essentially saying the same thing.  AutoGeneratedType should be applied when the user does _not_ expect to get that content when pressing Command-V. It can be difficult for mere software to discern what the user is thinking or expecting, but it must do its best.

I think you misunderstood my point. I am convinced that the user does not care whether the clipboard was "auto-generated" or created by command-C, as long as he knows what to expect on the clipboard. For example, I sometimes run a database query that puts the result on the clipboard. This is clearly "auto-generated", but I definitely expect the result on the clipboard.
But maybe we just have a different understanding of the term. As far as I understand "auto-generated", it means "generated by an automatic process, not by the user". But your explanation indicates that you mean "unexpected by the user". No, I do not suggest to rename it like this. ;-) I rather suggest to ditch this marker altogether.
 
The previous discussion also raised the question which party should determine the meaning. Brian suggested to add markers just for information and leave it up to the consumer to give meaning to these markers. I don't agree with that. Typinator doesn't just say "Hi, it's me" or "Nice weather today". It announces that a certain pasteboard operation was "auxiliary" during an internal operation, because we currently have no other way except via the pasteboard. This is sort of an apology: "Sorry, we had to temporarily modify the pasteboard. Please ignore these changes and do not bother reading the contents.". We add the markers because we want to tell a knowing consumers how to handle that. This is not just information; we expect a certain reaction.

Your second and third sentences here seem to be serious mis-reading of my statement: "My feeling is that any specifications provided from NSPasteboard.org should specify the meaning of various markers, but cannot specify how any particular software treats clipboard content with the markers."

No, I was referring to your contribution of June 12, where you wrote:
How that data is treated is up to the "consumer".
I do NOT want to leave this up to the consumer; I do want to tell the consumer to ignore clipboard changes.

I completely agree with the rest of the paragraph: the whole point of the existing and proposed NSPasteboard.org markers is to add meaning and user intent to clipboard contents, and SUGGEST how clipboard utilities would most amenably handle such markers.

I strongly believe that "suggesting" is not enough. I have been working in a standardization committee before, where we carefully avoided such soft phrases that allow the reader to do what he wishes. In that sense, I would define this as "Clipboard history tools SHALL ignore clipboard contents containing the X marker".
 
To summarize:
  • I suggest that we drop "org.nspasteboard.AutoGeneratedType".
Interesting, since it seems to have nearly identical meaning to "Pasteboard generator type" --- do you propose to drop its use as well?

My posting was only about the newly proposed types. I think we already have agreement that we will continue to support the legacy types (see www.nspasteboard.org: "Add support for existing identifiers (see above) of transient data not already supported by your application."). At least, Typinator will continue to use the old markers in addition to whatever we define here.
  • I propose to add "org.nspasteboard.TransientType" and define the meaning as "auxiliary clipboard change; was not meant to be publicly visible; ignore if possible". Specifically, this is a message from a producer to a consumer that this clipboard content should not be recorded in a history. IMHO, "org.nspasteboard.AuxiliaryType" would be a better name, but I think this is too late now.
"org.nspasteboard.TransientType" has been on the www.nspasteboard.org site and in use for at least three years.

OK, so we will have to live with that.
 
 I think that this would be sufficient.

 "RestoredType" is newly proposed, so I guess this is another vote against that.

Yes.

Cheers,
gue

Peter N Lewis

unread,
Jun 14, 2013, 4:15:41 AM6/14/13
to nspast...@googlegroups.com
On 14/06/2013, at 15:47 , Peter Maurer <pe...@manytricks.com> wrote:
>> org.nspasteboard. RestoredType:
>> ...
>> * It must be marked as a TransientType if and only if it is the clipboard being restored after a sequence of TransientType clipboards.
>
> Why? A restored pasteboard is not transient, so I'd rather not mark it as such.

I agree in principle, and that was where I started, but I've adjusted my thinking now. It requires that by "TransientType" what we mean is "does not need to be recorded in the clipboard history". Thus, the sequence:

Typical text expansion:
Set clipboard to INSERT(TransientType,AutoGeneratedType), Command-V
Set clipboard to CURRENT(TransientType,RestoredType)

Neither clipboard needs to be recorded to the history, because the clipboard history remains unchanged (and the system clipboard is restored) after the process has been completed.

The reason for this is largely to allow the RestoredType without breaking previous application’s clipboard matching code.

As I said, "It bastardises TransientType a little by using it in the case of the restored clipboard (but only when that restored clipboard is the immediately past non-transient clipboard). It's not how I would design a spec from the start, but it appears to work as a practical way of doing things while retaining the invariant and maximising backwards compatibility.".

> But it just seems so wrong! Judging from your comments below the spec, it looks like you're making a concession to someone by including this bullet, but I must have lost track somewhere along the way: Who asked for this?

It's not "wrong", it's just that the word "Transient" is not really the correct word in this altered definition. Think of it as "HistoryIgnored" instead of "Transient".

And, no, it's not a concession - it's a requirement caused by the addition of the RestoredType. But it remains self-consistent, as long as you don't hold too tightly to the english meaning of the word Transient.

And alternative would be this:

Typical text expansion:
Set clipboard to INSERT(TransientType,AutoGeneratedType), Command-V
Set clipboard to CURRENT()

Which is the current state of affairs.

> So if we could drop this one bullet from the spec, I'd be an even happier camper. But again, if there's a good reason to leave it in, then I'll accept grudgingly, lest we discuss RestoredType forever.

I agree with the grudging nature, which is how I've come to this definition. It's not what I would define if I was defining the spec from scratch. But what I might change might just be the naming of the org.nspasteboard.TransientType. I think the behaviour is actually better this way, it's just that it is inconsistent with the english meaning of the word Transient. If you reread my proposed spec with "HistoryIgnoredType" instead of "TransientType", I think the grudging acceptance would be removed.

Enjoy,

Günther "gue" Blaschek

unread,
Jun 14, 2013, 4:45:43 AM6/14/13
to nspast...@googlegroups.com, pe...@manytricks.com
Peter,
Our postings crossed each other. Two brief comments on yours:

I have one question, though -- you wrote:

> org.nspasteboard. RestoredType:
>         ...
>         * It must be marked as a TransientType if and only if it is the clipboard being restored after a sequence of TransientType clipboards.

Why? A restored pasteboard is not transient, so I'd rather not mark it as such.

Well, it's just the wrong term. But - as Brian explained - it's too late to change this now, as org.nspasteboard.TransientType has been in use for three years already.

[snip]

Typinator's "Pasteboard generator type" currently behaves like this (albeit with different content for the restored pasteboard, and a more fitting name for that kind of behavior), but I didn't get the impression that Günther insists on keeping it that way. Or did I miss something?

See my earlier posting: We will continue to use "Pasteboard generator type". We introduced this flavor six years ago, and it is here to stay.
The meaning is simply that clipboard history tools shall ignore clipboards containing this marker. This is essentially the same as TransientType.
The content is a UTF8 string containing the name of the generator application. When we restore a previous clipboard, we append " (restore)", but I'm not sure if other producers adopted this convention in the same way, so historians should not rely on that.
But as I said earlier: We will simply support all types that express our intended meaning, in order to maximize compatibility with history tools.

Cheers,
gue

Peter Maurer

unread,
Jun 14, 2013, 5:59:07 AM6/14/13
to nspast...@googlegroups.com
Two quick replies...


Peter N Lewis wrote:

> The reason for this is largely to allow the RestoredType without breaking previous application’s clipboard matching code.

Oh, I see. So the assumption is that there are apps that do support org.nspasteboard.TransientType, but won't adapt to the new RestoredType in a timely fashion, right? For some reason I had previously led myself to believe that most relevant apps either didn't support any org.nspasteboard types at all, or that they'd adapt quickly enough.

I have no proof for that, though, and even if TransientType-supporting apps do adapt, I guess there might be casualties among users who run an OS version that some of the involved apps have dropped support for, while others haven't.

Protest withdrawn.


Günther Blaschek wrote:

> See my earlier posting: We will continue to use "Pasteboard generator type"...

Right. I wasn't suggesting that you should change what you do with "Pasteboard generator type". I was just trying to say that TransientType/RestoredType's behavior doesn't have to reflect the behavior of proprietary types. "Pasteboard generator type"+"Typinator" could be set along with TransientType, while "Pasteboard generator type"+"Typinator (restore)" could be set along with RestoredType.

Since I've withdrawn my protest, though, it doesn't really matter. And yes, I think we'll keep good old "de.petermaurer.TransientPasteboardType" around for a little longer as well, although I'd sure like to ditch it eventually. Maybe we'll retire it on its 10th birthday in 2015. :)


Peter.
Reply all
Reply to author
Forward
0 new messages