Thursday January 27, 2005
playing around with mice and windows
Updated: 2005/02/03 - it didn't build so well on Linux.
This is a bit of code for Solaris which allows you to:
- Move your mouse around the screen
- Resize the window under the mouse
- Move the window under the mouse
| Solaris | Linux (mandrake 10 tested) |
|---|---|
| cc -v -I/usr/openwin/include -L/usr/openwin/lib -R/usr/openwin/lib -o movemouse movemouse.c -lX11 -lXmu | gcc -DLINUX -W -I/usr/X11R6/include -L/usr/X11R6/lib -o movemouse movemouse.c -lX11 -lXmu |
The meaning of the -R/usr/openwin/lib for solaris is to set the run-time linker lookup to try the /usr/openwin/lib path for libraries, as part of the symbol resolution step. Otherwise it relies on either the LD_LIBRARY_PATH (It is evil), or the crle path (man crle - it is neat).
For Linux you normally have the /etc/ld.so.conf file, which typically has /usr/X11R6/lib in there (and if you've got qt, probably has /usr/lib/qt3/lib as well). If you want to find out more abou tthis then look at the info/man page for ldconfig.
I have this code for window managers that don't have mouse/window movement shaping hotkeys of their own (e.g. fvwm). It makes the gnome window
managers almost useful. It should be portable to other X based OS's.
It comes with the usual preamble - use it at your own risk, if it eats your cat then it's not mine (or Sun's) fault.
#include <alloca.h>
#include <libgen.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#if defined(LINUX)
#include <string.h>
#include <stdint.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#include <X11/X.h>
#include <X11/Xlib.h>
static char *appname;
struct systeminfo {
int rootx;
int rooty;
int width;
int height;
int winx;
int winy;
Display *display;
Window rootwin;
Window undermouse;
XWindowAttributes childattr;
};
static char *actionhelp();
static void
usage(int exitcode)
{
(void) printf("usage: %s {<action> [+-]<valx>[%%] [+-]<valy>[%%] }+ \n",
appname);
(void) printf("\tif you use +- it is taken as a delta, otherwise it is"
" absolute\n");
(void) printf("Where action is one of %s\n", actionhelp());
(void) printf("\tFor example %s mm 0 0 would move the mouse to the "
"\n\ttop left of the screen\n", appname);
exit(exitcode);
}
static int
XError(Display *disp, XErrorEvent *code)
{
char buffer[2000];
XGetErrorText(disp, code->error_code, buffer, 1999);
(void) printf("Error: %s\n", buffer);
return (0);
}
static int isdelta(const char *value) {
return ((*value == '-') || (*value == '+'));
}
static int isperc(const char *value) {
return ((strrchr(value, '%') - value) == (strlen(value) - 1));
}
static int transform(const char *val, int start, int maxMetric) {
int av = atoi(val);
/*(void) printf("%s %d %d %d\n", val, av, start, maxMetric);*/
if (isdelta(val) && isperc(val))
return (start + (int)(maxMetric * av / 100));
if (isdelta(val))
return (start + av);
if (isperc(val))
return ((int)(maxMetric * av / 100));
return (av);
}
static void getxy(struct systeminfo *info, const char *xarg,
const char *yarg, int *xval, int *yval, uintptr_t offx,
uintptr_t offy) {
/*LINTED*/
*xval = transform(xarg, *((int *)((char *)info + offx)),
isperc(xarg) && isdelta(xarg) ? info->width :
WidthOfScreen(DefaultScreenOfDisplay(info->display)));
/*LINTED*/
*yval = transform(yarg, *((int *)((char *)info + offy)),
isperc(yarg) && isdelta(yarg) ? info->height :
HeightOfScreen(DefaultScreenOfDisplay(info->display)));
/* (void) printf("%d %d\n", *xval, *yval); */
}
static void MoveMouse(struct systeminfo *info, int xarg, int yarg) {
XWarpPointer(info->display, None, info->rootwin, 0, 0, 0, 0,
xarg, yarg);
}
static void ResizeWindow(struct systeminfo *info, int xarg, int yarg) {
XResizeWindow(info->display, info->undermouse, xarg, yarg);
}
static void MoveWindow(struct systeminfo *info, int xarg, int yarg) {
XMoveWindow(info->display, info->undermouse, xarg, yarg);
}
#define funtostring(FV) #FV, FV
static struct activity {
char *action;
char *helpstring;
void (*function)(struct systeminfo *, int, int);
uintptr_t offsetx;
uintptr_t offsety;
} activitylist[] = {
{ "mm", funtostring(MoveMouse),
offsetof(struct systeminfo, rootx),
offsetof(struct systeminfo, rooty) },
{ "rw", funtostring(ResizeWindow),
offsetof(struct systeminfo, width),
offsetof(struct systeminfo, height) },
{ "mw", funtostring(MoveWindow),
offsetof(struct systeminfo, winx),
offsetof(struct systeminfo, winy) },
{ NULL, NULL, NULL }
};
static char *actionhelp(void) {
static char *buffer = NULL;
char *stribo;
struct activity *ack = activitylist;
stribo = alloca(1024);
if (buffer != NULL)
return (buffer);
buffer = calloc(1, getpagesize());
while (ack->action != NULL) {
(void) sprintf(stribo, "%s(%s) ", ack->action, ack->helpstring);
(void) strcat(buffer, stribo);
ack++;
}
return (buffer);
}
extern Window XmuClientWindow(Display *, Window);
static void InitializeWinfoid(struct systeminfo *winfoid) {
unsigned int mask;
winfoid->rootwin = XDefaultRootWindow(winfoid->display);
XQueryPointer(winfoid->display, winfoid->rootwin,
&winfoid->rootwin, &winfoid->undermouse,
&winfoid->rootx, &winfoid->rooty,
&winfoid->winx, &winfoid->winy, &mask);
XGetWindowAttributes(winfoid->display, winfoid->undermouse,
&winfoid->childattr);
winfoid->winx = winfoid->childattr.x;
winfoid->winy = winfoid->childattr.y;
winfoid->undermouse = XmuClientWindow(winfoid->display,
winfoid->undermouse);
XGetWindowAttributes(winfoid->display, winfoid->undermouse,
&winfoid->childattr);
winfoid->width = winfoid->childattr.width;
winfoid->height = winfoid->childattr.height;
}
int
main(int argc, char **argv)
{
struct systeminfo winfoid;
int atarg;
int thisx, thisy;
char *disp;
appname = basename(strdup(argv[0]));
XSetErrorHandler(XError);
if ((argc < 3) || ((argc - 1) % 3)) usage(1);
disp = XDisplayName(NULL);
if (disp == NULL) disp = ":0.0";
winfoid.display = XOpenDisplay(disp);
if (winfoid.display == NULL) {
(void) fprintf(stderr, "Can't open display %s\n", disp);
exit(2);
}
InitializeWinfoid(&winfoid);
/* handle arguments */
for (atarg = 1; atarg < argc; atarg += 3) {
struct activity *atac = activitylist;
while (atac->action != NULL) {
if (strncmp(atac->action, argv[atarg], 2) == 0)
break;
atac++;
}
if (atac->action != NULL) {
getxy(&winfoid, argv[atarg+1], argv[atarg+2],
&thisx, &thisy, atac->offsetx, atac->offsety);
atac->function(&winfoid, thisx, thisy);
}
}
XCloseDisplay(winfoid.display);
return (0);
}
January 27, 2005 05:03 PM GMT
Permalink
fuser trickiness
I encountered this one a bit over a year ago while having a conversation with Ed in MPK (or is it a year and a half?). The fuser command is used to list the processes using a file system - fuser /home/bubba would list all the users of /home/bubba; and you can kill them too, using the -k option. So far so good.
What happens, though when you want to do something with the output?
haiiro[64i]~% fuser /home/bubba /home/bubba: 6780c 6760c 6758c 6756c 6502c 6422c 6404c 6368c 6332c 6331c 6330c 6322c 6308c 6301c 6206c 6081c 5951c 5879c 5756c 5251c 5247c 5201c 5092c 5004c 4992c 4987c 4985c 4982c 4980c 4968c 4952c 4920c 4672c 4080c 4079c 3990c 3989c 3987c 3985c 3983c 3981c 3979c 3975c 3973c 3969c 3963c 3943c 3939c 3937c 3935c 3898c 3896c 3893c 3891c 3882c 3880c 3836c 3834c 3831c 3769c 3726cit's a bit hard to parse? not so! What you can do is redirect stderr to /dev/null and magic happens
haiiro[64i]~% fuser /home/bubba 2>/dev/null 6781 6760 6758 6756 6502 6422 6404 6368 6332 6331 6330 6322 6308 6301 6206 6081 5951 5879 5756 5251 5247 5201 5092 5004 4992 4987 4985 4982 4980 4968 4952 4920 4672 4080 4079 3990 3989 3987 3985 3983 3981 3979 3975 3973 3969 3963 3943 3939 3937 3935 3898 3896 3893 3891 3882 3880 3836 3834 3831 3769No parse issues there. Then you can get full process information on each of the processes using a small bit of shell:
haiiro[64i]~% ps -o pid,args -p "$(fuser /home/bubba 2>/dev/null)" PID COMMAND 6206 /usr/openwin/bin/xterm -geom 80x25 -e /bin/zsh 3943 /usr/lib/evolution/1.4/evolution-alarm-notify --sm-config-prefix /evolution-ala 3939 nautilus --sm-config-prefix /nautilus-udaGgf/ --sm-client-id 11819cee2200010909 3935 metacity --sm-save-file 1106677632-2610-3195804027.ms 3880 /bin/ksh /usr/dt/config/Xsession2.jds 3834 /usr/dt/bin/sdt_shell -c unset DT; DISPLAY=:0; /usr/dt/bin/dt : : :Just what the doctor ordered for a sysadmin. January 27, 2005 10:38 AM GMT Permalink