On 11/03/2011 10:41 PM, Pavel Porvatov wrote:
Hi Charles,
On 10/27/2011 09:12 PM, Pavel Porvatov wrote:
Hi Charles,
On 10/14/2011 04:06 PM, Pavel Porvatov wrote:
Hi Charles,
On 10/11/2011 05:50 PM, Pavel Porvatov wrote:
Hi Charles,
On 10/08/2011 05:41 PM, Pavel Porvatov wrote:
I got your point. What about this solution:
If in the compose mode, endCompositoin just sendComposedText
instead of sendCommittedText.
The patch is attached
Could you please explain the fix? May be it removes NPE but it
puzzles me. So if buffer.length() == 0 you invoke
sendCommittedText, right? But sendCommittedText commits buffer,
but buffer is empty. Looks strange...
BTW: the code like "if (!notInCompositionMode) {" a little bit
difficult to understand =) I'd preffer to avoid two negations
and use "if (notInCompositionMode)" and swap if/else blocks...
Regards, Pavel
Hi Pavel,
Sorry for the confusion. Here is some explanation, please correct
me if I am wrong:
1. There two modes which is judge from the buffer size: composed
mode when the buffer size is not zero and normal mode when the
buffer size is zero.
Right
2. The original code make no difference whether it is in the
composed mode or normal mode. In the normal mode, which buffer
size is zero, it sends the committed text. In the composed mode,
which buffer size is not zero, it also sends the committed code.
And NPE occurred here.
3. In the patch, I do not change the logic when in the normal
mode. (notInCompositionMode branch) Why? I guess it is the logic
of "Ends any input composition that may currently be going on in
this context. Depending on the platform and possibly user
preferences, this may commit or delete uncommitted text." from
the api spec....
Yes. But after your change the following code looks strange for me:
if (!notInCompositionMode) {
....
} else {
>>>> sendCommittedText();
}
So if we are not in composition mode we send something (empty
string actually). Logically we shouldn't send anything (IMO),
because buffer is empty. Why should we do something at all if
endComposition is invoked and we are not in composition mode?
4. In the patch, the logic in the composed mode is that: if it is
in the composed mode, keep every thing as just composed :-)
I found a new bug (???) in the fix. If you apply the patch, run
the MouseEventTest2 test and follow the instructions from the bug
description NPE will not be thrown, but the JTextArea remains in
composition mode even after endComposition completion.
Right. It seems that we have to do some thing in the jdk :-). Here
it is:
The patch attached is just adding a null check at the beginning of
the mouseClicked method in DefaultCaret. So why the component is
null in the DefaultCaret? That because the caret has already been
deinstalled. It seems to be an order problem of mouse event and the
event which endCompositon sent. The endComposition will exchange
the caret and deinstall the old one. On the other hand, mouse click
event was happening on the old caret. So the component of the old
caret is null now. NPE happens.
It looks that you are trying to fix the consequence, but not the
root of the problem. The endComposition method shouldn't send
anything to deinstalled DefaultCaret. I think the previous version
of the fix was much closer than this one.
Regards, Pavel
Hi Pavel,
The problem is how should we deal with the uncommitted compose
character when endComposition.
1. Remain the character. Not good, will remain in compose mode after
endComposition.
2. Delete the character. I think it just like the cancelComposition.
We have to send some thing to delete the characters which are already
shown on the text area.
Here is a new patch which add a little bit logic in the
endComposition method:
1. It still remain the null check in the mouseClick
2. It use cancelCompostion in the endComposition when in the compose
mode.
Any idea?
I deeply analyzed the problem and found out that I agree with your
last fix *without* changing in the CodePointInputMethod.java class
(you sent such version on 10/19/2011). I answered on that mail "It
looks that you are trying to fix the consequence, but not the root of
the problem. The endComposition method shouldn't send anything to
deinstalled DefaultCaret." Actually we shouldn't send anything to
deinstalled DefaultCaret and I found code that removes listener of
deinstalled DefaultCaret. But at the same time deinstalled
DefaultCaret gets mouseClick notification because AWT makes copy of
all listeners before notifications. Unfortunately we can't change such
functionality and the best and simplest way to fix the problem is to
skip mouseClicked notification for deinstalled carets.
Could you please write an automatic test, please?
BTW: I didn't catch "problem is how should we deal with the
uncommitted compose character when endComposition". Current
implementation works fine, IMO: it commits entered characters and ends
composition.
Regards, Pavel
Hi Pavel,
/>>> "problem is how should we deal with the uncommitted compose
character when endComposition"/
I am talking about what user will when the endComposition calls. To me,
it is more reasonable when the uncommitted character go away if the
composition is not complete :-). That's the reason I am using
cancelComposition. Thanks for pointing out the AWT copy things. Would
you like to point me where it is? It is kind of hard to debug in the
awt/swing code :-P
Below is the patch and simple test case (attached):
--
Yours Charles
diff --git src/share/classes/javax/swing/text/DefaultCaret.java
src/share/classes/javax/swing/text/DefaultCaret.java
index ecbfdf0..48547f2 100644
--- src/share/classes/javax/swing/text/DefaultCaret.java
+++ src/share/classes/javax/swing/text/DefaultCaret.java
@@ -403,6 +403,10 @@ public class DefaultCaret extends Rectangle implements
Caret, FocusListener, Mou
* @see MouseListener#mouseClicked
*/
public void mouseClicked(MouseEvent e) {
+ if (getComponent() == null) {
+ return;
+ }
+
int nclicks = SwingUtilities2.getAdjustedClickCount(getComponent(), e);
if (! e.isConsumed()) {
diff --git test/javax/swing/text/DefaultCaret/6938583/bug6938583.java
test/javax/swing/text/DefaultCaret/6938583/bug6938583.java
new file mode 100644
index 0000000..4325cbb
--- /dev/null
+++ test/javax/swing/text/DefaultCaret/6938583/bug6938583.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Portions Copyright (c) 2011 IBM Corporation
+ */
+
+/*
+ @test
+ @bug 6938583
+ @summary Unexpected NullPointerException when use CodeIM demo on windows
+ @author LittleE
+*/
+
+import java.awt.event.MouseEvent;
+
+import javax.swing.JTextArea;
+import javax.swing.text.DefaultCaret;
+
+public class bug6938583 {
+ public static void main(String[] args) {
+ JTextArea jta = new JTextArea();
+ DefaultCaret dc = new DefaultCaret();
+ jta.setCaret(dc);
+ dc.deinstall(jta);
+ dc.mouseClicked(new MouseEvent(jta, MouseEvent.MOUSE_CLICKED, 0, 0, 0,
0, 0, false));
+ }
+}