[Googie] - 5 Nov 2009 - [Eclipse] (an [IDE]) has problems with copying contents to clipboard, especially under [Linux] with [KDE] and Klipper application running. The Klipper is [clipboard] helper application which enables our clipboard to remember more than 1 copied value and lets us to choose which value we want to paste for specific moment. It persists in [system tray] and shows a [menu] when clicked - the menu contains copied positions so we can choose which one we're interested in right now. Problem is that [Eclipse] doesn't like Klipper, or vice versa, I don't know. What I know is that quitting Klipper gets [Eclipse] copy&paste to work again. The price is lost multi-value clipboard. I was getting problem with copy&paste for almost 100% cases, which motivated me to write a little workaround. I just wrote my own Klipper substitute, which I call TkClipper. It's written in "just get it done" way, so you have to pick your own icon for systray (I used tkclipper.png and its name is hardcoded in code below). Also libtray extension is the one you have to get by yourself - for now. I got it from [aMSN]. Source code quality is bad, but I don't care. Not for this small utility. If I have some more free time and willingness, I'll provide some starkits. So here's the source code: #!/usr/bin/env tclsh package require Tk wm withdraw . package require img::png package require libtray set img [image create photo -file [file dirname [info script]]/tkclipper.png] proc dummyProc {args} return newti .t -pixmap $img -command "dummyProc" bind .t [list buttonClicked left %X %Y] bind .t [list buttonClicked right %X %Y] menu .menu -borderwidth 1 -activeborderwidth 1 # Adding to GUI "hints" set ::HINT_FONT TkDefaultFont set ::HINT_BG #FFFFDD set ::HINT_FG #000000 proc helpHint {w} { bind $w "+after 100 \"hint_aux %W\"" bind $w "+after cancel \"hint_aux %W\" catch {destroy .hint_help}" bind $w "+after cancel \"hint_aux %W\" catch {destroy .hint_help}" } proc hint_aux {w} { set t .hint_help catch {destroy $t} toplevel $t -background black wm overrideredirect $t 1 set labelWidget [ttk::label $t.l -font $::HINT_FONT -borderwidth 0 -background $::HINT_BG -foreground $::HINT_FG -justify left] set font [$t.l cget -font] set msg [getShortText] if {$msg != ""} { set label " Current TkClipper contents: \n $msg " set w1 [font measure $font " Current TkClipper contents: "] set w2 [font measure $font " $msg "] set x1 [expr {[winfo pointerx $w]-${w1}-5}] set x2 [expr {[winfo pointerx $w]-${w2}-5}] set x [expr {min($x1, $x2)}] } else { set label " No TkClipper contents " set width [font measure $font $label] set x [expr {[winfo pointerx $w]-${width}-5}] } $labelWidget configure -text $label pack $labelWidget -fill both -padx 1 -pady 1 -ipadx 0 -ipady 1 set height [font metrics $font -ascent] if {$msg != ""} { set heightRatio 2 } else { set heightRatio 1 } set y [expr {[winfo pointery $w]-${height}*${heightRatio}-10}] wm geometry $t +$x\+$y bind $t {after cancel {catch {destroy .hint_help}}} bind $t "catch {destroy .hint_help}" bind $t "catch {destroy .hint_help}" } #------------------------------------------------ set ::delay 100 set ::buffer [list] set ::ptr -1 set ::bufferLimit 20 proc getShortText {{idx ""}} { if {$idx != ""} { set val [lindex $::buffer $idx] } else { set val [lindex $::buffer $::ptr] } if {[string length $val] > 100} { set val "[string range $val 0 96]..." } set val [string trim [string map [list \n " "] $val]] return $val } proc getFullText {{idx ""}} { if {$idx != ""} { return [lindex $::buffer $idx] } else { return [lindex $::buffer $::ptr] } } proc buttonClicked {button x y} { if {$button == "right"} { .menu delete 0 end .menu add command -label "Exit" -command exit } else { if {$::ptr < 0} return .menu delete 0 end for {set i 0} {$i < [llength $::buffer]} {incr i} { .menu add radiobutton -label [getShortText $i] -value $i -variable ::ptr -command updateClipboard } .menu add separator .menu add command -label "Erase clipboard" -command eraseClipboard } update set width [winfo reqwidth .menu] set height [winfo reqheight .menu] .menu post [expr {$x - $width}] [expr {$y - $height}] } proc eraseClipboard {} { set ::ptr -1 set ::buffer [list] } proc updateClipboard {} { if {$::ptr < 0} return clipboard clear clipboard append [getFullText] } proc checkClipboard {} { if {![catch {clipboard get -type STRING} val]} { if {$val ni $::buffer} { set ::buffer [linsert $::buffer 0 $val] set ::ptr 0 if {[llength $::buffer] > $::bufferLimit} { set ::buffer [lrange $::buffer 0 [expr {$::bufferLimit - 1}]] } } else { set ::ptr [lsearch $::buffer $val] } } after $::delay "checkClipboard" } helpHint .t checkClipboard ---- !!!!!! %| [Category Application] | [Category Desktop] | [Category GUI] |% !!!!!!