Pasting into Second Life Linux client - a workaround
|
Zi Ree
Mrrrew!
Join date: 25 Feb 2006
Posts: 723
|
03-08-2006 13:56
Hi Linux group! I hacked a perl script that sends x-events to the Second Life client, so I can write my LSL scripts in my favorite editor and paste them into SL. It's still very ugly, but at least it's a start. Copy is not possible this way, but maybe someone finds this script useful. German and english/US keymap support is already implemented. Other layouts can be added. You will need xse to use the script. Get it from ftp://ftp.uni-magdeburg.de/pub/mirror/hpux.ask.uni-karlsruhe.de/X11/Misc/xse-2.1Have fun! #!/usr/bin/perl -w
# text2xev.pl V0.1 (C)2006 Zi Ree@Second Life # converter for pasting text into Second Life client window. # use, copy, modify and spread freely, I hope it wonj't be needed too much longer :) # have fun! # -- Zi!
# you need xse installed somewhere # get it from ftp://ftp.uni-magdeburg.de/pub/mirror/hpux.ask.uni-karlsruhe.de/X11/Misc/xse-2.1
use strict;
# Your Second Life window id (try xwininfo to get it) my($id)="0x2a0000e";
# path to the xse binary my($xse)="xse-2.1/xse";
my($line);
# read from stdin while($line=<>) { my($char); $line =~ s/^ +//; # skip blanks in the front, makes LSL editor behave better
# split line into individual characters my(@chars)=split //,$line; my($oldsym)="";
# go through characters foreach $char (@chars) { # convert key to xevent syntax, depending on keyboard layout my($output,$sym)=char2xev($char);
# pause for a moment if the same key is pressed twice (events get lost otherwise) if($sym eq $oldsym) { select(undef,undef,undef,0.25); }
# send events via xse to the Second Life client open(XSE,"| $xse -window $id -file /dev/stdin"); print XSE $output; close(XSE);
# remember sent key $oldsym=$sym; } # foreach } # while
# ------------------------
sub char2xev { my($char)=shift; if($char eq "\n") { $char="LF"; }
# modifier key / states my(%modifiers)=( "-" => "", "s" => "Shift", "l" => "Lock", "c" => "Ctrl", "a" => "Mod1", # untested "g" => "Mod5" # ALT-GR for german keyboard );
# select one of the following mappings by calling it "%conv" # more mappings can be added later
# german keyboard mapping (currently active) my(%conv)=( "^" => ["-","dead_circumflex"], "ß" => ["-","ssharp"], "´" => ["-","dead_acute"], "°" => ["s","dead_circumflex"], "!" => ["s","1"], "\"" => ["s","2"], "§" => ["s","3"], "\$" => ["s","4"], "%" => ["s","5"], "&" => ["s","6"], "/" => ["s","7"], "(" => ["s","8"], ")" => ["s","9"], "=" => ["s","0"], "?" => ["s","ssharp"], "`" => ["s","dead_acute"], "¬" => ["g","dead_circumflex"], "¹" => ["g","1"], "²" => ["g","2"], "³" => ["g","3"], "¼" => ["g","4"], "½" => ["g","5"], "¬" => ["g","6"], "{" => ["g","7"], "[" => ["g","8"], "]" => ["g","9"], "}" => ["g","0"], "\\" => ["g","ssharp"], "ü" => ["-","udiaeresis"], "+" => ["-","plus"], "\t" => ["-","Tab"], "Q" => ["s","q"], "W" => ["s","w"], "E" => ["s","e"], "R" => ["s","r"], "T" => ["s","t"], "Z" => ["s","z"], "U" => ["s","u"], "I" => ["s","i"], "O" => ["s","o"], "P" => ["s","p"], "Ü" => ["s","udiaeresis"], "*" => ["s","plus"], "@" => ["g","q"], "~" => ["g","plus"], "ö" => ["-","odiaeresis"], "ä" => ["-","adiaeresis"], "#" => ["-","numbersign"], "A" => ["s","a"], "S" => ["s","s"], "D" => ["s","d"], "F" => ["s","f"], "G" => ["s","g"], "H" => ["s","h"], "J" => ["s","j"], "K" => ["s","k"], "L" => ["s","l"], "Ö" => ["s","odiaeresis"], "Ä" => ["s","adiaeresis"], "'" => ["s","numbersign"], "<" => ["-","less"], "," => ["-","comma"], "." => ["-","period"], "-" => ["-","minus"], ">" => ["s","less"], "Y" => ["s","y"], "X" => ["s","x"], "C" => ["s","c"], "V" => ["s","v"], "B" => ["s","b"], "N" => ["s","n"], "M" => ["s","m"], ";" => ["s","comma"], ":" => ["s","period"], "_" => ["s","minus"], "|" => ["g","less"], "µ" => ["g","m"], "·" => ["g","period"], " " => ["-","space"], "LF" => ["-","Return"], );
# english (EN or US) keyboard mapping (partly untested) my(%conv_us)=( "`" => ["-","grave"], "-" => ["-","minus"], "=" => ["-","equal"], "~" => ["s","grave"], "!" => ["s","1"], "@" => ["s","2"], "#" => ["s","3"], "\$" => ["s","4"], "%" => ["s","5"], "^" => ["s","6"], "&" => ["s","7"], "*" => ["s","8"], "(" => ["s","9"], ")" => ["s","0"], "_" => ["s","minus"], "+" => ["s","equal"], "\t" => ["-","Tab"], "[" => ["-","braceleft"], "]" => ["-","braceright"], "Q" => ["s","q"], "W" => ["s","w"], "E" => ["s","e"], "R" => ["s","r"], "T" => ["s","t"], "Y" => ["s","y"], "U" => ["s","u"], "I" => ["s","i"], "O" => ["s","o"], "P" => ["s","p"], "{" => ["s","braceleft"], "}" => ["s","braceright"], ";" => ["-","semicolon"], "'" => ["-","apostrophe"], "\\" => ["-","backslash"], "A" => ["s","a"], "S" => ["s","s"], "D" => ["s","d"], "F" => ["s","f"], "G" => ["s","g"], "H" => ["s","h"], "J" => ["s","j"], "K" => ["s","k"], "L" => ["s","l"], ":" => ["s","semicolon"], "\"" => ["s","apostrophe"], "|" => ["s","backslash"], "," => ["-","comma"], "." => ["-","period"], "/" => ["-","slash"], "Z" => ["s","z"], "X" => ["s","x"], "C" => ["s","c"], "V" => ["s","v"], "B" => ["s","b"], "N" => ["s","n"], "M" => ["s","m"], "<" => ["s","comma"], ">" => ["s","period"], "?" => ["s","slash"], " " => ["-","space"], "LF" => ["-","Return"], ); # if key is on convert list if(defined($conv{$char})) { my($out)="";
# get event definition my($def)=$conv{$char};
# build xse string $out=$modifiers{@$def[0]}."<Key>".@$def[1]."\n".$modifiers{@$def[0]}."<KeyUp>".@$def[1]."\n"; return ($out,@$def[1]); } else { # standard letter / digit, just return xse string return ("<Key>$char\n<KeyUp>$char\n",$char); } }
_____________________
Zi! (SuSE Linux 10.2, Kernel 2.6.13-15, AMD64 3200+, 2GB RAM, NVidia GeForce 7800GS 512MB (AGP), KDE 3.5.5, Second Life 1.13.1 (6) alpha soon beta thingie) Blog: http://ziree.wordpress.com/ - QAvimator: http://qavimator.orgSecond Life Linux Users Group IRC Channel: irc.freenode.org #secondlifelug
|
Hello Toonie
Registered User
Join date: 25 Jul 2005
Posts: 212
|
03-08-2006 15:29
It fakes pasting by sending a whole load of synthetic keypress events to the Second Life window? That's hideous and great. XD
|
Sky Roundfield
Registered User
Join date: 10 Feb 2006
Posts: 44
|
03-08-2006 16:38
Wow, that's evil. It's also exactly what I need to enter some scripts. Thanks a bunch!
|
Khamon Fate
fategardens.net
Join date: 21 Nov 2003
Posts: 4,177
|
03-08-2006 18:30
/hearty clap
_____________________
Visit the Fate Gardens Website @ fategardens.net
|
Jarod Godel
Utilitarian
Join date: 6 Nov 2003
Posts: 729
|
03-08-2006 18:42
Sir... Dude... I mean... You need to email Wilder Linden now and get this on the SLHacks Wiki. You will be-- NO! You are the king of SL hacks! Bravo. 
_____________________
"All designers in SL need to be aware of the fact that there are now quite simple methods of complete texture theft in SL that are impossible to stop..." - Cristiano MidnightAd aspera per intelligentem prohibitus.
|
ninjafoo Ng
Just me :)
Join date: 11 Feb 2006
Posts: 713
|
03-08-2006 21:51
Only on Linux - Inspired and evil all at the same time!
_____________________
FooRoo : clothes,bdsm,cages,houses & scripts
QAvimator (Linux, MacOS X & Windows) : http://qavimator.org/
|
Zi Ree
Mrrrew!
Join date: 25 Feb 2006
Posts: 723
|
03-08-2006 23:47
Mew! I'm glad the script helped some of you. I will continue to improve things here as needed, feature requests are welcome. I'm planning on a scripted "Button Box" where you can add / remove buttons and define texts and commands to be sent. This could make the use of /1commands much simpler if you have a lot of them. I also think about an external editor that mimics the LSL editor and sends the keystrokes as typed... but that is still in the future 
_____________________
Zi! (SuSE Linux 10.2, Kernel 2.6.13-15, AMD64 3200+, 2GB RAM, NVidia GeForce 7800GS 512MB (AGP), KDE 3.5.5, Second Life 1.13.1 (6) alpha soon beta thingie) Blog: http://ziree.wordpress.com/ - QAvimator: http://qavimator.orgSecond Life Linux Users Group IRC Channel: irc.freenode.org #secondlifelug
|
Angel Sunset
Linutic
Join date: 7 Apr 2005
Posts: 636
|
03-11-2006 09:08
Hacker King 
_____________________
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Kubuntu Intrepid 8.10, KDE, linux 2.6.27-11, X.Org 11.0, server glx vendor: NVIDIA Corporation, server glx version: 1.5.2, OpenGL vendor: NVIDIA Corporation, OpenGL renderer: GeForce 9800 GTX+/PCI/SSE2, OpenGL version: 3.0.0 NVIDIA 180.29, glu version: 1.3, NVidia GEForce 9800 GTX+ 512 MB, Intel Core 2 Duo, Mem: 3371368k , Swap: 2570360k
|
Zi Ree
Mrrrew!
Join date: 25 Feb 2006
Posts: 723
|
03-11-2006 09:19
Queen! *pouts* 
_____________________
Zi! (SuSE Linux 10.2, Kernel 2.6.13-15, AMD64 3200+, 2GB RAM, NVidia GeForce 7800GS 512MB (AGP), KDE 3.5.5, Second Life 1.13.1 (6) alpha soon beta thingie) Blog: http://ziree.wordpress.com/ - QAvimator: http://qavimator.orgSecond Life Linux Users Group IRC Channel: irc.freenode.org #secondlifelug
|
Angel Sunset
Linutic
Join date: 7 Apr 2005
Posts: 636
|
03-11-2006 13:26
I said King? hehehe
_____________________
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Kubuntu Intrepid 8.10, KDE, linux 2.6.27-11, X.Org 11.0, server glx vendor: NVIDIA Corporation, server glx version: 1.5.2, OpenGL vendor: NVIDIA Corporation, OpenGL renderer: GeForce 9800 GTX+/PCI/SSE2, OpenGL version: 3.0.0 NVIDIA 180.29, glu version: 1.3, NVidia GEForce 9800 GTX+ 512 MB, Intel Core 2 Duo, Mem: 3371368k , Swap: 2570360k
|
Orren Walcott
BraveAlphaClientPioneer
Join date: 27 Oct 2005
Posts: 5
|
04-01-2006 17:05
Ah, many thanks! This helped me write a tiny bash script to keep SL from logging off after 30 minutes:
#!/bin/bash while true; do xse -window 0x2c0000e '<MotionNotify> Normal' sleep 600 done
Basically just an infinite loop that sends a mouse motion event every 10 minutes. Run it in the background and end it with killall; I'm too lazy to put any kind of control on it.
|
Claude Desmoulins
Registered User
Join date: 1 Nov 2005
Posts: 388
|
04-01-2006 21:25
Any idea how to rewrite these for xte? is the -x option in xte equivalent to -window in xse?
|
Rizzermon Sopor
Registered User
Join date: 15 Mar 2006
Posts: 43
|
Works Great!
04-02-2006 19:27
The script works great for regular and IM messages as well. Thanks very much for this cool script. I wish I had it the other night when someone had asked me for a web site that had such a long listing that I told them I was on the linux client and it was too long for me to type.  For the sake of newer linux users trying this script, one needs to modify two lines in the script for it to work. One is the window id (around line 15 of the script) and the other the location of xse on the system (around line 18 of the script). Great script Zi Ree and thanks a lot. Edit: Oh, I notice one needs to select the keyboard layout too. I changed to the us layout. So far it works flawlessly.
|
Jabador Jimador
happy submissive
Join date: 28 Sep 2005
Posts: 15
|
04-03-2006 12:40
Uhm... this might be a silly / stupid question. But how would one use this script?
_____________________
Jabador Jimador Owned and collared by Master Spiritfire Musketeer Any questions or complaints are to be directed to Him
|
Rizzermon Sopor
Registered User
Join date: 15 Mar 2006
Posts: 43
|
04-03-2006 17:27
From: Jabador Jimador Uhm... this might be a silly / stupid question. But how would one use this script? In the current (as of 1_9_0_18 version) linux second life client, there is no way to cut and paste text from say a browser into the client text box Jabador. You would have to type it in manually, which ends up being a real pain for long amounts of text. So that is where this script comes in handy. Just copy and save the script to a file, maybe like sl_paste.pl, open up the script with your favorite text editor and towards the beginning of the script set the variables for the window id of the window running second life (by using xwininfo), and where you have the xse executable stored (like maybe /usr/bin/xse ). There are instructions inside the script towards the end telling you how to switch to the us keyboard if you need that. then do a chmod+x sl_paste.pl to make the script executable. Then run the script as ./sl_paste.pl from the directory where you have stored the file. When you run the script, anything you type into the console window where the script is running will get pasted into second life chat. It works very well. Hope this helps. 
|
Foreign Fish
Registered User
Join date: 4 Feb 2006
Posts: 3
|
08-04-2006 14:35
Very cool script. Will make writing LSL much easier, though still more difficult than it should be (not much more can be done but by Lindens). I made a little change that might be appreciated--to find the Second Life Window interactively. Probably could be done better with a single regexp, but I don't know regexps very well.
my $id = `xwininfo -wm | grep 'Window id'`; $id =~ s/.* 0/0/; $id =~ s/ .*//; chomp $id;
|
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
|
08-05-2006 04:09
I couldn't find a version of xse I could actually compile, but seeing this thread has inspired me to write my own version (which I was getting annoyed enough to do anyway). It should compile with any ANSI Standard C++ compiler (though if you're not using g++ you are crazy) and any version of X11. I haven't tested this incredibly thoroughly yet. Try it out and post here with how it is working for you. One nifty little feature of this program is that--as is--you don't have to go find the handle for the X Window (though it does depend on your keyboard focus and mouse position being independent). You just bring up a terminal window in front of SL, type a command like (WITHOUT HITTING ENTER!): cat myScript.lsl | sltyper Then you put your mouse cursor over SL window (without giving SL keyboard focus) and hit enter to run the command in your shell. Viola! BTW, this program is pretty fast as it doesn't haved to delay between keypresses at all; it just TELLS SL there was a delay. (Wrong! See below.) I didn't remove leading whitespace. You can do that easily enough with a filter like 'sed' (and a shell script is your friend if you don't want to type it every time): cat myScript.lsl | sed -r 's/^[[:space:]]*//' | sltyper Also it only handles printable ASCII characters at the moment. Sorry!  So without further ado, here is the code: (NOTE: Broken. See post below.)#include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h>
#include <iostream> #include <map>
long KEY_EVENT_MASK = KeyPressMask | KeyReleaseMask;
Display* display = 0; KeyCode lShiftKeycode;
Window rootWindow; Window targetWindow; int rootPointerX; int rootPointerY; int pointerX; int pointerY;
void openDisplay(void) { display = XOpenDisplay(0); rootWindow = XDefaultRootWindow(display);
lShiftKeycode = XKeysymToKeycode(display, XK_Shift_L); }
XKeyEvent defaultKeyEvent(void) { XKeyEvent event;
event.window = targetWindow; event.root = rootWindow; event.subwindow = targetWindow; event.time = CurrentTime; event.x = 0; event.y = 0; event.x_root = 0; event.y_root = 0; event.same_screen = False;
return event; }
void findPointerWindow(void) { Window childWindow; unsigned int modifierMask;
childWindow = rootWindow; do { targetWindow = childWindow;
if (!XQueryPointer(display, targetWindow, &rootWindow, &childWindow, &rootPointerX, &rootPointerY, &pointerX, &pointerY, &modifierMask)) { std::cerr << "Couldn't locate pointer window. Exiting." << std::endl; std::exit(-1); } } while (childWindow != None);
if (targetWindow == rootWindow) { std::cerr << "Pointer is in root window. Exiting." << std::endl; std::exit(-1); } }
void closeDisplay(void) { XCloseDisplay(display); display = 0; }
void sendKeyEvent(XKeyEvent* keyEvent) { static long timeDelay_ms = 0;
// It seems we don't actually need a delay, even for repeated characters. // We just need to TELL SL there was a delay! keyEvent->time += (timeDelay_ms += HOLD_TIME__MS);
XSendEvent(display, targetWindow, True, KEY_EVENT_MASK, (XEvent*)keyEvent); }
void sendShiftEvent(bool shiftDown) { XKeyEvent shiftKeyEvent = defaultKeyEvent();
shiftKeyEvent.type = (shiftDown) ? KeyPress : KeyRelease; shiftKeyEvent.window = targetWindow; shiftKeyEvent.state = (shiftDown) ? 0 : ShiftMask; shiftKeyEvent.keycode = lShiftKeycode;
sendKeyEvent(&shiftKeyEvent); }
void sendKeyStroke(KeyCode keyCode, bool shiftDown) { static bool wasShiftDown = false;
if (shiftDown != wasShiftDown) { sendShiftEvent(shiftDown); wasShiftDown = shiftDown; }
XKeyEvent mainKeyEvent = defaultKeyEvent();
mainKeyEvent.state = (shiftDown) ? ShiftMask : 0; mainKeyEvent.keycode = keyCode;
mainKeyEvent.type = KeyPress; sendKeyEvent(&mainKeyEvent);
mainKeyEvent.type = KeyRelease; sendKeyEvent(&mainKeyEvent); }
void sendKeysym(KeySym keysym) { KeyCode keycode = XKeysymToKeycode(display, keysym);
KeySym lowerKeysym; KeySym upperKeysym; XConvertCase(keysym, &lowerKeysym, &upperKeysym);
bool needShift = (keysym != XKeycodeToKeysym(display, keycode, 0)) || (keysym != lowerKeysym);
sendKeyStroke(keycode, needShift); }
void sendChar(char ch) { KeySym keysym;
if (!isascii(ch)) { return; }
switch (ch) { case '\n': keysym = XK_Return; break;
case '\r': return;
case '\t': keysym = XK_space; break;
case '\v': return;
default: if (!isprint(ch)) { return; } keysym = ch; break; }
sendKeysym(keysym); }
int main(int argc, char** argv) { openDisplay(); findPointerWindow();
char ch; while (std::cin.get(ch)) { sendChar(ch); }
closeDisplay();
return 0; }
Don't forget to place your mouse cursor over SL! Otherwise it will silently do nothing (at least, most terminals are set to ignore events sent bye 'XSendEvent()' for security, so PROBABLY nothing will happen...).
|
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
|
08-05-2006 04:42
Erg! I tested all characters, but not large scripts. A delay WAS necessary after all. I guess X events were stacking up too much. Here's the new version: #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h>
#include <time.h>
#include <iostream> #include <map>
long HOLD_TIME__MS = 5;
long KEY_EVENT_MASK = KeyPressMask | KeyReleaseMask;
Display* display = 0; KeyCode lShiftKeycode;
Window rootWindow; Window targetWindow; int rootPointerX; int rootPointerY; int pointerX; int pointerY;
void msleep(int time_ms) { struct timespec sleepTime = {time_ms / 1000, (long)(time_ms % 1000) * 1000000}; while (nanosleep(&sleepTime, &sleepTime) < 0) {} }
void openDisplay(void) { display = XOpenDisplay(0); rootWindow = XDefaultRootWindow(display);
lShiftKeycode = XKeysymToKeycode(display, XK_Shift_L); }
XKeyEvent defaultKeyEvent(void) { XKeyEvent event;
event.window = targetWindow; event.root = rootWindow; event.subwindow = targetWindow; event.time = CurrentTime; event.x = 0; event.y = 0; event.x_root = 0; event.y_root = 0; event.same_screen = False;
return event; }
void findPointerWindow(void) { Window childWindow; unsigned int modifierMask;
childWindow = rootWindow; do { targetWindow = childWindow;
if (!XQueryPointer(display, targetWindow, &rootWindow, &childWindow, &rootPointerX, &rootPointerY, &pointerX, &pointerY, &modifierMask)) { std::cerr << "Couldn't locate pointer window. Exiting." << std::endl; std::exit(-1); } } while (childWindow != None);
if (targetWindow == rootWindow) { std::cerr << "Pointer is in root window. Exiting." << std::endl; std::exit(-1); } }
void closeDisplay(void) { XCloseDisplay(display); display = 0; }
void sendKeyEvent(XKeyEvent* keyEvent) { XSendEvent(display, targetWindow, True, KEY_EVENT_MASK, (XEvent*)keyEvent); }
void sendShiftEvent(bool shiftDown) { XKeyEvent shiftKeyEvent = defaultKeyEvent();
shiftKeyEvent.type = (shiftDown) ? KeyPress : KeyRelease; shiftKeyEvent.window = targetWindow; shiftKeyEvent.state = (shiftDown) ? 0 : ShiftMask; shiftKeyEvent.keycode = lShiftKeycode;
sendKeyEvent(&shiftKeyEvent); }
void sendKeyStroke(KeyCode keyCode, bool shiftDown) { static bool wasShiftDown = false;
if (shiftDown != wasShiftDown) { sendShiftEvent(shiftDown); wasShiftDown = shiftDown; }
XKeyEvent mainKeyEvent = defaultKeyEvent();
mainKeyEvent.state = (shiftDown) ? ShiftMask : 0; mainKeyEvent.keycode = keyCode;
mainKeyEvent.type = KeyPress; sendKeyEvent(&mainKeyEvent);
mainKeyEvent.type = KeyRelease; sendKeyEvent(&mainKeyEvent);
XSync(display, False); msleep(HOLD_TIME__MS); }
void sendKeysym(KeySym keysym) { KeyCode keycode = XKeysymToKeycode(display, keysym);
KeySym lowerKeysym; KeySym upperKeysym; XConvertCase(keysym, &lowerKeysym, &upperKeysym);
bool needShift = (keysym != XKeycodeToKeysym(display, keycode, 0)) || (keysym != lowerKeysym);
sendKeyStroke(keycode, needShift); }
void sendChar(char ch) { KeySym keysym;
if (!isascii(ch)) { return; }
switch (ch) { case '\n': keysym = XK_Return; break;
case '\r': return;
case '\t': keysym = XK_space; break;
case '\v': return;
default: if (!isprint(ch)) { return; } keysym = ch; break; }
sendKeysym(keysym); }
int main(int argc, char** argv) { openDisplay(); findPointerWindow();
char ch; while (std::cin.get(ch)) { sendChar(ch); }
closeDisplay();
return 0; }
|
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
|
08-05-2006 04:55
BTW, to compile the above a command such as the following should work on most distributions (assuming you named the file sltyper.C and it is in the current working directory): g++ -o sltyper sltyper.C -lX11
|
Llauren Mandelbrot
Twenty-Four Weeks Old.
Join date: 26 Apr 2006
Posts: 665
|
Where can I get this?
08-05-2006 10:07
Way cool! Where can I get a binary of this? I`m not prepared to compile my own sources. [Heck, I don`t even know if I have a compiler installed.  ]
|
Michael Balboa
Registered User
Join date: 4 Aug 2006
Posts: 2
|
08-05-2006 17:13
From: Orren Walcott Ah, many thanks! This helped me write a tiny bash script to keep SL from logging off after 30 minutes:
#!/bin/bash while true; do xse -window 0x2c0000e '<MotionNotify> Normal' sleep 600 done
Basically just an infinite loop that sends a mouse motion event every 10 minutes. Run it in the background and end it with killall; I'm too lazy to put any kind of control on it. Thanks to you too Oren. Bash script works a treat...I can now earn some money while sleeping. Much appreciated Michael
|
Michael Balboa
Registered User
Join date: 4 Aug 2006
Posts: 2
|
08-05-2006 17:20
From: Zi Ree Hi Linux group! I hacked a perl script that sends x-events to the Second Life client, so I can write my LSL scripts in my favorite editor and paste them into SL. It's still very ugly, but at least it's a start. Copy is not possible this way, but maybe someone finds this script useful. German and english/US keymap support is already implemented. Other layouts can be added. You will need xse to use the script. Get it from ftp://ftp.uni-magdeburg.de/pub/mirror/hpux.ask.uni-karlsruhe.de/X11/Misc/xse-2.1Have fun! #!/usr/bin/perl -w
# text2xev.pl V0.1 (C)2006 Zi Ree@Second Life # converter for pasting text into Second Life client window. # use, copy, modify and spread freely, I hope it wonj't be needed too much longer :) # have fun! # -- Zi!
# you need xse installed somewhere # get it from ftp://ftp.uni-magdeburg.de/pub/mirror/hpux.ask.uni-karlsruhe.de/X11/Misc/xse-2.1
use strict;
# Your Second Life window id (try xwininfo to get it) my($id)="0x2a0000e";
# path to the xse binary my($xse)="xse-2.1/xse";
my($line);
# read from stdin while($line=<>) { my($char); $line =~ s/^ +//; # skip blanks in the front, makes LSL editor behave better
# split line into individual characters my(@chars)=split //,$line; my($oldsym)="";
# go through characters foreach $char (@chars) { # convert key to xevent syntax, depending on keyboard layout my($output,$sym)=char2xev($char);
# pause for a moment if the same key is pressed twice (events get lost otherwise) if($sym eq $oldsym) { select(undef,undef,undef,0.25); }
# send events via xse to the Second Life client open(XSE,"| $xse -window $id -file /dev/stdin"); print XSE $output; close(XSE);
# remember sent key $oldsym=$sym; } # foreach } # while
# ------------------------
sub char2xev { my($char)=shift; if($char eq "\n") { $char="LF"; }
# modifier key / states my(%modifiers)=( "-" => "", "s" => "Shift", "l" => "Lock", "c" => "Ctrl", "a" => "Mod1", # untested "g" => "Mod5" # ALT-GR for german keyboard );
# select one of the following mappings by calling it "%conv" # more mappings can be added later
# german keyboard mapping (currently active) my(%conv)=( "^" => ["-","dead_circumflex"], "ß" => ["-","ssharp"], "´" => ["-","dead_acute"], "°" => ["s","dead_circumflex"], "!" => ["s","1"], "\"" => ["s","2"], "§" => ["s","3"], "\$" => ["s","4"], "%" => ["s","5"], "&" => ["s","6"], "/" => ["s","7"], "(" => ["s","8"], ")" => ["s","9"], "=" => ["s","0"], "?" => ["s","ssharp"], "`" => ["s","dead_acute"], "¬" => ["g","dead_circumflex"], "¹" => ["g","1"], "²" => ["g","2"], "³" => ["g","3"], "¼" => ["g","4"], "½" => ["g","5"], "¬" => ["g","6"], "{" => ["g","7"], "[" => ["g","8"], "]" => ["g","9"], "}" => ["g","0"], "\\" => ["g","ssharp"], "ü" => ["-","udiaeresis"], "+" => ["-","plus"], "\t" => ["-","Tab"], "Q" => ["s","q"], "W" => ["s","w"], "E" => ["s","e"], "R" => ["s","r"], "T" => ["s","t"], "Z" => ["s","z"], "U" => ["s","u"], "I" => ["s","i"], "O" => ["s","o"], "P" => ["s","p"], "Ü" => ["s","udiaeresis"], "*" => ["s","plus"], "@" => ["g","q"], "~" => ["g","plus"], "ö" => ["-","odiaeresis"], "ä" => ["-","adiaeresis"], "#" => ["-","numbersign"], "A" => ["s","a"], "S" => ["s","s"], "D" => ["s","d"], "F" => ["s","f"], "G" => ["s","g"], "H" => ["s","h"], "J" => ["s","j"], "K" => ["s","k"], "L" => ["s","l"], "Ö" => ["s","odiaeresis"], "Ä" => ["s","adiaeresis"], "'" => ["s","numbersign"], "<" => ["-","less"], "," => ["-","comma"], "." => ["-","period"], "-" => ["-","minus"], ">" => ["s","less"], "Y" => ["s","y"], "X" => ["s","x"], "C" => ["s","c"], "V" => ["s","v"], "B" => ["s","b"], "N" => ["s","n"], "M" => ["s","m"], ";" => ["s","comma"], ":" => ["s","period"], "_" => ["s","minus"], "|" => ["g","less"], "µ" => ["g","m"], "·" => ["g","period"], " " => ["-","space"], "LF" => ["-","Return"], );
# english (EN or US) keyboard mapping (partly untested) my(%conv_us)=( "`" => ["-","grave"], "-" => ["-","minus"], "=" => ["-","equal"], "~" => ["s","grave"], "!" => ["s","1"], "@" => ["s","2"], "#" => ["s","3"], "\$" => ["s","4"], "%" => ["s","5"], "^" => ["s","6"], "&" => ["s","7"], "*" => ["s","8"], "(" => ["s","9"], ")" => ["s","0"], "_" => ["s","minus"], "+" => ["s","equal"], "\t" => ["-","Tab"], "[" => ["-","braceleft"], "]" => ["-","braceright"], "Q" => ["s","q"], "W" => ["s","w"], "E" => ["s","e"], "R" => ["s","r"], "T" => ["s","t"], "Y" => ["s","y"], "U" => ["s","u"], "I" => ["s","i"], "O" => ["s","o"], "P" => ["s","p"], "{" => ["s","braceleft"], "}" => ["s","braceright"], ";" => ["-","semicolon"], "'" => ["-","apostrophe"], "\\" => ["-","backslash"], "A" => ["s","a"], "S" => ["s","s"], "D" => ["s","d"], "F" => ["s","f"], "G" => ["s","g"], "H" => ["s","h"], "J" => ["s","j"], "K" => ["s","k"], "L" => ["s","l"], ":" => ["s","semicolon"], "\"" => ["s","apostrophe"], "|" => ["s","backslash"], "," => ["-","comma"], "." => ["-","period"], "/" => ["-","slash"], "Z" => ["s","z"], "X" => ["s","x"], "C" => ["s","c"], "V" => ["s","v"], "B" => ["s","b"], "N" => ["s","n"], "M" => ["s","m"], "<" => ["s","comma"], ">" => ["s","period"], "?" => ["s","slash"], " " => ["-","space"], "LF" => ["-","Return"], ); # if key is on convert list if(defined($conv{$char})) { my($out)="";
# get event definition my($def)=$conv{$char};
# build xse string $out=$modifiers{@$def[0]}."<Key>".@$def[1]."\n".$modifiers{@$def[0]}."<KeyUp>".@$def[1]."\n"; return ($out,@$def[1]); } else { # standard letter / digit, just return xse string return ("<Key>$char\n<KeyUp>$char\n",$char); } }
Zi, Great stuff...just want to say thanks...works a charm! I had a little fun getting xse to compile, but it worked eventually..  thanks again Michael
|
Davorak Black
Registered User
Join date: 12 Apr 2005
Posts: 3
|
Bash scripting wth a pinch of python
08-09-2006 11:56
After reading the thread I thought to myself there is a perl implementation a C++ implementation it would be nice to have a python implementation. After a little research I discovered Xlib was apparently the library to use to interface python and the X11. My lack of understanding of X11 and the fact that I could not google, krugle, koder a good example, and general laziness prevented anything from happening on The Xlib python front. Instead of a python Xlib implementation I give some command line shenanigans with and optional python wrapper. Scripting is not my forte so improvements may be need and are welcomed. Needed utilities xte, xwit(or wmctrl) xte is part of the xautomation deb package xnee could possible replace xte though I could not get it to type all characters correctly. On the command line. xwit -focus -select; xte "str $(cat <file>)"
This command will prompt the user to click the window they want the automation to run on. To work on a specific window id xwit -focus -id <winid>; xte "str $(cat <file>)"
I did not want to write that all out each time I ran the script though so.. In python import sys import os
args = sys.argv if len(args)==1: print "send.py [file] [xwit options:default='-select']" sys.exit()
file = open(sys.argv[1]).read()
xwitcommands = ' '.join(sys.argv[2:]) if xwitcommands is '': xwitcommands = '-select'
command = r'xwit -focus ' + xwitcommands + '; xte "str ' + file + '"'
os.popen(command)
And in bash: #!/bin/bash
if [ $# -eq 0 ]; then echo 'send [file] [xwit options:default='-select']' fi
if [ $# -eq 1 ]; then xwitcommands="-select" else xwitcommands=${@:2} fi
echo $xwitcommands
xwit -focus $xwitcommands; xte "str $(cat $1)"
These scripts take the file name first and then options for xwit. The default behavior is to prompt the user to select what window to run on. I have not done it yet but I am sure that xte, xwit could be used to script other sl events maybe an automatic import of a directory filled with scripts. Best regards, pjw Edit: The above code only works on very short files. Here is a better version: import sys import os import time
if len(sys.argv)==1: print "send.py [file] [xwit options:default='-select']" sys.exit()
file = open(sys.argv[1])
xwitoptions = ' '.join(sys.argv[2:]) if xwitoptions is '': xwitoptions = '-select'
# Making wxit command for window selection xwitcommand = r'xwit -focus ' + xwitoptions
charmaping = {'\n':'Return'}
input = file.read() mappedinput = [charmaping.get(c, c) for c in input] xteinput = ['"key ' + c + '"' for c in mappedinput] xtecommand = 'xte ' + ' "usleep 5000" '.join(xteinput) command = xwitcommand + ' ; ' + xtecommand os.popen(xwitcommand) time.sleep(.2) os.popen(xtecommand)
|
tiller Gilman
Registered User
Join date: 22 Jul 2004
Posts: 200
|
Wow
08-20-2006 06:42
This stuff is fntastic what is it,lol.  .waits quietly for a lamer version. 
|
Issarlk Chatnoir
Cross L. apologist.
Join date: 3 Oct 2004
Posts: 424
|
08-31-2006 04:38
From: Hewee Zetkin Don't forget to place your mouse cursor over SL! Otherwise it will silently do nothing (at least, most terminals are set to ignore events sent bye 'XSendEvent()' for security, so PROBABLY nothing will happen...). It works great. Thanks.
_____________________
Vincit omnia Chaos From: Flugelhorn McHenry Anyway, ignore me, just listen to the cow
|