Re: [Mono-dev] AppActivate and System.Windows.Forms.SendKeys on Ubuntu 10.10

2011-03-21 Thread Quandary
To make a long mail short, that's incorrect.

When you look at xvkbd-3.0, focus a window and simulate alt+f4, it
closes, and with simulated alt + tab, it switches windows.

Looking at its sources, it's not working with XSendEvent there however,
it uses some magic in libxtst, which however, just all comes back to
some wrapping around base X11 calls.

I didn't look any closer at it, as I don't deem ALT+TAB and ALT+F4 as
important in respect to SendKeys.
Sending key combinations + key modifiers (ALT/CTRL) to other application
however, is.

Thus I attached fixme.c, a basic key dispatch implementation for
Linux/X11 in C using XSendEvent.
It's probably still a bit buggy, especially in respect to
"UNICODE"/KeyboardInternationalization (not really important in this
respect IMHO).
I'll probably port it to CS next weekend.


Note that it also contains an AppActivate implementation for Linux !
(It doesn't yet switch to the appropriate workspace, but fixing that is
rather simple, but unfortunately time-consuming, and as I don't need it,
I have just commented that part out for now)
AppActivate for Windows is simple, just pinvoke SetActiveWindow.

I don't have a Mac, but the simplest way to activate a window there I
found to be so easy I can implement it blindly:


[System.Runtime.InteropServices.DllImport("libc", EntryPoint = "system")]
internal extern static int system(string strCommand);

Note that in the below C snippet, one would still need to check for
malicious \n\r or semicolons when the application title is being
supplied as parameter.
-

#include 
#include 


int main(int argc, char* argv[])
{
//
http://stackoverflow.com/questions/3313332/bringing-another-apps-window-to-front-on-mac-in-c
system("osascript -e \"tell application \\\"Address Book\\\" to
activate\"");
return EXIT_SUCCESS;
}







On 03/17/2011 03:19 AM, Jonathan Pryor wrote:
> Now, what does X11 provide? A cursory glance shows XSendEvent:
>   http://tronche.com/gui/x/xlib/event-handling/XSendEvent.html
>
> This allows passing an XEvent, such as an XKeyEvent, to a given window.
>
> Problem: In Windows, it's the operating system which handles the input, which 
> thus allows OS "capturing" of Alt+Tab so that the active application is 
> switched. In X11, XSendEvent() requires that you explicitly specify both the 
> Display and Window that the event is being passed to. Consequently, there is 
> NO MECHANISM to have Alt+Tab "captured" by the OS and thus change windows 
> (even if Alt+Tab _will_ change windows when typed via the keyboard). This is 
> because the WIndow Manager is grabbing Alt+Tab, but the Window Manager is a 
> completely separate process, and there's not necessarily an easy way to grab 
> the Display+Window for the Window Manager (which might not have a Window to 
> begin with).


#include 
#include 
#include 
#include 
#include 
//#include 
//#include 
#include 

// xprop

// Compile using:
// gcc -o sendmsg sendmsg.c -L/usr/X11R6/lib -lX11



#define _NET_WM_STATE_REMOVE0/* remove/unset property */
#define _NET_WM_STATE_ADD   1/* add/set property */
#define _NET_WM_STATE_TOGGLE2/* toggle property  */


static int client_msg(Display *disp, Window win, char *msg, 
unsigned long data0, unsigned long data1, 
unsigned long data2, unsigned long data3,
unsigned long data4) {
XEvent event;
long mask = SubstructureRedirectMask | SubstructureNotifyMask;

event.xclient.type = ClientMessage;
event.xclient.serial = 0;
event.xclient.send_event = True;
event.xclient.message_type = XInternAtom(disp, msg, False);
event.xclient.window = win;
event.xclient.format = 32;
event.xclient.data.l[0] = data0;
event.xclient.data.l[1] = data1;
event.xclient.data.l[2] = data2;
event.xclient.data.l[3] = data3;
event.xclient.data.l[4] = data4;

if (XSendEvent(disp, DefaultRootWindow(disp), False, mask, &event)) {
return EXIT_SUCCESS;
}
else {
fprintf(stderr, "Cannot send %s event.\n", msg);
return EXIT_FAILURE;
}
}




static int activate_window (Display *disp, Window win) //  , gboolean switch_desktop) 
{
unsigned long *desktop;
	/*
// desktop ID
if ((desktop = (unsigned long *)get_property(disp, win, XA_CARDINAL, "_NET_WM_DESKTOP", NULL)) == NULL) 
{
if ((desktop = (unsigned long *)get_property(disp, win,
XA_CARDINAL, "_WIN_WORKSPACE", NULL)) == NULL) {
p_verbose("Cannot find desktop ID of the window.\n");
}
}

if (switch_desktop && desktop) {
if (client_msg(disp, DefaultRootWindow(disp), 
"_NET_CURRENT_DESKTOP", 
*desktop, 0, 0, 0, 0) != EXIT_SUCCESS) {
p_verbose("Cannot switch desktop.\n");
}
g_free(desktop);
}
	*/
client_msg(disp, win, "_NET_ACTIVE_WINDOW", 0, 0, 0, 0, 0);
XMapRaised(disp, win);

return EX

Re: [Mono-dev] AppActivate and System.Windows.Forms.SendKeys on Ubuntu 10.10

2011-03-16 Thread Jonathan Pryor
On Mar 16, 2011, at 4:07 PM, Quandary wrote:
> What, only SendKeys to WinForms, are you serious ?
> That doesn't make much sense.

It makes perfect sense.

> It sends KeyEvents to the Windowing system, which happens to be the
> WinAPI on Windows, or X11 on Linux for all intents and purposes.
> GTK has nothing to do with it.
> 
> You send the keyboard keys as simulated input to X11, and before that,
> you set the focus window.

The problem is that there is no such mechanism in X11, at least not in a way 
that can be used in a straightforward fashion.

For example, Microsoft's SendKeys.Send() method is _probably_ implemented in 
terms of the SendInput() WinAPI function:

http://msdn.microsoft.com/en-us/library/ms646310(VS.85).aspx

So SendKeys.Send() presumably maps the input string into a set of INPUT 
structures, then sends the structures to SendInput() so that the operating 
system will interpret them. Note that this is _very_ low level, working at the 
keyboard level, not the thread event loop level.

One of the things that this allows is that SendKeys.Send("%{TAB}") (aka 
Alt+Tab) will change the active window.

Now, what does X11 provide? A cursory glance shows XSendEvent:

http://tronche.com/gui/x/xlib/event-handling/XSendEvent.html

This allows passing an XEvent, such as an XKeyEvent, to a given window.

Problem: In Windows, it's the operating system which handles the input, which 
thus allows OS "capturing" of Alt+Tab so that the active application is 
switched. In X11, XSendEvent() requires that you explicitly specify both the 
Display and Window that the event is being passed to. Consequently, there is NO 
MECHANISM to have Alt+Tab "captured" by the OS and thus change windows (even if 
Alt+Tab _will_ change windows when typed via the keyboard). This is because the 
WIndow Manager is grabbing Alt+Tab, but the Window Manager is a completely 
separate process, and there's not necessarily an easy way to grab the 
Display+Window for the Window Manager (which might not have a Window to begin 
with).

In short, you can't get there from here, as the entire X11 architecture is 
~completely different.

> At least on Windows.

Exactly. On Windows, everything uses the same WinAPI message looping mechanism. 
On X11, very little is consistent across toolkits, and X11 doesn't specify much 
(leaving it up to the Window Manager + applications + ... to work out the 
details).

Then there's OSX, which uses yet another completely different mechanism. 
SendKeys.Send() is inherently Windows specific; you should be glad it works for 
System.Windows.Forms apps at all.

 - Jon

___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


Re: [Mono-dev] AppActivate and System.Windows.Forms.SendKeys on Ubuntu 10.10

2011-03-16 Thread Quandary
What, only SendKeys to WinForms, are you serious ?
That doesn't make much sense.

The SendKeys function is just a static method that resides in
System.Windows.Forms,
and has nothing to do with WinForms otherwise.

It sends KeyEvents to the Windowing system, which happens to be the
WinAPI on Windows, or X11 on Linux for all intents and purposes.
GTK has nothing to do with it.

You send the keyboard keys as simulated input to X11, and before that,
you set the focus window.
X11 processes it, and forwards the input to the respective application's
handlers/callbacks.
Using it works with everything, GTK+/WinForms/QT/wxWidgets/Java etc.,
since it's just the same as if you press a keyboard key.

At least on Windows.
And if mono doesn't, that's a bug and needs to be fixed.

SendKeys is the only way to steer a 3rd party applications if every
other method fails or isn't implemented applicationwise.

If it was a WinForms application, it would mean it's written in C#,
which would mean I could just automagically reverse engineer it and
recreate a console application instead of resorting to sendkeys.



On 03/16/2011 08:07 PM, Bojan Rajkovic wrote:
>
> Erm, I don't think SendKeys for WinForms is going to work against !WinForms 
> apps on Linux. gEdit is GTK+, so the mainloops don't match at all, and gEdit 
> likely isn't expecting any keys from Mono.
>
> —Bojan

___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


Re: [Mono-dev] AppActivate and System.Windows.Forms.SendKeys on Ubuntu 10.10

2011-03-16 Thread Bojan Rajkovic
On Mar 16, 2011, at 8:37 AM, Quandary wrote:

> Hi,
> 
> Question: 
> Is System.Windows.Forms.SendKeys implemented and working on Ubuntu Linux ?
> 
> I try to control JD-GUI with it, but the keys don't arrive, neither do they 
> arrive in gedit.
> They do arrive in Notepad on Windows using the same program, and they work 
> with JD-GUI on Windows, using the same program. 
> 
> Or does it need any library installed, such as XTest/XFakeEvent ?
> 
> 
> And BTW, Microsoft.VisualBasic.Interaction.AppActivate("Window Title") throws 
> not implemented...
> 
> You can use the functions:
>  static Window FindWindow(Window top, char *name)
>  static void GetFocusedWindow(void)
> From xvkbd -> in file xvkbd.c
> Basically, all you need to do is save the mouse position, find the target 
> window position & rectangle, and press the left mousebutton somewhere on it 
> with mousedown & mouseup via xsendevent, then restore the mouse position.
> 
> I can supply left + right mousedown + mouseup,
> I have appended cMouse.cs and the dependencies: XorgAPI + XorgStructs.
> 
> And when I loop through all processes, as shown below, I don't get a 
> WindowTitle anywhere...
> (using mono 2.10.1 on Ubuntu)
> 
> 
> public void GetProcesses()
> { 
> System.Diagnostics.Process[] processlist = 
> System.Diagnostics.Process.GetProcesses();
> 
> string str = "";
> foreach(System.Diagnostics.Process theprocess in processlist)
> {
> Console.WriteLine("Process: {0} ID: {1} WindowTitle: {2}", 
> theprocess.ProcessName, theprocess.Id, theprocess.MainWindowTitle);
> str += string.Format("Process: {0} ID: {1} WindowTitle: {2}", 
> theprocess.ProcessName, theprocess.Id, theprocess.MainWindowTitle);
> str += Environment.NewLine;
> }
> MessageBox.Show(str);
> }
> 
> 
> 
> ___
> Mono-devel-list mailing list
> Mono-devel-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list

Erm, I don't think SendKeys for WinForms is going to work against !WinForms 
apps on Linux. gEdit is GTK+, so the mainloops don't match at all, and gEdit 
likely isn't expecting any keys from Mono.

—Bojan
___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list