window only gets events when in focus - Xwindows
This is a discussion on window only gets events when in focus - Xwindows ; Hi,
In my program, I open an X11 window in a thread, then draw on it from
another using Cairo. The window is updated using the XDamage
extension.
My problem is that the window only gets DamageNotify and even
DestroyNotify ...
-
window only gets events when in focus
Hi,
In my program, I open an X11 window in a thread, then draw on it from
another using Cairo. The window is updated using the XDamage
extension.
My problem is that the window only gets DamageNotify and even
DestroyNotify (so this is not something specific to the XDamage
extension) events when in focus. For example, I send the window a
destroy event, but it is not destroyed until I select it with Alt-Tab
in my window manager.
I would appreciate advice on what I should do. The program is as
follows:
#include
#include
#include
#include
#include
#include
#include
#define TRUE 1
#define FALSE 0
#define DEBUG
#define ERROR_OUTOFMEMORY 1
#define ERROR_OPENDISPLAY 2
#define ERROR_XDAMAGEMISSING 3
#define RETURN_ERROR(err) { free(xc); return (err); }
typedef struct {
unsigned int width;
unsigned int height;
Display *display;
int screen;
Window window;
Pixmap pixmap;
GC gc;
} xlib_context_data;
int
create_xlib_context(char *display_name,
unsigned int width,
unsigned int height,
xlib_context_data **xc_pointer,
cairo_t **context_pointer)
{
Window root; /* root window */
Visual *visual; /* visual */
int depth; /* depth */
XEvent ev; /* event */
cairo_surface_t *surface; /* surface */
Atom prots[1];
int damage_event, damage_error; /* for querying extension */
Damage damage; /* damage notification handler */
XDamageNotifyEvent *dev;
cairo_t *context;
XSizeHints *hints;
xlib_context_data *xc = (void *)NULL;
/* initialize pointer with NULL */
*xc_pointer = NULL;
/* allocate xlib_context */
xc = malloc( sizeof(xlib_context_data) );
if (!xc)
RETURN_ERROR(ERROR_OUTOFMEMORY);
/* save width and height */
xc->width = width;
xc->height = height;
/* open display, get screen, root, visual, and depth */
xc->display = XOpenDisplay(display_name);
if (!xc->display)
RETURN_ERROR( ERROR_OPENDISPLAY );
xc->screen = DefaultScreen(xc->display);
root = RootWindow(xc->display, xc->screen);
visual = DefaultVisual(xc->display, xc->screen);
depth = DefaultDepth(xc->display, xc->screen);
/* check X damage extension */
if (!XDamageQueryExtension( xc->display, &damage_event,
&damage_error ))
RETURN_ERROR( ERROR_XDAMAGEMISSING );
/* create window and pixmap */
xc->window = XCreateSimpleWindow(xc->display, root, 0, 0, xc-
>width, xc->height, 0, 0,
WhitePixel (xc->display, xc->screen));
xc->pixmap = XCreatePixmap(xc->display, xc->window, xc->width, xc-
>height, depth);
/* size hints */
hints = XAllocSizeHints();
hints->min_width = width;
hints->min_height = height;
hints->max_width = width;
hints->max_height = height;
hints->flags = PMinSize | PMaxSize;
XSetWMNormalHints(xc->display, xc->window, hints);
XFree(hints);
/* graphics context */
xc->gc = XCreateGC(xc->display, xc->pixmap, 0, 0);
/* setup damage notification */
damage = XDamageCreate( xc->display, xc->pixmap,
XDamageReportNonEmpty );
/* select events, map window */
XSelectInput( xc->display, xc->window,
ExposureMask | StructureNotifyMask | KeyPressMask |
KeyReleaseMask );
/* handle window closing */
prots[0] = XInternAtom(xc->display, "WM_DELETE_WINDOW", FALSE);
XSetWMProtocols(xc->display, xc->window, prots, 1);
/* map window */
XMapWindow(xc->display, xc->window);
/* allocate structure, create cairo surface */
surface = cairo_xlib_surface_create( xc->display, xc->pixmap,
visual,
width, height );
context = cairo_create(surface);
cairo_surface_destroy(surface);
/* set pointers before we start loop */
#ifdef DEBUG
FILE *debug = fopen("/tmp/debug","w");
fprintf(debug, "before setting: xc_pointer=%p *xc_pointer=%p
context_pointer=%p *context_pointer=%p\n", xc_pointer, *xc_pointer,
context_pointer, *context_pointer);
#endif /* DEBUG */
*xc_pointer = xc;
*context_pointer = context;
#ifdef DEBUG
fprintf(debug, "xc=%p=%p context=%p=%p\n", xc, *xc_pointer,
context, *context_pointer);
fprintf(debug, "damage_event=%d, XDamageNotify=%d\n",
damage_event, XDamageNotify);
fflush(debug);
#endif /* DEBUG */
/* main loop */
for (;
{
XNextEvent(xc->display, &ev);
#ifdef DEBUG
fprintf(debug, "event of type %d\n", ev.type);
fflush(debug);
#endif /* DEBUG */
if (ev.type == (damage_event + XDamageNotify)) {
dev = (XDamageNotifyEvent *) &ev;
#ifdef DEBUG
fprintf(debug, "damage event received\n");
fflush(debug);
#endif /* DEBUG */
/* !!!! should only update the rectangle */
XCopyArea(xc->display, xc->pixmap, xc->window, xc->gc, 0, 0,
xc->width, xc->height, 0, 0);
XDamageSubtract( xc->display, dev->damage, None, None );
} else {
switch (ev.type) {
case Expose:
#ifdef DEBUG
fprintf(debug, "expose event received\n");
fflush(debug);
#endif /* DEBUG */
if (ev.xexpose.count > 0)
break;
/* !!!! should only update the rectangle */
XCopyArea(xc->display, xc->pixmap, xc->window, xc->gc, 0, 0,
xc->width, xc->height, 0, 0);
break;
case DestroyNotify:
case ClientMessage:
/* cleanup & close */
XDamageDestroy( xc->display, damage );
XDestroyWindow( xc->display, xc->window );
XCloseDisplay( xc->display );
#ifdef DEBUG
fclose(debug);
#endif /* DEBUG */
return(0);
default:
break;
}
}
}
}
void close_xlib_context(xlib_context_data *xc)
{
XEvent ev;
ev.type = DestroyNotify;
XSendEvent(xc->display, xc->window, FALSE, 0, &ev);
}
Thanks,
Tamas
-
Re: window only gets events when in focus
"Tamas" wrote in message
news:1181657669.529656.94760@i13g2000prf.googlegro ups.com...
> Hi,
>
> In my program, I open an X11 window in a thread, then draw on it from
> another using Cairo. The window is updated using the XDamage
> extension.
>
> My problem is that the window only gets DamageNotify and even
> DestroyNotify (so this is not something specific to the XDamage
> extension) events when in focus. For example, I send the window a
> destroy event, but it is not destroyed until I select it with Alt-Tab
> in my window manager.
>
> I would appreciate advice on what I should do. The program is as
> follows:
> (snip)
>
> XSelectInput( xc->display, xc->window,
> ExposureMask | StructureNotifyMask | KeyPressMask |
> KeyReleaseMask );
>
> (snip)
Try adding SubstructureNotifyMask to get DestroyNotify events.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Aero Stability and Controls Computing
-
Re: window only gets events when in focus
On Jun 12, 8:17 pm, "Fred Kleinschmidt"
wrote:
> "Tamas" wrote in message
>
> news:1181657669.529656.94760@i13g2000prf.googlegro ups.com...
>
>
>
> > Hi,
>
> > In my program, I open an X11 window in a thread, then draw on it from
> > another using Cairo. The window is updated using the XDamage
> > extension.
>
> > My problem is that the window only gets DamageNotify and even
> > DestroyNotify (so this is not something specific to the XDamage
> > extension) events when in focus. For example, I send the window a
> > destroy event, but it is not destroyed until I select it with Alt-Tab
> > in my window manager.
>
> > I would appreciate advice on what I should do. The program is as
> > follows:
> > (snip)
>
> > XSelectInput( xc->display, xc->window,
> > ExposureMask | StructureNotifyMask | KeyPressMask |
> > KeyReleaseMask );
>
> > (snip)
>
> Try adding SubstructureNotifyMask to get DestroyNotify events.
> --
> Fred L. Kleinschmidt
> Boeing Associate Technical Fellow
> Aero Stability and Controls Computing
Thanks, but it didn't help. I realize my previous example was too
complicated for people to look at it, so I simplified. But it still
doesn't work: I start create_window in a thread, then issue
close_window, which only takes effect after I focus and click on the
window title bar (merely making the window active doesn't work). I am
using SBCL's threads.
#include
#include
#include
#include
#include
typedef struct {
Display *display;
Window window;
} window_data;
/
************************************************** *************************
* create_window -- create window, save it in wd_pointer, start event
loop *
************************************************** *************************/
int
create_window(char *display_name,
window_data **wd_pointer)
{
Window root; /* root window */
Visual *visual; /* visual */
int depth; /* depth */
XEvent ev; /* event */
int screen; /* screen */
GC gc;
Atom prots[1];
window_data *wd = malloc( sizeof(window_data) ); /* allocate
window_data */
/* open display, get screen, root, visual, and depth */
wd->display = XOpenDisplay(display_name);
screen = DefaultScreen(wd->display);
root = RootWindow(wd->display, screen);
visual = DefaultVisual(wd->display, screen);
depth = DefaultDepth(wd->display, screen);
wd->window = XCreateSimpleWindow(wd->display, root, 0, 0, 100,
100, 0, 0,
WhitePixel (wd->display, screen));
/* graphics context */
gc = XCreateGC(wd->display, wd->window, 0, 0);
/* select events, map window */
XSelectInput( wd->display, wd->window,
ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask
|
SubstructureNotifyMask );
/* handle window closing */
prots[0] = XInternAtom(wd->display, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(wd->display, wd->window, prots, 1);
XMapWindow(wd->display, wd->window); /* map window */
*wd_pointer = wd; /* set pointers before we start loop */
/* main loop */
for (;
{
XNextEvent(wd->display, &ev);
switch (ev.type) {
case Expose:
if (ev.xexpose.count > 0)
break;
/* do nothing */
break;
case DestroyNotify:
case ClientMessage:
/* cleanup & close */
XDestroyWindow( wd->display, wd->window );
XCloseDisplay( wd->display );
return(0);
default:
break;
}
}
}
void close_window(window_data *wd)
{
XEvent ev;
ev.type = DestroyNotify;
XSendEvent(wd->display, wd->window, 0, 0, &ev);
}
-
Re: window only gets events when in focus
On Jun 13, 10:24 am, Tamas wrote:
> Thanks, but it didn't help. I realize my previous example was too
> complicated for people to look at it, so I simplified. But it still
> doesn't work: I start create_window in a thread, then issue
> close_window, which only takes effect after I focus and click on the
> window title bar (merely making the window active doesn't work). I am
> using SBCL's threads.
I think I am on my way to a solution. The events are received when I
call XSync or XFlush. I understand the need to call XFlush after
using XSendEvent, but when I am drawing onto the pixmap, I thought
that the XDamage extension wouldn't only generate the events but flush
them out too. How can I make it do that?
Thanks,
Tamas