Bug 101087

Summary: klipper is flooded with graphic selection (from openoffice)
Product: [Unmaintained] klipper Reporter: Jonas Widarsson <jonas>
Component: generalAssignee: Esben Mose Hansen <kde>
Status: RESOLVED FIXED    
Severity: normal CC: hhellwig, jjstickel, richlv
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Gentoo Packages   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: screenshot of klipper flooded with graphical objects from oodraw
Klipper/image copy test

Description Jonas Widarsson 2005-03-08 10:47:37 UTC
Version:            (using KDE KDE 3.4.0)
Installed from:    Gentoo Packages
Compiler:          gcc version 3.3.2 20031218 (Gentoo Linux 3.3.2-r5, propolice-3.3-7) 
OS:                Linux

First of all, Klipper is totally awesome!
I was surprised to see klipper contain my graphical selections too. That is just sooo great!

However, it is a little immature just yet.
Klipper is flooded with graphical selections from openoffice.

Klipper runs in tray.
I run openoffice draw 1.1.4, installed from binary downloaded from openoffice.org

1) create some graphics in oodraw.
2) clear clipboard history in klipper.
3) select some graphics with rubberband selection in oodraw.
4) show the klipper menu.
The klipper menu has two entries with the same graphical content.

5) Then, I fired up KSnaphot to make a screenshot, and selected a 2 sec delay, and full screen capture. 
6) Show the menu while waiting for the screenshot to happen.
then the menu contains MANY objects seemingly identical, even though I didn't even touch openoffice in between.

Screenshot follows in an attachment.

Thanks for a wonderful, but yet flaky, feature of klipper.

/Jonas
Comment 1 Jonas Widarsson 2005-03-08 10:50:21 UTC
Created attachment 10019 [details]
screenshot of klipper flooded with graphical objects from oodraw
Comment 2 Lee Woodcock 2005-04-28 01:30:00 UTC
Same thing happens with me... I am running OO 1.1.4 and KDE 3.4 (compiled from konstuct on Fedore Core 3). 

This would not be so bad if there was a way to tell klipper not to copy images. Regardless this is a feature that should be added. Give klipper the option to only select text or everything (images included). 

If there is a way to stop this in the setting can someone please post that. 

Thanks
Comment 3 Jonas Widarsson 2005-04-28 06:13:42 UTC
I've also had numerous ooo chrasches when working with graphics. openoffice from gentoo binaries, ooo binaries, version 1.1.3 or 1.1.4 does not matter. All of them crash.

I discovered recently that the crashes only happens when klipper is running. Maybe it has something to do with this bug?

I completely adore the image view feature in klipper... if it worked. The thing is that it appears it is only in ooo the klipper history is flooded. (fired up Kolourpaint to test) Therefore, I am not sure this is a kde bug at all.
Comment 4 Jonas Widarsson 2005-04-28 06:17:10 UTC
I should add that I use KDE 3.4 from CVS now (KDE_3_4_BRANCH)
The current one built a few hours ago.
Comment 5 richlv 2005-05-25 13:28:43 UTC
nope, this is not oo.org problem (unless gimp is broken the same way). i can reproduce the same thing with gimp 2.2.4 (but not with kpdf or kiconedit)

it would be nice to find out why this is happening - if this not klipper problem, it should be reported to oo.org and gimp as fast as possible
Comment 6 Martin Heusel 2005-09-11 18:43:09 UTC
To reproduce this
one opens gnuplot and plots at least two graphics in two windows:

set terminal x11 0
plot sin(x)

klipper fetches repeatedly the graphics

now

set terminal x11 1
plot cos(x)

klipper fetches now this graphics repeatedly

if one closes the last window klipper stops fetching graphics

note that the first graphics window is still open





 
Comment 7 Konrad Twardowski 2005-12-08 08:40:53 UTC
Created attachment 13821 [details]
Klipper/image copy test

Hi
I have the same problem with Java apps. :(
I've attached a simple test program written in Java (tested with KDE 3.5 and
JDK 1.5.0_04/1.6).
To compile and run type "javac Test.java && java Test".
1. Click "Copy Image" to copy image to the clipboard.
2. Debug messages are printed to stderr. Enjoy!
Comment 8 David Liontooth 2006-01-27 04:31:40 UTC
Please give us a way of disabling bitmap copy in klipper! It drives me up the wall that clipper copies (multiple) bitmaps from OpenOffice.org Impress, turning perfectly good text into useless images. This is a debilitating feature that slows my work to a crawl -- it's almost impossible to copy text from one slide to another in Impress.

The problem is in part that klipper is flooded by these bitmaps, but the bitmaps often shouldn't be created at all -- klipper should have a way of turning off image copy and wait until there's text selected, as was the case before. 

Dave
Comment 9 Lubos Lunak 2006-01-30 19:07:33 UTC
*** Bug 109272 has been marked as a duplicate of this bug. ***
Comment 10 Lubos Lunak 2006-01-30 19:21:32 UTC
This problem is basically caused by OOo/gnuplot. Their clipboard implementations lack the required TIMESTAMP target (ICCCM, section 2.6.2 at the end). Which means Klipper cannot determine when the clipboard contents changed the last time. In other words, OOo/gnuplot are broken, not Klipper, complain to them.

I'll see what would be the best way to work around such broken implementations in Klipper.
Comment 11 richlv 2006-01-31 09:43:31 UTC
i was unable to find relevant oo.org issue, so i filed one.
http://qa.openoffice.org/issues/show_bug.cgi?id=61402
Comment 12 Lubos Lunak 2006-01-31 14:12:03 UTC
SVN commit 504109 by lunakl:

XFixes support in Klipper. This
a) avoids the cost of Klipper's polling (not that high actually, but anyway)
b) avoids repeated clipboard transfers from applications with variously broken
clipboard implementations (missing required TIMESTAMP target or whatever)
BUG: 101087



 M  +1 -1      Makefile.am  
 M  +81 -5     clipboardpoll.cpp  
 M  +4 -0      clipboardpoll.h  
 M  +0 -2      toplevel.cpp  


--- branches/KDE/3.5/kdebase/klipper/Makefile.am #504108:504109
@@ -8,7 +8,7 @@
 
 CLEANFILES = dummy.cpp
 
-libklipper_common_la_LIBADD = $(LIB_KDEUI) $(LIB_KSYCOCA) 
+libklipper_common_la_LIBADD = $(LIB_KDEUI) $(LIB_KSYCOCA) $(LIB_XFIXES)
 libklipper_common_la_SOURCES = main.cpp toplevel.cpp urlgrabber.cpp configdialog.cpp \
     toplevel.skel clipboardpoll.cpp history.cpp historyitem.cpp historystringitem.cpp klipperpopup.cpp popupproxy.cpp \
     historyimageitem.cpp
--- branches/KDE/3.5/kdebase/klipper/clipboardpoll.cpp #504108:504109
@@ -18,6 +18,8 @@
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
 */
+#include "config.h"
+
 #include "clipboardpoll.h"
 
 #include <kapplication.h>
@@ -26,8 +28,14 @@
 #include <X11/Xatom.h>
 #include <time.h>
 
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
 #include "toplevel.h"
 
+//#define NOISY_KLIPPER_
+
 /*
 
  The polling magic:
@@ -44,6 +52,9 @@
  the same, it's assumed the contents haven't changed. Note that some applications (like XEmacs) does
  not provide this information, so Klipper has to assume that the clipboard might have changed in this
  case --- this is what is meant by REFUSED below.
+ 
+ Update: Now there's also support for XFixes, so in case XFixes support is detected, only XFixes is
+ used for detecting changes, everything else is ignored, even Qt's clipboard signals.
 
 */
 
@@ -51,11 +62,9 @@
 
 ClipboardPoll::ClipboardPoll( QWidget* parent )
     :   QWidget( parent )
+    , xfixes_event_base( -1 )
 {
     hide();
-    kapp->installX11EventFilter( this );
-    connect( &timer, SIGNAL( timeout()), SLOT( timeout()));
-    timer.start( 1000, false );
     const char* names[ 6 ]
         = { "_QT_SELECTION_SENTINEL",
             "_QT_CLIPBOARD_SENTINEL",
@@ -71,6 +80,41 @@
     xa_timestamp = atoms[ 3 ];
     selection.timestamp_atom = atoms[ 4 ];
     clipboard.timestamp_atom = atoms[ 5 ];
+    bool use_polling = true;
+    kapp->installX11EventFilter( this );
+#ifdef HAVE_XFIXES
+    int dummy;
+    if( XFixesQueryExtension( qt_xdisplay(), &xfixes_event_base, &dummy ))
+    {
+        XFixesSelectSelectionInput( qt_xdisplay(), qt_xrootwin( 0 ), XA_PRIMARY,
+            XFixesSetSelectionOwnerNotifyMask |
+            XFixesSelectionWindowDestroyNotifyMask |
+            XFixesSelectionClientCloseNotifyMask );
+        XFixesSelectSelectionInput( qt_xdisplay(), qt_xrootwin( 0 ), xa_clipboard,
+            XFixesSetSelectionOwnerNotifyMask |
+            XFixesSelectionWindowDestroyNotifyMask |
+            XFixesSelectionClientCloseNotifyMask );
+        use_polling = false;
+#ifdef NOISY_KLIPPER_
+            kdDebug() << "Using XFIXES" << endl;
+#endif
+    }
+#endif
+    if( use_polling )
+        {
+#ifdef NOISY_KLIPPER_
+        kdDebug() << "Using polling" << endl;
+#endif
+        initPolling();
+        }
+}
+    
+void ClipboardPoll::initPolling()
+{
+    connect( kapp->clipboard(), SIGNAL( selectionChanged() ), SLOT(qtSelectionChanged()));
+    connect( kapp->clipboard(), SIGNAL( dataChanged() ), SLOT( qtClipboardChanged() ));
+    connect( &timer, SIGNAL( timeout()), SLOT( timeout()));
+    timer.start( 1000, false );
     selection.atom = XA_PRIMARY;
     clipboard.atom = xa_clipboard;
     selection.last_change = clipboard.last_change = qt_x_time; // don't trigger right after startup
@@ -79,7 +123,7 @@
     kdDebug() << "(1) Setting last_owner for =" << "selection" << ":" << selection.last_owner << endl;
 #endif
     clipboard.last_owner = XGetSelectionOwner( qt_xdisplay(), xa_clipboard );
-#ifdef NOISY_KLIPPER
+#ifdef NOISY_KLIPPER_
     kdDebug() << "(2) Setting last_owner for =" << "clipboard" << ":" << clipboard.last_owner << endl;
 #endif
     selection.waiting_for_timestamp = false;
@@ -88,9 +132,41 @@
     updateQtOwnership( clipboard );
 }
 
+void ClipboardPoll::qtSelectionChanged()
+{
+    emit clipboardChanged( true );
+}
+
+void ClipboardPoll::qtClipboardChanged()
+{
+    emit clipboardChanged( false );
+}
+
 bool ClipboardPoll::x11Event( XEvent* e )
 {
 // note that this is also installed as app-wide filter
+#ifdef HAVE_XFIXES
+    if( xfixes_event_base != -1 && e->type == xfixes_event_base + XFixesSelectionNotify )
+    {
+        XFixesSelectionNotifyEvent* ev = reinterpret_cast< XFixesSelectionNotifyEvent* >( e );
+        if( ev->selection == XA_PRIMARY && !kapp->clipboard()->ownsSelection())
+        {
+#ifdef NOISY_KLIPPER_
+            kdDebug() << "SELECTION CHANGED (XFIXES)" << endl;
+#endif
+            qt_x_time = ev->timestamp;
+            emit clipboardChanged( true );
+        }
+        else if( ev->selection == xa_clipboard && !kapp->clipboard()->ownsClipboard())
+        {
+#ifdef NOISY_KLIPPER_
+            kdDebug() << "CLIPBOARD CHANGED (XFIXES)" << endl;
+#endif
+            qt_x_time = ev->timestamp;
+            emit clipboardChanged( false );
+        }
+    }
+#endif
     if( e->type == SelectionNotify && e->xselection.requestor == winId())
     {
         if( changedTimestamp( selection, *e ) ) {
@@ -248,7 +324,7 @@
 #endif
     if( timestamp != data.last_change || timestamp == CurrentTime )
     {
-#ifdef NOISY_KLIPPER
+#ifdef NOISY_KLIPPER_
         kdDebug() << "TIMESTAMP CHANGE:" << ( data.atom == XA_PRIMARY ) << endl;
 #endif
         data.last_change = timestamp;
--- branches/KDE/3.5/kdebase/klipper/clipboardpoll.h #504108:504109
@@ -37,6 +37,8 @@
         virtual bool x11Event( XEvent* );
     private slots:
         void timeout();
+        void qtSelectionChanged();
+        void qtClipboardChanged();
     private:
         struct SelectionData
         {
@@ -52,11 +54,13 @@
         void updateQtOwnership( SelectionData& data );
         bool checkTimestamp( SelectionData& data );
         bool changedTimestamp( SelectionData& data, const XEvent& e );
+        void initPolling();
         QTimer timer;
         SelectionData selection;
         SelectionData clipboard;
         Atom xa_clipboard;
         Atom xa_timestamp;
+        int xfixes_event_base;
     };
     
 #endif
--- branches/KDE/3.5/kdebase/klipper/toplevel.cpp #504108:504109
@@ -194,8 +194,6 @@
     poll = new ClipboardPoll( this );
     connect( poll, SIGNAL( clipboardChanged( bool ) ),
              this, SLOT( newClipData( bool ) ) );
-    connect( clip, SIGNAL( selectionChanged() ), SLOT(slotSelectionChanged()));
-    connect( clip, SIGNAL( dataChanged() ), SLOT( slotClipboardChanged() ));
 
     m_pixmap = KSystemTray::loadIcon( "klipper" );
     adjustSize();
Comment 13 David Liontooth 2006-01-31 18:31:38 UTC
I encourage people to vote for OOo's companion bug http://qa.openoffice.org/issues/show_bug.cgi?id=61402
since this is the real source of the problem.
Comment 14 René Matthäi 2006-02-14 13:36:25 UTC
Yes, they are the real source - but I would love and think others would do as well to have the option to keep only text in the clipboard, i. e. preventing any app to send images or other to klipper.

This would make life with klipper as easy as it used to be before content like images was processed.

For there will be even more apps to come with such problems like the above (OOo, gnuplot, ...). So pleas let's stop all bad programmers resp. apps to interfere in an unrequested way with klipper.

Once and for all with an option like I and others mentioned. What about that?
Comment 15 Lubos Lunak 2006-02-14 14:51:45 UTC
See bug #109032 .