[Xlib] Force Raise/Map/Focus a given Window
Andrew Troschinetz
ast at arlut.utexas.edu
Mon Aug 11 12:25:30 PDT 2008
Hi,
I'm trying to force raise/present/focus a window in Gnome/Metacity
2.18 (RHEL5) but it seems like a "don't steal focus" feature is
preventing me from doing so. The following code works in Gnome/
Metacity 2.8 (RHEL4), but note quite in RHEL5.
What I mean is: If the window is minimized (unmapped) then the
following code will map, raise, and focus the window correctly in
either RHEL4 or RHEL5. But in RHEL5 only, if the window currently
doesn't have focus, but is mapped and raised (say another window has
focus and is ontop of the window I want to present), then the
following code only results in the taskbar item for the window blinking.
So my question is, is there a problem in my code? Is there a known
workaround for this, some Xlib function I should be calling here? Or
does anyone happen to know off the top of their head if this is a new
feature in RHEL5 that can be easily disabled?
void present_window(Display* display, Window window)
{
// Get current hidden/unhidden state of window
XWindowAttributes atts;
XGetWindowAttributes (display, window, &atts);
bool hidden = (atts.map_state == IsUnmapped);
// If hidden: map, raise, and focus the window.
// The window has to be mapped before we can call XSetInputFocus() on
it,
// otherwise we will likely get BadMatch errors.
if (hidden)
{
// Save current even mask
unsigned long old_mask = atts.your_event_mask;
unsigned long wanted_mask = StructureNotifyMask;
// Add wanted mask to current mask
XSelectInput (display, window, old_mask | wanted_mask);
// Request to raise and map window
XMapRaised (display, window);
// Wait for window to be mapped before going on,
// but only wait timeout seconds before giving up
const double timeout = 5;
XEvent e;
std::vector<XEvent> events;
boost::timer time;
do
{
if (XCheckWindowEvent (display, window, wanted_mask, &e))
{
events.push_back (e);
}
} while (e.type != MapNotify && time.elapsed () < timeout);
// Determine if we unhid the window or not
hidden = (e.type != MapNotify);
// Push back the events we stole
std::vector<XEvent>::iterator i = events.begin ();
for (; i != events.end (); ++i)
{
XPutBackEvent (display, &(*i));
}
// Revert the mask to previous state
XSelectInput (display, window, old_mask);
if (!hidden)
{
XSetInputFocus (display, window, RevertToParent, CurrentTime);
}
}
else
{
XRaiseWindow (display, window);
XSetInputFocus (display, window, RevertToParent, CurrentTime);
}
}
--
Andrew Troschinetz
Applied Research Laboratories
More information about the xorg
mailing list