1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
|
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright (C) 2011-2014 Brian P. Hinz
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package com.tigervnc.vncviewer;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.io.*;
import java.nio.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.text.*;
import com.tigervnc.rfb.LogWriter;
import static com.tigervnc.vncviewer.Parameters.*;
class ClipboardDialog extends Dialog {
protected static class MyJTextArea extends JTextArea {
private class VncTransferHandler extends TransferHandler {
// Custom TransferHandler designed to limit the size of outbound
// clipboard transfers to VncViewer.maxCutText.getValue() bytes.
private LogWriter vlog = new LogWriter("VncTransferHandler");
public void exportToClipboard(JComponent c, Clipboard clip, int a)
throws IllegalStateException {
if (!(c instanceof JTextComponent)) return;
String text = ((JTextComponent)c).getText();
try {
if (text.equals((String)clip.getData(DataFlavor.stringFlavor))) return;
} catch (IOException e) {
// worst case we set the clipboard contents unnecessarily
vlog.info(e.toString());
} catch (UnsupportedFlavorException e) {
// worst case we set the clipboard contents unnecessarily
vlog.info(e.toString());
}
StringSelection selection = new StringSelection(text);
clip.setContents(selection, null);
}
public boolean importData(JComponent c, Transferable t) {
if (canImport(c, t.getTransferDataFlavors())) {
try {
DataFlavor VncFlavor = null;
for (DataFlavor f : t.getTransferDataFlavors()) {
if (f.isMimeTypeEqual("text/plain") &&
f.isRepresentationClassInputStream()) {
VncFlavor = f;
break;
}
}
if (VncFlavor == null) return false;
CharBuffer cbuf =
CharBuffer.allocate(maxCutText.getValue());
Reader reader = (Reader)VncFlavor.getReaderForText(t);
int n = reader.read(cbuf.array(), 0, cbuf.length());
reader.close();
// reader returns -1 (EOF) for empty clipboard
cbuf.limit(n < 0 ? 0 : n);
if (c instanceof JTextComponent)
if (!cbuf.toString().equals(((JTextComponent)c).getText()))
((JTextComponent)c).setText(cbuf.toString());
return true;
} catch (OutOfMemoryError e) {
vlog.error("ERROR: Too much data on local clipboard!");
} catch (UnsupportedFlavorException e) {
// Skip import
vlog.info(e.toString());
} catch (IOException e) {
// Skip import
vlog.info(e.toString());
}
}
return false;
}
public boolean canImport(JComponent c, DataFlavor[] flavors) {
for (DataFlavor f : flavors)
if (f.isMimeTypeEqual("text/plain") &&
f.isRepresentationClassReader())
return true;
return false;
}
}
private class MyTextListener implements DocumentListener {
public MyTextListener() { }
public void changedUpdate(DocumentEvent e) { }
public void insertUpdate(DocumentEvent e) {
if (!listen) return;
String text = textArea.getText();
if (sendClipboard.getValue())
VncViewer.cc.writeClientCutText(text, text.length());
}
public void removeUpdate(DocumentEvent e) { }
}
public MyJTextArea() {
super();
setTransferHandler(new VncTransferHandler());
getDocument().addDocumentListener(new MyTextListener());
// If the textArea can receive the focus, then text within the textArea
// can be selected. On platforms that don't support separate selection
// and clipboard buffers, this triggers a replacement of the textAra's
// contents with the selected text.
setFocusable(false);
setLineWrap(false);
setWrapStyleWord(true);
}
}
public ClipboardDialog() {
super(false);
setTitle("VNC Clipboard Viewer");
setPreferredSize(new Dimension(640, 480));
addWindowFocusListener(new WindowFocusListener() {
// Necessary to ensure that updates from the system clipboard
// are propagated to the textArea when the dialog is visible.
public void windowGainedFocus(WindowEvent e) {
clientCutText();
}
public void windowLostFocus(WindowEvent e) { }
});
JScrollPane sp = new JScrollPane(textArea);
getContentPane().add(sp, BorderLayout.CENTER);
// button panel placed below the scrollpane
JPanel pb = new JPanel();
clearButton = new JButton("Clear");
pb.add(clearButton);
sendButton = new JButton("Send to VNC server");
pb.add(sendButton);
cancelButton = new JButton("Cancel");
pb.add(cancelButton);
getContentPane().add("South", pb);
addListeners(this);
pack();
}
public static void showDialog(Container c) {
if (dialog == null)
dialog = new ClipboardDialog();
dialog.show(c);
}
public void show(Container c) {
super.showDialog(c);
}
public void endDialog() {
super.endDialog();
dialog.dispose();
}
public static void serverCutText(String str) {
if (textArea.getText().equals(str))
return;
// Update the text area with incoming serverCutText. We need to diable
// the DocumentListener temporarily to prevent an clientCutText msg from
// being sent back to the server when the textArea is updated.
listen = false;
textArea.setText(str);
textArea.copy();
listen = true;
}
public static void clientCutText() {
// Update the textArea with the current contents of the system clipboard.
// The TransferHandler ensures that the textArea's contents are only
// changed when they differ from the clipboard's. If the textArea is
// updated, the DocumentListener will trigger an RFB clientCutText msg.
textArea.paste();
textArea.setCaretPosition(0);
}
public void setSendingEnabled(boolean b) {
sendButton.setEnabled(b);
}
public void actionPerformed(ActionEvent e) {
Object s = e.getSource();
if (s instanceof JButton && (JButton)s == clearButton) {
serverCutText(new String(""));
} else if (s instanceof JButton && (JButton)s == sendButton) {
String text = textArea.getText();
VncViewer.cc.writeClientCutText(text, text.length());
endDialog();
} else if (s instanceof JButton && (JButton)s == cancelButton) {
endDialog();
}
}
private JButton clearButton, sendButton, cancelButton;
private static boolean listen = true;
static ClipboardDialog dialog;
static MyJTextArea textArea = new MyJTextArea();
static Toolkit tk = Toolkit.getDefaultToolkit();
static LogWriter vlog = new LogWriter("ClipboardDialog");
}
|