I wrote the following code to detect when a window is created on the screen by another application (not by my code):
Display* display = XOpenDisplay(":0");
XSetWindowAttributes attributes;
attributes.event_mask = SubstructureNotifyMask | StructureNotifyMask;
Window win = XDefaultRootWindow(display);
XChangeWindowAttributes(display, win, CWEventMask, &attributes);
while (1) {
XEvent event;
XNextEvent(display, &event);
if (event.type == CreateNotify)
puts("create Notify event occured\n");
}
The code basically works, however, I noticed that, when I start an application (e.g. terminal) the CreateNotify event seems to be fired multiple times. Can anybody explain why? I would have expected that CreateNotify will only be fired once for every started application/window. How do I have to modify the code to achieve this?
The events are for child windows. Per the Xlib Programming Manual, "Creating any children ... generates an event." A typical X application includes numerous child windows, and you're seeing each of them.
When you get the event, check event.xcreatewindow.parent (XEvent is a union per the reference). If that is win, the root window, you have a top-level window. Otherwise, you have a child window. Try:
if ( (event.type == CreateNotify) && (event.xcreatewindow.parent == win) )
puts("top-level create Notify event occured\n");
Related
I am trying to exit a window i've third DestroyWindow() and SendMessage() with WM_CLOSE and CloseWindow() the first two don't work and CloseWindow(); only minimizes it!
Example code of what i'm trying to do:
int main()
{
HWND curwind;
char ccurwind[256];
HWND newwind;
HWND wind2;
Sleep(1000);
printf("Destroying in 5...\n");
Sleep(1000);
printf("Destroying in 4...\n");
Sleep(1000);
printf("Destroying in 3...\n");
Sleep(1000);
printf("Destroying in 2...\n");
Sleep(1000);
printf("Destroying in 1...\n");
curwind = GetForegroundWindow();
GetWindowTextA(curwind, ccurwind, 256);
//DestroyWindow(curwind);
if (DestroyWindow(curwind) == 0) {
printf("Failed with error: %s", GetLastError());
}
else {
printf("\nDestroyed %s", ccurwind);
}
getch();
return 0;
}
So basically close the window but not the process
example scenario:
I open a new tab on google in a new window this program will close that window but not the whole process. Is this possible and if so what function would i use?
Only the thread that owns the window is allowed to call DestroyWindow. SendMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0) is the same as closing the window with the system menu but it ultimately just sends WM_CLOSE.
A window can ignore WM_CLOSE and there is not much you can do about that.
If the window is in a process with a higher integrity level than you then UIPI will block your message.
the function: DestroyWindow() should do the job.
From: 'https://msdn.microsoft.com/en-us/library/windows/desktop/ms632682(v=vs.85).aspx'
Destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus from it. The function also destroys the window's menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain).
If the specified window is a parent or owner window, DestroyWindow automatically destroys the associated child or owned windows when it destroys the parent or owner window. The function first destroys child or owned windows, and then it destroys the parent or owner window.
DestroyWindow also destroys modeless dialog boxes created by the CreateDialog function.
I have a somewhat hackish utility that sends keystrokes to a window, using SendInput(). That works just fine, however, the target window needs to be a foreground window, so before sending anything, the utility needs to call SetForegroundWindow(). This is annoying from the user's perspective, as the target window flashes to the top (even though the utility immediately switches back to the recent active window, so that the user can continue work).
Is there a way to focus a window, without changing z-order? I realise that it is not a common use case, as it would be extremely frustrating under normal conditions for the user to have a background window active, where they might not even see what they are typing. I tried using both SetFocus() and SetWindowPos() with SWP_NOZORDER, but neither of them actually activates the window.
Note that the window I'm trying to activate is not owned by the calling thread. Also note that I can't use SendMessage() as the keystroke is a CTRL+NUMPAD3 combination and the target window will not react to separate WM_KEYDOWN / WM_KEYUP events, I've tried. It might be relevant that I'm trying to use this on Windows 7.
My code so far is:
HWND h_target = FindWindow(...);
INPUT p_input[2] = {0};
p_input[0].type = INPUT_KEYBOARD;
p_input[0].ki.wVk = VK_CONTROL;
p_input[1].type = INPUT_KEYBOARD;
p_input[1].ki.wVk = VK_NUMPAD3;
// prepare input
HWND h_act = GetForegroundWindow();
// remember this
SetForegroundWindow(h_target); // works
//SetWindowPos(h_target, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // does not work
// activate the target window first
SendInput(2, p_input, sizeof(INPUT));
// send the keystrokes
p_input[0].ki.dwFlags |= KEYEVENTF_KEYUP;
p_input[1].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(2, p_input, sizeof(INPUT));
// don't forget to release the keys
SetForegroundWindow(h_act);
// put the active window back
What is the proper way to wait until an X11 window is mapped and viewable? Precisely, I want to wait until I can safely call XSetInputFocus() without running into any risks of the X server backfiring with the following error:
// X Error of failed request: BadMatch (invalid parameter attributes)
// Major opcode of failed request: 42 (X_SetInputFocus)
Currently this error happens quite often, especially on slow X servers or when trying to open a new window right after having changed the monitor resolution using libXrandr.
I already have a solution for this problem but it is pretty hacky because it polls the window attribute so I'd like to know whether or not there is a cleaner version.
Here is my current approach:
static Bool predicate(Display *display, XEvent *ev, XPointer arg)
{
return(ev->type == MapNotify);
}
static void waitmapnotify(struct osdisplayinfo *osd)
{
XEvent ev;
XWindowAttributes xwa;
XPeekIfEvent(osd->display, &ev, predicate, NULL);
do {
XGetWindowAttributes(osd->display, osd->window, &xwa);
usleep(1);
} while(xwa.map_state != IsViewable);
}
This code works fine but it is hacky so I'm putting it up for debate here - just in case there is a cleaner way of doing this.
Select SubstructureNotifyMask on the root window. You should get an event each time a top-level window is mapped, unmapped, moved, raised, resized etc. These are the events that potentially change visibility of top-level windows. This program prints a message whenever such an event happens:
#include <X11/Xlib.h>
#include <stdio.h>
int main ()
{
Display* d = XOpenDisplay(0);
int cnt = 0;
XEvent ev;
XSelectInput (d, RootWindow(d, DefaultScreen(d)), SubstructureNotifyMask);
while (1)
{
XNextEvent(d, &ev);
printf ("Got an event %d!\n", cnt++);
// <----- do your XGetWindowAttributes(...) check here
}
}
Note that you may not get events about your own windows getting mapped. This is because the WM is likely to reparent top-level windows to be children not of the root, but of intermediate decoration windows.
There are two ways to cope with the situation:
Check if your window parent, the parent of the parent, ... etc is the mapped window of the event.
Add XSelectInput (d, yourwindow, StructureNotifyMask); to the mix.
Note the first select has SubstructureNotifyMask and the second one StructureNotifyMask, a different mask.
As far as I know X11 lib does not expose any callback mechanics for the X11 Event handling. (you can easily build your own once you understand the event filtering model)
You might want to loop on the X11 event queue as I guest this should be more efficient being designed for that purpose. Moreover you can configure the events filter, so that you get only the events that are of interest for your specific window.
A useful (though dated) link might be:
Linux Journal X11 Tutorial Check page two for an example on installing filters and getting events from the X11 queue.
My WndProc isn't seeing mouse-up notifications when I click with a modifier key (shift or control) pressed. I see them without the modifier key, and I see mouse-down notifications with the modifier keys.
I'm trying to track user actions in a component I didn't write, so I'm using the Windows Forms NativeWindow wrapper (wrapping the component) to get Windows messages from the WndProc() method.
I've tried tracking the notifications I do get, and I the only clue I see is WM_CAPTURECHANGED. I've tried calling SetCapture when I receive the WM_LBUTTONDOWN message, but it doesn't help.
Without modifier (skipping paint, timer and NCHITTEST messages):
WM_PARENTNOTIFY
WM_MOUSEACTIVATE
WM_MOUSEACTIVATE
WM_SETCURSOR
WM_LBUTTONDOWN
WM_SETCURSOR
WM_MOUSEMOVE
WM_SETCURSOR
WM_LBUTTONUP
With modifier (skipping paint, timer and NCHITTEST messages):
WM_KEYDOWN
WM_PARENTNOTIFY
WM_MOUSEACTIVATE
WM_MOUSEACTIVATE
WM_SETCURSOR
WM_LBUTTONDOWN
WM_SETCURSOR (repeats)
WM_KEYDOWN (repeats)
WM_KEYUP
If I hold the mouse button down for a long time, I can usually get a WM_LBUTTONUP notification, but it should be possible to make it more responsive..
Edit: I've tried control-clicking outside of the component of interest and moving the cursor into it before releasing the mouse button, and then I do get a WM_LBUTTONUP notification, so it looks like the component is capturing the mouse on mouse-down. Is there any way to receive that notification when another window has captured the mouse?
Thanks.
Frequently, when the mouse is clicked down on a (native) windows control, some kind of modal tracking loop is entered to manage the "drag" operation. During the duration of the modal loop messages are directly extracted from the message queue and processed - the mouse up notification would be one of the terminating conditions for the modal loop and thus typically consumed without being dispatched.
Can you click elsewhere on the desktop, move the mouse over the window and release and see the click? That would indicate some kind of modal code is being triggered on mouse-down messages.
I can think of four ways you can possibly get around this problem.
Find out what sort of drag operation the control supports - and disable it. Hopefully if the built in WindowProc knows that no modal drags are allowed it won't enter a modal loop.
Prevent the WindowProc finding out about the modal drag: i.e. intercept AND DON'T PASS ON any WM_LBUTTONDOWN messages to the next Windowproc in the chain.
Install a message hook using SetWindowsHookEx.
All these solutions are very windows API. No idea how they translate in the managed environment.
Within your handler you need to check the WPARAM key when you receive a WM_LBUTTONUP message.
http://msdn.microsoft.com/en-us/library/ms645608%28VS.85%29.aspx
If the component captures mouse messages, the WM_LBUTTONUP message might bypass your wrapper and go directly to the component.
Modifier and navigation keys are reserved for the OS's internal use by default. The default keyboard handler interprets them and generates appropriate messages based on them as needed. If a control wants to act on them directly, it needs to handle the WM_GETDLGCODE message, optionally with a result that includes the appropriate DLGC_WANT... flags, such as DLGC_WANTALLKEYS and DLGC_WANTARROWS, so the keys are delivered to the message queue as normal messages (for instance, DLGC_WANTALLKEYS will generate WM_KEYDOWN/UP messages).
Use Application.AddMessageFilter to add a handler to the native message pump. Something like this:
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
private class ZoomGestureHandler : IMessageFilter
{
private const UInt32 WM_MOUSEWHEEL = 0x20A;
private const UInt32 MK_CONTROL = 0x08;
private readonly ImageListView _target;
public ZoomGestureHandler(ImageListView target)
{
_target = target;
}
public bool PreFilterMessage(ref Message m)
{
if (m.Msg != WM_MOUSEWHEEL)
{
// Not a mouse wheel message
return false;
}
int wheelDelta = HiWord(m.WParam.ToInt32());
int keyState = LoWord(m.WParam.ToInt32());
// Mouse wheel scrolled while the Control key was down
if ((wheelDelta != 0) && (MK_CONTROL == keyState))
{
// Hit test the mouse location
int xPos = LoWord(m.LParam.ToInt32());
int yPos = HiWord(m.LParam.ToInt32());
Point controlLocation = _target.Parent.PointToScreen(_target.Location);
if ((xPos >= controlLocation.X) && (xPos < (controlLocation.X + _target.Width))
&& (yPos >= controlLocation.Y) && (yPos < (controlLocation.Y + _target.Height)))
{
// Determine whether to zoom in or out
if (wheelDelta > 0)
{
_target.ViewModel.TryZoomIn();
}
if (wheelDelta < 0)
{
_target.ViewModel.TryZoomOut();
}
}
}
return false;
}
private static int HiWord(int number)
{
if ((number & 0x80000000) == 0x80000000)
return (number >> 16);
return (number >> 16) & 0xffff;
}
private static int LoWord(int number)
{
return number & 0xffff;
}
}
That sample isn't specific to your particular goal, but you can modify it to suit. That just happened to be one I've written recently.
I want to monitor all the open windows under X11. Currently, I'm doing this as follows:
Initially walking the whole tree by recursively calling XQueryTree from the root window
Listening for substructure changes on the whole desktop: XSelectInput( display, root_window, SubstructureNotifyMask | PropertyChangeMask )
Handling all MapNotify, UnmapNotify and DestroyNotify events, updating my own list of windows in the process
I'm mainly worried about point 1. During the recursion, XQueryTree will be called multiple times. Is there any way to ensure that the tree does not change in the meantime? In other words, to get a 'snapshot' of the whole tree at one point in time?
Also, I've noticed that under some X11 systems, not all events arrive correctly. For example, when opening a new window on the desktop, MapNotify for that window may never arrive at my monitoring application. How can this be? Is it possible that it is thrown away before arriving?
Update:
I've written a small program that will monitor X events on the root window (see below). Now, when I run this program and start and quit xcalc, I get the following output:
Reparented: 0x4a0005b to 0x1001e40
Mapped : 0x1001e40
Destroyed : 0x1001e40
That's it. I'm never notified of the real window (0x4a0005b) being destroyed. Not even of it being mapped! Can anyone tell me why not? Does SubStructureNotifyMask only cause events of direct subwindows to be sent instead of the whole subtree?
By the way, this apparently does not happen when Compiz is running. Then no reparenting is done:
Mapped : 0x4a0005b
Mapped : 0x4e00233
Destroyed : 0x4a0005b
Destroyed : 0x4e00233
Monitoring program source:
#include <X11/Xlib.h>
#include <cstdio>
int main()
{
Display *display;
Window rootwin;
display = XOpenDisplay( NULL );
rootwin = DefaultRootWindow( display );
XSelectInput( display, rootwin, SubstructureNotifyMask );
XEvent event;
while ( 1 ) {
XNextEvent( display, &event );
if ( event.type == MapNotify ) {
XMapEvent *mapevent = (XMapEvent *)&event;
printf( "Mapped : 0x%x\n", (unsigned int)(mapevent->window) );
}
if ( event.type == DestroyNotify ) {
XDestroyWindowEvent *destroywindowevent = (XDestroyWindowEvent *)&event;
printf( "Destroyed : 0x%x\n", (unsigned int)(destroywindowevent->window) );
}
if ( event.type == ReparentNotify ) {
XReparentEvent *reparentevent = (XReparentEvent *)&event;
printf( "Reparented: 0x%x to 0x%x\n", (unsigned int)(reparentevent->window), (unsigned int)(reparentevent->parent) );
}
}
return 0;
}
Have a look at xwininfo.
You might also like xprop and xspy for getting more info.
Update: Yep. Try using xwininfo and -root with either -tree or -children to get all windows involved.
And changes can be tracked with xprop -spy.
I believe that grabbing the X server (XGrabServer(3)) will prevent changes to the window hierarchy. It is a bit heavy handed though, so you should probably only do it if you really need it.
For an example of code that walks the window hierarchy, builds up a tree, uses window events to keep it up to date, and ignores X protocol errors which are unavoidable due to races, see the file src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp in the source code for VirtualBox.
X11 is a remote protocol. This means when you query the X server for any information, you always get your own copy. Your copy never changes when the X server updates its internal data structures.
This means the tree won't suddenly change while you traverse it but when you use the information in it (like examining a window), that information might be stale (someone might have closed the window). That is why you need to do proper error handling.