I'm experimenting with XReparentWindow with the end goal to aggregate windows of multiple processes into one "cockpit" simulating process. Experiments with XReparentWindow works sporadically; sometimes the window is reparented successfully, sometimes not. When unsuccessfully reparented the (not) grabbed window flickers for a second and then proceedes as usual, and the grabber show undefined window content. It is successfull every other time (tempted to brute-force the problem away by always trying two times).
Edit 1: Checking output of XQueryTree right after XReparentWindow shows the grabbed window is properly reparented, but would appear to keep its frame origin where grabbed from on display rather than being moved to the grabber window.
The grabbed window is from a real-time OpenGL rendering application, compiled from source. The application does not anticipate the grabbing in any way (maybe it should?). I have also tried grabbing glxgears and a GNOME Terminal, same result.
The experimental code, taking window to grab as program argument (e.g. using xwininfo | grep "Window id"):
#include <X11/Xlib.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h> // usleep
int main(int argc, char** argv) {
assert(argc==2);
Window window, extwin;
sscanf(argv[1], "%p", &extwin);
Display* display = XOpenDisplay(0);
window = XCreateWindow(display, RootWindow(display, 0), 0, 0, 500, 500, 0, DefaultDepth(display, 0), InputOutput, DefaultVisual(display, 0), 0, 0);
XMapWindow(display, window);
XReparentWindow(display, extwin, window, 0, 0);
while(1) {
XFlush(display);
usleep(3e5);
}
return 0;
}
(Code is manually exported from a restricted environment. Sorry for any typos made during export.)
Looking forward for suggestions of what to try out next.
Edit 2: Having captured the event stream of the grabbed window using xev I notice something odd; after being reparented to the grabber window, it reparents itself back to root window after less than a second (restricted environment, typing what's seen on other window with anticipated significance):
UnmapNotify event ...
ReparentNotify event ... parent 0x4000001 (grabber window)
MapNotify event ...
ConfigureNotify event ... synthetic YES (what is this?)
UnmapNotify event ...
ReparentNotify event ... parent 0xed (reparenting back to parent window, but why?)
MapNotify event ...
VisibilityNotify event ...
Expose event ...
PropertyNotify event ... _NET_WM_DESKTOP state PropertyDelete
PropertyNotify event ... _NET_WM_STATE state PropertyDelete
PropertyNotify event ... WM_STATE state PropertyNewValue
I quit the program and try again a second time, at which the output that continues is:
UnmapNotify event ...
ReparentNotify event ... parent 0x4000001 (grabber window)
MapNotify event ...
VisibilityNotify event ...
Expose event ...
What is going on?
I am a newbie in the GUI world and I don't know X11 internals. But I've just read a very interesting documentation (https://www.x.org/releases/current/doc/libX11/libX11/libX11.html)
Most of the functions in Xlib just add requests to an output buffer. These requests later execute asynchronously on the X server. Functions that return values of information stored in the server do not return (that is, they block) until an explicit reply is received or an error occurs. You can provide an error handler, which will be called when the error is reported.
If a client does not want a request to execute asynchronously, it can follow the request with a call to XSync, which blocks until all previously buffered asynchronous events have been sent and acted on. As an important side effect, the output buffer in Xlib is always flushed by a call to any function that returns a value from the server or waits for input.
So I guess what you have is a race condition between reparenting and something.
This works for me:
// gcc -lX11 -lXcomposite a.c && ./a.out 0x1a00001
// IDs can be gotten from
// `wmctrl -l` (shows only the parent windows) or `xwininfo`.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <X11/Xlib.h> // -lX11
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xcomposite.h> // optional, -lXcomposite
void reparent (Display *d, Window child, Window new_parent)
{
XUnmapWindow(d, child);
XMapWindow(d, new_parent);
XSync(d, False);
XReparentWindow(d, child, new_parent, 0, 0);
XMapWindow(d, child);
// 1 ms seems to be enough even during `nice -n -19 stress -c $cpuThreadsCount` (pacman -S stress) on linux-tkg-pds.
// Probably can be decreased even further.
usleep(1e3);
XSync(d, False);
}
int main (int argc, char **argv)
{
Display *d = XOpenDisplay(XDisplayName(NULL));
int s = DefaultScreen(d);
Window root = RootWindow(d, s);
if (argc != 2)
{
printf("Wrong number of arguments, exiting.");
exit(1);
}
Window child = strtol(argv[1], NULL, 0);
Window new_parent = XCreateSimpleWindow(
d, root, 0, 0, 500, 500, 0, 0, 0
);
// (Optional)
// Allow grabbing by `ffmpeg -f x11grab -window_id`
// while being on the same virtual screen
// AND (focused or unfocused)
// AND (seen or unseen)
// AND no other window is both fullscreen and focused.
XCompositeRedirectWindow(d, child, CompositeRedirectAutomatic);
// After `new_parent` is destroyed (when the program exists),
// don't make `child` unmapped/invisible.
XAddToSaveSet(d, child);
reparent(d, child, new_parent);
XEvent e;
while (1)
{
XNextEvent(d, &e);
}
return 0;
}
Also it's possible to use xdotool:
xdotool windowunmap $CHID
xdotool windowreparent $CHID $NEWPID
xdotool windowmap --sync $CHID
Brute force solution, grabbing the window repeatedly:
#include <X11/Xlib.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h> // usleep
int main(int argc, char** argv) {
assert(argc==2);
Window window, extwin;
sscanf(argv[1], "%p", &extwin);
Display* display = XOpenDisplay(0);
window = XCreateWindow(display, RootWindow(display, 0), 0, 0, 500, 500, 0, DefaultDepth(display, 0), InputOutput, DefaultVisual(display, 0), 0, 0);
XMapWindow(display, window);
while(1) {
Window root, parent, *ch;
unsigned int nch;
XQueryTree(display, extwin, &root, &parent, &ch, &nch);
if(parent!=window) {
XReparentWindow(display, extwin, window, 0, 0);
}
if(nch>0) { XFree(ch); }
XFlush(display);
usleep(3e5);
}
return 0;
}
Assuming this only happens once the clause can be disabled after two calls to reparent. Works on my machine. Would appreciate full explaination of what is really going on.
I have never tried with an OpenGL application and do not have the environment here.
Maybe try first with a simple X app (like xclock) and observe if you get the same behaviour.
If yes, that's your code, if no, probably OpenGL interaction.
From your snippset, two comments though:
In the while loop, you should consume the X events
XEvent e;
while(1) {
XNextEvent(d, &e);
}
Then the XAddToSaveSet function does not work properly.
You will need to use the XFixes in order to properly restore that window in case of a crash.
#include <X11/extensions/Xfixes.h>
...
// The Xorg API is buggy in certain areas.
// Need to use the XFixes extensions to address them
// Initializes these extensions
int event_base_return = 0;
int error_base_return = 0;
Bool result = XFixesQueryExtension(display, &event_base_return);
printf("XFixesQueryExtension result: %d. eventbase: %d - errorbase: %d\n", result, event_base_return, error_base_return);
// We actually only need version 1.0. But if 4.0 is not there then something is really wrong
int major = 4;
int minor = 0;
result = XFixesQueryVersion(display, &major, &minor);
printf("XFixesQueryVersion result: %d - version: %d.%d\n", result, major, minor);
...
XReparentWindow(display, childWindowId, parentWindowId, 0, 0);
XFixesChangeSaveSet(display, childWindowId, SetModeInsert, SaveSetRoot, SaveSetUnmap);
...
For my college project I am developing a solution to distinguish between mouse user data from a person with Parkinson's compared to a healthy person. For which I need mouse data, ideally raw.
I presume I have misunderstood how to collect raw mouse input from the WM_INPUT message but I cannot figure it out.
I have been looking at the following thread: How to accurately measure mouse movement in inches or centimetres for a mouse with a known DPI
and Mouse input libraries on github all of which seem to easily catch a WM_INPUT message whose lParam is a handle to some RawInputData with something like this:
GetMessage(&msg, GetActiveWindow(), WM_INPUT, 0);
if (msg.message == WM_INPUT){ .....
And then retreiving the lParam from the message and collecting the data associated with that handle with:
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
However when I call GetMessage in my main loop, the function never exits!
Consequently there is no way (that i know of) for me to get a handle to the RawInputData. Especially since the MSDN page just assumes you have the lParam already.
In summary I need a method of getting an lParam to pass to the GetRawInputData function which will remain active whether the program is running in the active window of not.
I'm running this code in a blank C++ CLR project in Visual Studio with the "winuser.h" library.
#include "stdafx.h"
#include "Windows.h"
#include "winuser.h"
#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
#endif
int main(array<System::String ^> ^args)
{
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
Rid[0].dwFlags = 0; //ideally RIDEV_INPUTSINK but that prevents registration
Rid[0].hwndTarget = GetActiveWindow(); //ideally this would be Null to be independent of the active window
if (RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
//registration failed. Call GetLastError for the cause of the error
Console::WriteLine("Registration Error");
}
MSG msg;
while (true) {
while (GetMessage(&msg, GetActiveWindow(), WM_INPUT, 0) != 0) { //this command is never completed
DispatchMessage(&msg); //this line is never ran
}
if (msg.message == WM_INPUT) {
Console::WriteLine("caught a message!!!");
}
}
}
Issue solved after much more research I found the winAPI walk through which I followed fixing the issue above by adding an:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE unused, PSTR cmd, int show) {.....}
Function to register devices and create a window then call GetMessage which calls LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {....} with the parameters occupied by the message ID,WParam and LParam corresponding the message event.
For anyone stuck with a similar issue follow this MSDN guide: https://msdn.microsoft.com/en-us/library/bb384843.aspx
Is there a WinAPI function to retrieve a handle to the Task Bar?
The purpose is to determine the Task Bar docking setting (ABE_LEFT, ABE_RIGHT, ABE_BOTTOM, ABE_TOP). The function SHAppBarMessage requires the taskbar handle to retrieve the docking information. Unless there is another way to determine the task bar docking setting without needing the handle?
I'm aware of this method which works ok but I am not sure it works on all Windows versions:
HWND taskBar = FindWindow("Shell_TrayWnd", NULL);
That appears to be a documentation bug. You don't need to provide a window handle in the APPBARDATA structure for the ABM_GETTASKBARPOS when calling SHAppBarMessage1).
The following code properly returns the location of the taskbar (tested on Windows 10 x64):
#include <shellapi.h>
#pragma comment(lib, "Shell32.lib")
#include <stdexcept>
RECT GetTaskbarPos() {
APPBARDATA abd = { 0 };
abd.cbSize = sizeof( abd );
if ( !::SHAppBarMessage( ABM_GETTASKBARPOS, &abd ) ) {
throw std::runtime_error( "SHAppBarMessage failed." );
}
return abd.rc;
}
Update: The question was really asking for the docking enumeration value. That is returned as well:
#include <shellapi.h>
#pragma comment(lib, "Shell32.lib")
#include <stdexcept>
UINT GetTaskbarDockingEdge() {
APPBARDATA abd = { 0 };
abd.cbSize = sizeof( abd );
if ( !::SHAppBarMessage( ABM_GETTASKBARPOS, &abd ) ) {
throw std::runtime_error( "SHAppBarMessage failed." );
}
return abd.uEdge;
}
1) It would be awkward if you needed the well hidden window handle of the taskbar to send this message. If you had the window handle already, you could simply call GetWindowRect instead.
My WPF app consumes a third-party Win32 dll that logs messages via OutputDebugString.
I can see the OutputDebugString messages in Visual Studio or via DebugView, but I don't want to ask my customer to run DebugView. I'd like to capture the messages from OutputDebugString and automatically log them to a file, so if the customer has a problem, I can just ask her to send me that log file.
Is this possible? Or does the user necessarily have to start DebugView, reproduce the error, and then send me the log that way?
Hook OutputDebugStringW. I'd suggest using the Detours library for this.
#include <windows.h>
#include <detours.h>
#pragma comment(lib, "detours.lib")
BOOL SetHook(__in BOOL bState, __inout PVOID* ppPointer, __in PVOID pDetour)
{
if (DetourTransactionBegin() == NO_ERROR)
if (DetourUpdateThread(GetCurrentThread()) == NO_ERROR)
if ((bState ? DetourAttach : DetourDetach)(ppPointer, pDetour) == NO_ERROR)
if (DetourTransactionCommit() == NO_ERROR)
return TRUE;
return FALSE;
{
#define InstallHook(x, y) SetHook(TRUE, x, y)
VOID (WINAPI * _OutputDebugStringW)(__in_z_opt LPCWSTR lpcszString) = OutputDebugStringW;
VOID WINAPI OutputDebugStringHook(__in_z_opt LPCWSTR lpcszString)
{
// do something with the string, like write to file
_OutputDebugStringW(lpcszString);
}
// somewhere in your code
InstallHook((PVOID*)&_OutputDebugStringW, OutputDebugStringHook);
#Cody Gray's suggestion to "write your own debug listener, and then you've basically written an inferior clone of DebugView" sounds like it might actually be an answer to my question.
Here's a C# implementation of a basic OutputDebugString capture tool. I'd seen it in my Googling a couple of times, but my eyes glazed over it, assuming, "that can't possibly be what I want, can it?" Turns out, it just might be the answer to my question.
I have a slightly odd problem involving a MoGo mouse failing to charge when put in the cartridge slot of my Windows XP laptop. Long story, but one suggestion to fix it is to write a bespoke driver which only says "I'm functioning OK: don't turn the power off".
I'm figuring that this should be next to trivial, but my only experience of drivers is to download and install them through provided MSIs. I realised that I don't know:
What language they're written in.
What conventions they must follow.
How they are associated with their respective hardware.
Where they are located.
Or indeed, anything at all...
I also haven't found anything staggeringly helpful on the web - probably because they are aimed at a far higher level than I'm at.
Any insights would be welcome.
Microsoft provides a "Hello World" driver example in their documentation. This is an example of "World's most simple Windows driver". Unfortunately, it's 13 pages long and thus not a good fit for a StackOverflow answer.
The language they are written in is C++.
To get started, be sure you have Microsoft Visual Studio, the Windows
SDK, and the Windows Driver Kit (WDK) installed.
Their example contains one file called Driver.c that looks like this:
#include <ntddk.h>
#include <wdf.h>
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
// NTSTATUS variable to record success or failure
NTSTATUS status = STATUS_SUCCESS;
// Allocate the driver configuration object
WDF_DRIVER_CONFIG config;
// Print "Hello World" for DriverEntry
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n" ));
// Initialize the driver configuration object to register the
// entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd
WDF_DRIVER_CONFIG_INIT(&config,
KmdfHelloWorldEvtDeviceAdd
);
// Finally, create the driver object
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE
);
return status;
}
NTSTATUS
KmdfHelloWorldEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
// We're not using the driver object,
// so we need to mark it as unreferenced
UNREFERENCED_PARAMETER(Driver);
NTSTATUS status;
// Allocate the device object
WDFDEVICE hDevice;
// Print "Hello World"
KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));
// Create the device object
status = WdfDeviceCreate(&DeviceInit,
WDF_NO_OBJECT_ATTRIBUTES,
&hDevice
);
return status;
}
Full details found here:
https://learn.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/writing-a-very-small-kmdf--driver