Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have a perl/Tk application that uses Tk::ROText. I want to be able to display text with parts of it pre-selected, so the user can immediately copy it to the clipboard. So I do this:

  $t->insert('end', $mytext, ['mytag', 'sel']);

Without prior user interaction, it doesn't work. It displays the text with 'mytag' but not 'sel'. However, if I first go into some displayed text and select it with the mouse, all subsequent executions of the above code have the desired effect. It's as if the select mechanism needs to be awakened first by manually selecting text. So my question is, "Is there a programmatic way to 'wake up' text selection before invoking it in the program?"

Replies are listed 'Best First'.
Re: Waking up text select
by Chmrr (Vicar) on Oct 09, 2000 at 05:27 UTC
    Looks like you've found (yet another :) bug in the Windows port of Perl/Tk. At least, I'm assuming you're running under Windows, because the following works fine under Linux:
    #!/usr/bin/perl use Tk; use Tk::ROText; my $mw = MainWindow->new(); my $rot = $mw->ROText; $rot->pack; $rot->insert('end','foo '); $rot->insert('end','the bar',['mytag','sel']); $rot->insert('end',' baz'); MainLoop;
    Of course, the same code does nothing under my Win32 box, so I'd assume that is the problem you are referring to. Unfortunatly, I could find no way around it -- normally $mw->idletasks() or $mw->update() fixes problems such as these, but had no effect here. I'll poke a bit more; but failing that, I don't see a simple answer. BTW, this problem is not limited to Tk::ROText -- it appears to be a problem even in Tk::Text. I'm amazed that nobody has noticed this before.
    Of course, if you're running under Linux, then disregard all of the above, and take the above code as a working example. :)
      Thanks much for checking it out. You're right -- I am using Windows and the balance of my code is structurally like yours.
      After posting the problem, it occurred to me that examining Text.pm might offer some clues. After all, if manual text selections are handled in the module-level code via its own 'sel' mechanism, then I should be able to do so in my program too. But I haven't done that yet. It might also be that some lower-level communication with Windows handles the manual selecting; hence the discrepancy with Linux.
RE: Waking up text select
by Anonymous Monk on Oct 09, 2000 at 09:25 UTC
    Postscript from humble supplicant: I examined Text.pm (see Re: re: for Reply #1) and noted that for manual selections it uses (e.g. for 'select all'):
    $t->tagAdd('sel', '1.0', 'end');
    So I tried it. It didn't work. Now how could Text.pm get by with this and not my program?

    To make a long story short, it turns out not to be manual selection that wakes up the select mechanism, but any manual activity (including a single mouse click) in the text area. And when manual activity takes place, the widget has the focus. So I tried forcing the issue with the focus method:

    $t = $mw->ROText(-foo => 'bar' etc.)->pack; $t->focus;
    It worked! I use it once at the beginning of the program, before calling MainLoop. It appears sufficient to activate the selection mechanism for the duration of the program.

      Post-postscript:

      Well not quite! It's actually not sufficient to invoke the focus method only once. The Text or ROText widget must have the focus when the selecting is being done. If there are other widgets capable of acquiring focus, you must return the focus to the text widget using $t->focus; before any operations involving 'sel' are performed.

      Now I'm curious if the code given in the first reply would work, even under Linux, if there were other widgets competing for the focus. Perhaps the only relevant difference between Linux and Windows is that Linux always assigns the focus to something when the program starts, and Windows doesn't.

        Hrm. I did the test you mention, and it still worked under Linux. I added and focused on a new ROText at every opportunity, and it still insisted on working. Here's the code I used:
        #!/usr/local/bin/perl use Tk; use Tk::ROText; my $mw = MainWindow->new(); $a=$mw->ROText(height=>2)->pack; $a->insert('end','foo'); $a->focus; $rot = $mw->ROText(height=>2)->pack; $a=$mw->ROText(height=>2)->pack; $a->insert('end','foo'); $a->focus; $rot->insert('end', 'foo '); $a=$mw->ROText(height=>2)->pack; $a->insert('end','foo'); $a->focus; $rot->insert('end', 'the bar', ['mytag','sel']); $a=$mw->ROText(height=>2)->pack; $a->insert('end','foo'); $a->focus; $rot->insert('end', ' is baz'); $a=$mw->ROText(height=>2)->pack; $a->insert('end','foo'); $a->focus; MainLoop;
        So it looks like Linux doesn't care about where the focus is, when it's selecting text. Having to push the focus around to do selections strikes me as more than a little odd. Apparently Linux has the same opinion.. Anyways, glad you were able to puzzle this one out -- it looks like it's one of the long list of "problems that aren't documented anywhere, but should be!"


        Addendum: It looks like this is tied to Windows' treatment of selections. For instance, the following code leaves all three boxes with selections under Linux, but only the last one selected under Windows:
        #!/usr/local/bin/perl use Tk; use Tk::ROText; my $mw = MainWindow->new(); for (1..3) { $a = $mw->ROText(height=>2)->pack; $a->focus; $a->insert('end','foo',['sel']); $a->focus; } MainLoop;
        ..which means that the Windows port will always be slightly broken -- the ->focus() stuff is just an indication of this. Anyways, hope this helps.