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 <stdio.h>
#include <stdlib.h>


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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/X.h>
#include <X11/Xlib.h>
//#include <X11/Xutil.h>
//#include <X11/Xatom.h>
#include <X11/keysym.h>

// xprop

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



#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
#define _NET_WM_STATE_ADD           1    /* add/set property */
#define _NET_WM_STATE_TOGGLE        2    /* 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 EXIT_SUCCESS;
}




// ERROR HANDLER, GENERIC
static int ErrorHandler (Display *display, XErrorEvent *error)
{
   //printf ("\r\n error! \r\n");// gcc -o xwinspy lol.c -L/usr/X11R6/lib -lX11
   return 0;
}
// END ERROR HANDLER


// Recursively search through all windows on display
Window SearchWindow(char* szWindowToFind, int level, Display *display, Window rootWindow, int iMatchMode, int showErrors)
{
	Window parent;
	Window *children;
	unsigned int noOfChildren;
	int status;
	int i;
	Window wSearchedWindow = 0;
	
	char* win_name;
	if (XFetchName(display, rootWindow, &win_name))
	{
			//printf("WinName (Level %d): %s\n", level, win_name);
			if(iMatchMode == 0)
			{
				if( strstr(win_name, szWindowToFind) )
				{
					return rootWindow;
				}
			}
			else if(iMatchMode == 1)
			{
				if( !strcmp(win_name, szWindowToFind) )
				{
					return rootWindow;
				}
			}
			else if(iMatchMode == 2)
			{
				if( strcasestr(win_name, szWindowToFind) )
				{
					return rootWindow;
				}
			}
			else if(iMatchMode == 3)
			{
				if( !strcasecmp(win_name, szWindowToFind) )
				{
					return rootWindow;
				}
			}
			else 
			{
				if( strstr(win_name, szWindowToFind) )
				{
					return rootWindow;
				}
			}
			
	} // End if XFetchName
	
	
	
	status = XQueryTree (display, rootWindow, &rootWindow, &parent, &children, &noOfChildren);
	
	if (status == 0)
	{
		if (showErrors)
			printf ("ERROR - Could not query the window tree. Aborting.\r\n");
		return;
	}
	
	if (noOfChildren > 0)
	{
		for (i=0; i < noOfChildren; i++)
		{
			wSearchedWindow = SearchWindow(szWindowToFind, level+1, display, children[i], iMatchMode, showErrors);
			if(wSearchedWindow)
			{
				break;
			}
		}
	} 
	
	XFree ((char*) children);
	
	return wSearchedWindow;
} // End Sub EnumerateWindows


Window FindWindow(char* szWindowToFind)
{
	Display *display = XOpenDisplay (NULL);
	int screen = DefaultScreen (display);
	
	XSetErrorHandler(ErrorHandler);
	
	Window rootWindow = RootWindow (display, screen);   
	
	Window wSearchedWindow = SearchWindow(szWindowToFind, 0, display, rootWindow, 0, 0);
	
	char* win_name;
	if (XFetchName(display, wSearchedWindow, &win_name))
	{
		printf("Found: %s\n", win_name);
	}
	
	XCloseDisplay (display);
	return wSearchedWindow;
}



void ActivateWindow(char* szWindow)
{
	Window wdThisWindow = FindWindow(szWindow);


	
	Display *display = XOpenDisplay (NULL);
	
	char* win_name;
	if (XFetchName(display, wdThisWindow, &win_name))
	{
		printf("Activating: %s\n", win_name);
	}
	
	XSetErrorHandler(ErrorHandler);
	activate_window(display, wdThisWindow) ;
	
	
	XSetInputFocus(display, wdThisWindow, RevertToNone, CurrentTime);
	
	XCloseDisplay (display);
}



void MoveWindow(char* szWindow, int x, int y) {
	Display *display = XOpenDisplay (NULL);
	
	XSetErrorHandler(ErrorHandler);
	
	Window wdThisWindow = FindWindow(szWindow);
	
	char* win_name;
	if (XFetchName(display, wdThisWindow, &win_name))
	{
		printf("Moving: %s\n", win_name);
	}
	
	XMoveWindow(display, wdThisWindow, x, y);
	
    XCloseDisplay (display);
}


void ResizeWindow(char* szWindow, unsigned int width, unsigned int height) 
{
	Display *display = XOpenDisplay (NULL);
	
	XSetErrorHandler(ErrorHandler);
	
	Window wdThisWindow = FindWindow(szWindow);
	
	char* win_name;
	if (XFetchName(display, wdThisWindow, &win_name))
	{
		printf("Moving: %s\n", win_name);
	}
	
	XResizeWindow(display, wdThisWindow, width, height);
	
    XCloseDisplay (display);
}



// X11 modifier masks for various keys
static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
static unsigned num_mask, mode_switch_mask;


static void get_modifier_masks(Display *display)
{
	static unsigned got_masks;
	int i, j;
	XModifierKeymap *xmods;
	unsigned n;

	if(got_masks)
		return;

	xmods = XGetModifierMapping(display);
	n = xmods->max_keypermod;
	for(i = 3; i < 8; i++) 
	{
		for(j = 0; j < n; j++) 
		{
			KeyCode kc = xmods->modifiermap[i * n + j];
			KeySym ks = XKeycodeToKeysym(display, kc, 0);
			unsigned mask = 1 << i;
			switch(ks) {
			case XK_Num_Lock:
				num_mask = mask; break;
			case XK_Alt_L:
				alt_l_mask = mask; break;
			case XK_Alt_R:
				alt_r_mask = mask; break;
			case XK_Meta_L:
				meta_l_mask = mask; break;
			case XK_Meta_R:
				meta_r_mask = mask; break;
			case XK_Mode_switch:
				mode_switch_mask = mask; break;
			}
		}
	}
	XFreeModifiermap(xmods);
	got_masks = 1;
	
	printf("meta_l_mask: 0x%08X\n", meta_l_mask);
	printf("meta_r_mask: 0x%08X\n", meta_r_mask);
	printf("alt_l_mask: 0x%08X\n", alt_l_mask);
	printf("alt_r_mask: 0x%08X\n", alt_r_mask);
	printf("num_mask: 0x%08X\n", num_mask);
	printf("mode_switch_mask: 0x%08X\n", mode_switch_mask);
}

int iWithShift = 0;
int iWithCtrl  = 0;
int iWithAltL  = 0;


void ResetModifiers()
{
	iWithShift = 0;
	iWithCtrl  = 0;
	iWithAltL  = 0;
}

void WithShift()
{
	iWithShift = 1;
}

void WithCtrl()
{
	iWithCtrl = 1;
}


void WithAltL()
{
	iWithAltL  = 1;
}

void WithCtrlAltL()
{
	iWithCtrl = 1;
	iWithAltL  = 1;
}


typedef struct
{
	char cChar;
	KeySym Key;
	int iRequiresShift;
} special_character_t;


// gedit /usr/include/X11/keysymdef.h
static special_character_t special_characters [] =
{
	
	{ ' ',  XK_space },
	{ '\t', XK_KP_Tab   },
	{'\r',  XK_Return },
	{'\n',  XK_KP_Enter },
	
	{ '/',  XK_slash, 1   },
	{ '\\', XK_backslash  },
	{ '_',  XK_underscore },
	{ ';',  XK_semicolon  },
	{ '\'', XK_apostrophe },
	{ '"',  XK_quotedbl   },
	
	{ '0',  XK_KP_0},
	{ '1',  XK_KP_1},
	{ '2',  XK_KP_2},
	{ '3',  XK_KP_3},
	{ '4',  XK_KP_4},
	{ '5',  XK_KP_5},
	{ '6',  XK_KP_6},
	{ '7',  XK_KP_7},
	{ '8',  XK_KP_8},
	{ '9',  XK_KP_9},
	  
	{ '#', XK_numbersign},  
	{ ',', XK_comma},
	{ '.', XK_KP_Decimal},
    { '-', XK_minus },
    { '+', XK_KP_Add },
    { '*', XK_asterisk},
    { ':', XK_colon },
    { '^', XK_asciicircum},
    { '!', XK_exclam},
    { '=', XK_KP_Equal},
    { '>', XK_greater},
    { '<', XK_less},
    
    { '@', XK_at},
    { '~', XK_asciitilde },
    { '&', XK_ampersand },
    { '|', XK_bar},
    
    { '%', XK_percent  },
    { '?', XK_question },
    { '$', XK_dollar   },    
    
    { '(', XK_parenleft   },
    { ')', XK_parenright  },
    { '{', XK_braceleft   },
    { '}', XK_braceright  },
    { '[', XK_bracketleft },
    { ']', XK_backslash   },
    
};

static int special_character_count = sizeof(special_characters) / sizeof(special_characters[0]);

void SendSomeKeys(Display *display, Window wdThisWindow, Window wdThisRootWindow, char cThisChar)
{
	XKeyEvent event;
	event.display = display;
	//event.window = cur_focus;
	event.window = wdThisWindow;
	event.root = wdThisRootWindow;
	event.subwindow = None;
	event.time = CurrentTime;
	event.x = 1;
	event.y = 1;
	event.x_root = 1;
	event.y_root = 1;
	event.same_screen = True;
	event.state = 0;
	event.type = KeyPress;
	
	char szText[2] ;
	sprintf(szText, "%c", cThisChar);
	KeySym ThisKey = XStringToKeysym(szText);
	
	/*
	KeySym lower_return;
	KeySym upper_return;
	XConvertCase(ThisKey, &lower_return, &upper_return);
	 
	
	
	// gedit /usr/include/X11/X.h
	
	#define XK_Shift_L                       0xffe1 
	#define XK_Shift_R                       0xffe2 
	
	#define KeyPressMask	(1L<<0)
	#define KeyReleaseMask	(1L<<1)
	
	
	#define ShiftMask		(1<<0)
	#define LockMask		(1<<1)
	#define ControlMask		(1<<2)
	#define Mod1Mask		(1<<3)
	#define Mod2Mask		(1<<4)
	#define Mod3Mask		(1<<5)
	#define Mod4Mask		(1<<6)
	#define Mod5Mask		(1<<7)
	
	*/
	
	event.keycode = XKeysymToKeycode(display, ThisKey);
	
	int j;
	for(j=0; j < special_character_count; ++j)
	{
		if(special_characters[j].cChar == cThisChar)
		{
			event.keycode = XKeysymToKeycode(display, special_characters[j].Key);
			iWithShift = special_characters[j].iRequiresShift;
			break;
		}
	}
	
	//event.keycode = XKeysymToKeycode(target_dpy, XK_Control_L);
	//event.keycode = XKeysymToKeycode(display, XK_0);
	
	
	if(tolower(cThisChar) != cThisChar)
		iWithShift = 1;
	
	if(iWithShift)
		event.state |= ShiftMask;
	
	if(iWithCtrl)
		event.state |= ControlMask;
	
	if(iWithAltL)
		event.state |= alt_l_mask;
	
	XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *) &event);
	
	usleep(10);
	//sleep(1);
	
	event.type = KeyRelease;
	//XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *) event);
	XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *) &event);
	ResetModifiers();
}


void SendString(char* szTargetWindow, char* szTextToSend)
{
	Window wdThisWindow = FindWindow(szTargetWindow);
	Display *display = XOpenDisplay (NULL);
	XSetErrorHandler(ErrorHandler);
	
	Window wndroot = RootWindow(display, DefaultScreen(display));
	
	get_modifier_masks(display);


	
	int i;
	for(i=0; i < strlen(szTextToSend); ++i)
	{
		SendSomeKeys(display, wdThisWindow, wndroot, szTextToSend[i]);
		
		//printf("%c", szTextToSend[i]);
	}
	//SendTerminate(display, wdThisWindow, wndroot, 'X');
	//printf("\n");
	XCloseDisplay (display);
}




int main(int argc, char* argv[])
{
	system("open \"/usr/bin/notjode\" \"/root/Downloads/my_own_apk.dex.jar\"");
	sleep(1);
	ActivateWindow("Decompiler");
	
	/*
	WithShift()
	WithCtrl()
	*/
	
	
	WithCtrlAltL();
	SendString("Decompiler", "s");
	sleep(1);
	
	SendString("Save", "/root/Desktop/my_own_apk.src.zip");
	sleep(1);
	
	//WithAltL();
	//SendString("Save", "s");
	SendString("Save", "\n");
	sleep(1);
	WithAltL();
	SendString("Save", "y");
	sleep(1);
	WithAltL();
	SendString("Decompiler", "x");
	sleep(1);
	
	//SendSomeKeys("gedit");
	//MoveWindow("fuel-efficiency", 50, 50);
	//ResizeWindow("fuel-efficiency", 50, 50);
	return EXIT_SUCCESS;
}
_______________________________________________
Mono-vb mailing list
[email protected]
http://lists.ximian.com/mailman/listinfo/mono-vb

Reply via email to