Subject: FVWM: fvwm & xlock interaction

From: Philippe Meunier <[email-masked]>
Date: Thu, 16 Aug 2001 20:04:28 -0400 (EDT)

Hi,

I'm writing my own xlock program (yes, I have too much time on my
hands, and I like to play) and I came across some strange interaction
between fvwm and my program. I've appended my .fvwm2rc and my program
below. It's fvwm 2.4.0 on a Solaris 5.6 machine.

What happens: as you can see, I have an fvwm keyboard shorcut (^F12)
to start my xlock program. When I use the keyboard shortcut and the
keyboard focus is in a window, I get an "XGrabKeyboard failed with
code 1" error message from my program on my console (error code 1
being X11's "AlreadyGrabbed"), most of the time. I also get an
"XGrabPointer failed with code 1" error message most of the time when
I try to start my xlock program the same way (i.e. with the focus in a
window), but through a menu (not shown in my .fvwm2rc here). I say
"most of the time", because from time to time my program actually
works and locks the display... It also always works when no window has
the focus and I use a keyboard shortcut or a menu to start it, and it
also always works when I start it from the command line (regardless of
whether any window has the focus at the time it's started).

Now, since I'm using fvwm's SloppyFocus, I wasn't too surprised to get
an AlreadyGrabbed error when trying to grab the keyboard while a
window had the focus, since I guess fvwm implements that feature by
grabbing the keyboard itself. I'm already less sure about why fvwm
would grab the mouse while openning a menu (I haven't read fvwm's
code, so I might be wrong...) but it seems to be what it does. It
would also explain why my program works when no window has the
focus. I have no idea, then, why, when I use my program from the
command line, it works regardless of whether any window has the focus
or not. I also have no idea why it does actually work from time to
time when some window has the focus and I use a keyboard shortcut or a
menu. I also tried running fvwm without using SloppyFocus, but
basically got the same result: as soon as a window has the focus, my
program doesn't work (most of the time, but not always) if I start it
from fvwm.

The other funny thing is that the system-provided xlock works every
time, regardless of how I start it or whether any window has the
focus.

So I guess I'm either doing something wrong in my program, or I'm
missing something somewhere. Does somebody have a clue ? Any help will
be appreciated...

I haven't actually subscribed to the list, so please put me in copy if
you reply.

Thanks a lot,

Philippe (and yes, I use goto)

============================================================
Style "*" SmartPlacement, ActivePlacement, SloppyFocus
Style "*" NoPPosition
Style "*" BorderWidth 2, HandleWidth 2, Icon unknown1.xpm

Style "Fvwm*"      NoTitle, NoHandles, Sticky, WindowListSkip, BorderWidth 0
Style "xbiff"      NoTitle, NoHandles, Sticky, WindowListSkip, BorderWidth 0

Style "*" MWMFunctions
Style "*" HintOverride
Style "*" MWMDecor

EdgeScroll 0 0
EdgeResistance 10000 0

DeskTopSize 3x2

AddToFunc "Move-or-RaiseLower" "M" Move
+              "C" RaiseLower

AddToFunc "Move-or-Iconify" "M" Move
+              "C" Iconify

AddToMenu "Utilities" "xterm" Exec exec xterm -e /bin/bash > /dev/console 2>&1
+              "" Nop
+              "identity" Module FvwmIdent
+              "refresh" Refresh
+              "destroy" Destroy

Mouse 1		R   	A       Popup "Utilities"
Mouse 1		FS	A	Resize
Mouse 1		T	A	Function "Move-or-RaiseLower"
Mouse 1		I	A	Function "Move-or-Iconify"
Mouse 1         W       M       Function "Move-or-RaiseLower"

Mouse 2		FSTI	A	Function "Move-or-Iconify"
Mouse 2		W	M	Function "Move-or-Iconify"

Key Left	A	C	Scroll -100 0
Key Right	A	C	Scroll +100 +0
Key Up		A	C	Scroll +0   -100
Key Down	A	C	Scroll +0   +100

Key Left	R	A	Scroll -100 0
Key Right	R	A	Scroll +100 +0
Key Up		R	A	Scroll +0   -100
Key Down	R	A	Scroll +0   +100

Key F1		A	A	RaiseLower
Key F1		A	C	Iconify
Key F2		A	A	Maximize 0 100
Key F3		A	A	Maximize 100 0
Key F4		A	A	Maximize 100 100
Key F5		A	A	Maximize 200 200
Key F9		A	A	Exec exec xterm > /dev/console 2>&1
Key F10		A	A	Module	FvwmIdent
Key F11		A	A	Refresh
Key F12		A	C	Exec exec xlock > /dev/console 2>&1
Key F12		A	M	Destroy

============================================================
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <string.h>

#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>

extern char *crypt(char *key, char *salt);

int main(void)
{
    Display *display;
    XEvent event;
    char input_passwd[9];
    char keysym_buf[3];
    int input_passwd_pos, keysym_buf_len, i;
    struct passwd *current_passwd;
    int exit_value = 0;
    int error_code;

    /* this doesn't work if the system is using shadow passwds */
    if (!(current_passwd = getpwuid(getuid()))) {
	fprintf(stderr, "unknown user: %d\n", (int) getuid());
	exit_value = -1;
	goto final_exit;
    }
    if ((display = XOpenDisplay("")) == NULL) {
	char *pt;

	pt = getenv("DISPLAY");
	if (pt)
	    fprintf(stderr, "XOpenDisplay: displaylay %s not found\n", pt);
	else
	    fprintf(stderr, "XOpenDisplay: DISPLAY not set\n");
	exit_value = -1;
	goto final_exit;
    }
    /* grab mouse */
    if ((error_code = XGrabPointer(display, XDefaultRootWindow(display),
				   False, 0, GrabModeAsync, GrabModeAsync,
				   None, None, CurrentTime))
	!= GrabSuccess) {
	fprintf(stderr, "XGrabPointer failed with code %d\n", error_code);
	exit_value = -1;
	goto close_and_exit;
    }
    /* grab keyboard */
    if ((error_code = XGrabKeyboard(display, XDefaultRootWindow(display),
				    False, GrabModeAsync, GrabModeAsync,
				    CurrentTime))
	!= GrabSuccess) {
	fprintf(stderr, "XGrabKeyboard failed with code %d\n", error_code);
	exit_value = -1;
	goto ungrab_pointer_and_exit;
    }
    do {
	input_passwd_pos = 0;
	do {
	    if (XNextEvent(display, &event) != 0) {
		fprintf(stderr, "XNextEvent failed\n");
		exit_value = -1;
		goto ungrab_all_and_exit;
	    }
	    if (event.type == KeyPress) {
		keysym_buf_len = XLookupString((XKeyEvent *) & event, keysym_buf,
					       3, NULL, NULL);
		for (i = 0; i < keysym_buf_len; i++) {
		    switch (keysym_buf[i]) {
		    case 8:	/* ^H */
		    case 127:	/* DEL */
			if (input_passwd_pos > 0)
			    input_passwd_pos--;
			break;
		    case 10:	/* ^J */
		    case 13:	/* ^M */
			input_passwd[input_passwd_pos++] = 0;
			break;
		    case 21:	/* ^U */
			input_passwd_pos = 0;
			break;
		    default:
			if (input_passwd_pos == 8)
			    input_passwd[input_passwd_pos++] = 0;
			else
			    input_passwd[input_passwd_pos++] = keysym_buf[i];
		    }
		}
	    }
	} while (!(input_passwd_pos && input_passwd[input_passwd_pos - 1] == 0));
    } while (strcmp(current_passwd->pw_passwd,
		    crypt(input_passwd, current_passwd->pw_passwd)));

  ungrab_all_and_exit:
    XUngrabKeyboard(display, CurrentTime);
  ungrab_pointer_and_exit:
    XUngrabPointer(display, CurrentTime);
  close_and_exit:
    XCloseDisplay(display);
  final_exit:
    return exit_value;
}
--
Visit the official FVWM web page at <URL: http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm" in the body of a
message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 17 Aug 2001 09:53:20 +0200

On Thu, Aug 16, 2001 at 08:04:28PM -0400, Philippe Meunier wrote:
> code, so I might be wrong...) but it seems to be what it does.

You can't even prevent that the keyboard or the pointer is grabbed
in X if you want that input.  When you click in a window (or press
a key for that matter) that takes clicks (or key presses), that
window grabs the mouse (keyboard) automatically.  This is a
feature of X to prevent that other applications can grab the
pointer (keyboard) in the time before the click and the moment the
application would grab the pointer itself.  Key and button actions
in fvwm are often triggered before the passive grab is released,
i.e. while the button (key) is still depressed.

> It
> or not.

That depends on the focus model as well as on the bindings you
have on the window.

> I also have no idea why it does actually work from time to
> menu.

Because the grab has already been released when the program makes
its call.

> I also tried running fvwm without using SloppyFocus, but

This would probably work if you disable the raise-on-click feature
of the focus model:

For 2.3.x or later:

  Style * MouseFocusClickRaisesOff

For 2.2.x:

  GlobalOpts MouseFocusClickDoesntRaise

Anyway, there is a simple solution that is independent of the
window manager:  simply retry grabbing the pointer/keyboard after
a few milliseconds.  Fvwm itself always retries this for up to
five seconds before finally giving up.

> I haven't actually subscribed to the list, so please put me in copy if

Bye

Dominik ^_^  ^_^

-- 
Dominik Vogt, email: [email-masked]
LifeBits Aktiengesellschaft, Albrechtstr. 9, D-72072 Tuebingen
fon: ++49 (0) 7071/7965-0, fax: ++49 (0) 7071/7965-20
--
Visit the official FVWM web page at <URL: http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm" in the body of a
message to [email-masked].
To report problems, send mail to [email-masked].