I use fedora 14 system.
When I use starx startup desktop systems, I created a Xlib program, the code is as follows:
Atom wmStateAbove = XInternAtom(display, "_NET_WM_STATE_ABOVE",1);
if(wmStateAbove != None)
printf("_NET_WM_STATE_ABOVE has atom of %ld \n", (long)wmStateAbove);
else
printf("ERROR: can't find atom for _NET_WM_STATE_Above! \n");
Atom wmNetWmState = XInternAtom(display, "_NET_WM_STATE", 1);
if(wmNetWmState != None)
printf("_NET_WM_STATE has atom of %ld \n", (long)wmNetWmState);
else
printf("ERROR: can't find atom for _NET_WM_STATE! \n");
if(wmStateAbove != None)
{
printf("======\n");
XClientMessageEvent xclient;
memset(&xclient, 0, sizeof(xclient));
xclient.type = ClientMessage;
xclient.window = win;
xclient.message_type = wmNetWmState;
xclient.format = 32;
xclient.data.l[0] = 1;
xclient.data.l[1] = wmStateAbove;
xclient.data.l[2] = 1;
xclient.data.l[3] = 1;
xclient.data.l[4] = 0;
printf(" default Window %d \n", DefaultRootWindow(display));
XSendEvent(display,
DefaultRootWindow(display), False,
SubstructureRedirectMask | SubstructureNotifyMask,
(XEvent*)&xclient);
The window can be created placed at the top
But if I use xinit startup desktop systems, xinitrc script as follows,:
enter image description here
the program can't work normally, prompt _NET_WM_STATE and _NET_WM_STATE_ABOVE cannot find,the window can not be placed at the top, what's the reason?
Doing this at startup might be tricky, if this code executes before the window manager is up and ready to react to the message.
There's also an error in the event; xclient.data.l[2] should be 0, not 1. https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#idm46035372536800
Related
I work on VoIP app on macOS and use VoiceProcessingIO Audio Unit for audio processing like Echo cancellation and automatic gain control.
Problem is, when I init the audio unit, the list of Core Audio devices changes - not just by adding new aggregate device which VP audio unit uses for it's needs, but also because built-in output device (i.e. "Built - In MacBook Pro Speakers") now appears also as an input device, i.e. having an unexpected input stream in addition to output ones.
This is a list of INPUT devices (aka "microphones") I get from Core Audio before initialising my VP AU:
DEVICE: INPUT 45 BlackHole_UID
DEVICE: INPUT 93 BuiltInMicrophoneDevice
This is the same list when my VP AU is initialised:
DEVICE: INPUT 45 BlackHole_UID
DEVICE: INPUT 93 BuiltInMicrophoneDevice
DEVICE: INPUT 86 BuiltInSpeakerDevice /// WHY?
DEVICE: INPUT 98 VPAUAggregateAudioDevice-0x101046040
This is very frustrating because I need to display a list of devices in the app and even though I can filter out Aggregate devices from device list boldly (they are not usable with VP AU anyway), I cannot exclude our built-in macBook Speaker device.
Maybe someone of You has already been through this and has a clue what's going on and if this can be fixed. Some kAudioObjectPropertyXX I need to watch for to exclude the device from inputs list. Or course this might be a bug/feature on Apple's side and I simply have to hack my way around this.
VP AU works well, and the problem reproduces despite devices used (I tried on built-in and on external/USB/Bluetooth alike). The problem is reproduced on all macOS version I could test on, starting from 10.13 and ending by 11.0 included. This also reproduces on different Macs and different audio device sets connected. I am curious that there is next to zero info on that problem available, which brings me to a thought that I did something wrong.
One more strange thing is, when VP AU is working, the HALLab app indicates the another thing: Built-in Input having two more input streams (ok, I would survive this If it was just that!). But it doesn't indicate that Built-In output has input streams added, like in my app.
Here is extract from cpp code on how I setup VP Audio Unit:
#define MAX_FRAMES_PER_CALLBACK 1024
AudioComponentInstance AvHwVoIP::getComponentInstance(OSType type, OSType subType) {
AudioComponentDescription desc = {0};
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentSubType = subType;
desc.componentType = type;
AudioComponent ioComponent = AudioComponentFindNext(NULL, &desc);
AudioComponentInstance unit;
OSStatus status = AudioComponentInstanceNew(ioComponent, &unit);
if (status != noErr) {
printf("Error: %d\n", status);
}
return unit;
}
void AvHwVoIP::enableIO(uint32_t enableIO, AudioUnit auDev) {
UInt32 no = 0;
setAudioUnitProperty(auDev,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
1,
&enableIO,
sizeof(enableIO));
setAudioUnitProperty(auDev,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
0,
&enableIO,
sizeof(enableIO));
}
void AvHwVoIP::setDeviceAsCurrent(AudioUnit auDev, AudioUnitElement element, AudioObjectID devId) {
//Set the Current Device to the AUHAL.
//this should be done only after IO has been enabled on the AUHAL.
setAudioUnitProperty(auDev,
kAudioOutputUnitProperty_CurrentDevice,
element == 0 ? kAudioUnitScope_Output : kAudioUnitScope_Input,
element,
&devId,
sizeof(AudioDeviceID));
}
void AvHwVoIP::setAudioUnitProperty(AudioUnit auDev,
AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void* __nullable inData,
uint32_t inDataSize) {
OSStatus status = AudioUnitSetProperty(auDev, inID, inScope, inElement, inData, inDataSize);
if (noErr != status) {
std::cout << "****** ::setAudioUnitProperty failed" << std::endl;
}
}
void AvHwVoIP::start() {
m_auVoiceProcesing = getComponentInstance(kAudioUnitType_Output, kAudioUnitSubType_VoiceProcessingIO);
enableIO(1, m_auVoiceProcesing);
m_format_description = SetAudioUnitStreamFormatFloat(m_auVoiceProcesing);
SetAudioUnitCallbacks(m_auVoiceProcesing);
setDeviceAsCurrent(m_auVoiceProcesing, 0, m_renderDeviceID);//output device AudioDeviceID here
setDeviceAsCurrent(m_auVoiceProcesing, 1, m_capDeviceID);//input device AudioDeviceID here
setInputLevelListener();
setVPEnabled(true);
setAGCEnabled(true);
UInt32 maximumFramesPerSlice = 0;
UInt32 size = sizeof(maximumFramesPerSlice);
OSStatus s1 = AudioUnitGetProperty(m_auVoiceProcesing, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maximumFramesPerSlice, &size);
printf("max frames per callback: %d\n", maximumFramesPerSlice);
maximumFramesPerSlice = MAX_FRAMES_PER_CALLBACK;
s1 = AudioUnitSetProperty(m_auVoiceProcesing, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maximumFramesPerSlice, size);
OSStatus status = AudioUnitInitialize(m_auVoiceProcesing);
if (noErr != status) {
printf("*** error AU initialize: %d", status);
}
status = AudioOutputUnitStart(m_auVoiceProcesing);
if (noErr != status) {
printf("*** AU start error: %d", status);
}
}
And Here is how I get my list of devices:
//does this device have input/output streams?
bool hasStreamsForCategory(AudioObjectID devId, bool input)
{
const AudioObjectPropertyScope scope = (input == true ? kAudioObjectPropertyScopeInput : kAudioObjectPropertyScopeOutput);
AudioObjectPropertyAddress propertyAddress{kAudioDevicePropertyStreams, scope, kAudioObjectPropertyElementWildcard};
uint32_t dataSize = 0;
OSStatus status = AudioObjectGetPropertyDataSize(devId,
&propertyAddress,
0,
NULL,
&dataSize);
if (noErr != status)
printf("%s: Error in AudioObjectGetPropertyDataSize: %d \n", __FUNCTION__, status);
return (dataSize / sizeof(AudioStreamID)) > 0;
}
std::set<AudioDeviceID> scanCoreAudioDeviceUIDs(bool isInput)
{
std::set<AudioDeviceID> deviceIDs{};
// find out how many audio devices there are
AudioObjectPropertyAddress propertyAddress = {kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
uint32_t dataSize{0};
OSStatus err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize);
if ( err != noErr )
{
printf("%s: AudioObjectGetPropertyDataSize: %d\n", __FUNCTION__, dataSize);
return deviceIDs;//empty
}
// calculate the number of device available
uint32_t devicesAvailable = dataSize / sizeof(AudioObjectID);
if ( devicesAvailable < 1 )
{
printf("%s: Core audio available devices were not found\n", __FUNCTION__);
return deviceIDs;//empty
}
AudioObjectID devices[devicesAvailable];//devices to get
err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize, devices);
if ( err != noErr )
{
printf("%s: Core audio available devices were not found\n", __FUNCTION__);
return deviceIDs;//empty
}
const AudioObjectPropertyScope scope = (isInput == true ? kAudioObjectPropertyScopeInput : kAudioObjectPropertyScopeOutput);
for (uint32_t i = 0; i < devicesAvailable; ++i)
{
const bool hasCorrespondingStreams = hasStreamsForCategory(devices[i], isInput);
if (!hasCorrespondingStreams) {
continue;
}
printf("DEVICE: \t %s \t %d \t %s\n", isInput ? "INPUT" : "OUTPUT", devices[i], deviceUIDFromAudioDeviceID(devices[i]).c_str());
deviceIDs.insert(devices[i]);
}//end for
return deviceIDs;
}
Well, replying my own question in 4 months since Apple Feedback Assistant responded to my request:
"There are two things you were noticing, both of which are expected and considered as implementation details of AUVP:
The speaker device has input stream - this is the reference tap stream for echo cancellation.
There is additional input stream under the built-in mic device - this is the raw mic streams enabled by AUVP.
For #1, We'd advise you to treat built-in speaker and (on certain Macs) headphone with special caution when determining whether it’s input/output device based on its input/output streams.
For #2, We'd advise you to ignore the extra streams on the device."
So they suggest me doing exactly what I did then: determine built - in output device before starting AU and then just memorising it; Ignoring any extra streams that appear in built - in devices during VP AU operation.
I have an application that is used as a control system for a presentation, under Linux and using X11. I have a USB presentation remote that acts as a very miniature keyboard (four buttons: Page Up, Page Down, and two others) which can be used to advance and go back in the presentation. I would like to have my presentation application to receive all of the events from this remote regardless of where the mouse focus is. But I would also like to be able to receive the normal mouse and keyboard events if the current window focus is on the presentation application. Using XIGrabDevice() I was able to receive all events from the remote in the presentation application regardless of the current focus but I was not able to receive any events from the mouse or keyboard while the grab was active.
I ended up setting up a separate program to capture the remote's keys, then I relay those keys to my main program. I did it this way because the original program was using the older XInput extension, and I needed to use the newer XInput2 extension, and they do not exist well together. Here's some C++ code (it doesn't do any error checking, but this should be done in a real program):
// Open connection to X Server
Display *dpy = XOpenDisplay(NULL);
// Get opcode for XInput Extension; we'll need it for processing events
int xi_opcode = -1, event, error;
XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error);
// Allow user to select a device
int num_devices;
XIDeviceInfo *info = XIQueryDevice(dpy, XIAllDevices, &num_devices);
for (int i = 0; i < num_devices; ++i)
{
XIDeviceInfo *dev = &info[i];
std::cout << dev->deviceid << " " << dev->name << "\n";
}
XIFreeDeviceInfo(info);
std::cout << "Enter the device number: ";
std::string input;
std::cin >> input;
int deviceid = -1;
std::istringstream istr(input);
istr >> deviceid;
// Create an InputOnly window that is just used to grab events from this device
XSetWindowAttributes attrs;
long attrmask = 0;
memset(&attrs, 0, sizeof(attrs));
attrs.override_redirect = True; // Required to grab device
attrmask |= CWOverrideRedirect;
Window win = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, 0, InputOnly, CopyFromParent, attrmask, &attrs);
// Make window without decorations
PropMotifWmHints hints;
hints.flags = 2;
hints.decorations = 0;
Atom property = XInternAtom(dpy, "_MOTIF_WM_HINTS", True);
XChangeProperty(dpy, win, property, property, 32, PropModeReplace, (unsigned char *)&hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
// We are interested in key presses and hierarchy changes. We also need to get key releases or else we get an infinite stream of key presses.
XIEventMask evmasks[1];
unsigned char mask0[XIMaskLen(XI_LASTEVENT)];
memset(mask0, 0, sizeof(mask0));
XISetMask(mask0, XI_KeyPress);
XISetMask(mask0, XI_KeyRelease);
XISetMask(mask0, XI_HierarchyChanged);
evmasks[0].deviceid = XIAllDevices;
evmasks[0].mask_len = sizeof(mask0);
evmasks[0].mask = mask0;
XISelectEvents(dpy, win, evmasks, 1);
XMapWindow(dpy, win);
XFlush(dpy);
XEvent ev;
bool grab_success = false, grab_changed;
while (1)
{
grab_changed = false;
if (!grab_success)
{
XIEventMask masks[1];
unsigned char mask0[XIMaskLen(XI_LASTEVENT)];
memset(mask0, 0, sizeof(mask0));
XISetMask(mask0, XI_KeyPress);
masks[0].deviceid = deviceid;
masks[0].mask_len = sizeof(mask0);
masks[0].mask = mask0;
XIGrabDevice(dpy, deviceid, win, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, XIOwnerEvents, masks);
}
XNextEvent(dpy, &ev);
XGenericEventCookie *cookie = &ev.xcookie;
if (cookie->type == GenericEvent && cookie->extension == xi_opcode && XGetEventData(dpy, cookie))
{
if (cookie->evtype == XI_KeyPress)
{
XIDeviceEvent *de = (XIDeviceEvent*)cookie->data;
std::cout << "found XI_KeyPress event: keycode " << de->detail << "\n";
}
else if (cookie->evtype == XI_HierarchyChanged)
{
// Perhaps a device was unplugged. The client is expected to re-read the list of devices to find out what changed.
std::cout << "found XI_HierarchyChanged event.\n";
grab_changed = true;
}
XFreeEventData(dpy, cookie);
}
if (grab_changed)
{
XIUngrabDevice(dpy, deviceid, CurrentTime);
grab_success = false;
break;
}
}
I found the following links helpful:
Peter Hutterer's 6-part blog on XInput2: 1 2 3 4 5 6
This blog entry was useful to determine which class to cast the cookie->data pointer to, depending on the cookie->evtype: 7
How to find which com-port is occupied by serial mouse
Here is how I detect mouse in C# (adapted code from this answer)
var info = IntPtr.Zero;
try
{
var guid = new Guid("{4d36e96f-e325-11ce-bfc1-08002be10318}"); // mouses
info = SetupDiGetClassDevsW(ref guid, null, IntPtr.Zero, 0);
if ((int)info == -1) // INVALID_HANDLE_VALUE
throw new Exception(string.Format("Error({0}) SetupDiGetClassDevsW", Marshal.GetLastWin32Error()));
// enumerate mouses
var device = new SP_DEVINFO_DATA();
device.cbSize = (UInt32)Marshal.SizeOf(device);
for (uint i = 0; ; i++)
{
// get device info
if (!SetupDiEnumDeviceInfo(info, i, out device))
{
var error = Marshal.GetLastWin32Error();
if (error == 259) // ERROR_NO_MORE_ITEMS
break;
else
throw new Exception(string.Format("Error({0}) SetupDiEnumDeviceInfo", error));
}
string id = GetStringPropertyForDevice(info, device, 1); // SPDRP_HARDWAREID
if (id != null && id.Contains("*PNP0F09")) // Microsoft BallPoint Serial Mouse
{
// ...
// here I want to check com-port, how?
// ...
}
}
}
finally
{
if (info != IntPtr.Zero)
SetupDiDestroyDeviceInfoList(info);
}
Edit
Removing C# tag. Looking for general info (any language).
You can use Process Monitor from SysInternalSuite and open device manager then find out from where does the device manager getting its values
I tried it on USB Mouse and was able to get (on USB Input Device) as shown below
1. Open Mouse Properties (From Control Panel)
2. Open ProcMon
3. Click on the target icon and choose the mouse properties window
4. From the Mouse Properties window open the Hardware tab
5. In ProcMon Click on File-> Captuer Events
6. In ProcMon Edit->Find and look for "com" without quotation mark
7. Double click the found row (If you where able to find it)
Another solution would be to get device information using device manager command line utility devcon and parse the information from the output stream
More information on devcon:
* http://support.microsoft.com/kb/311272
* https://superuser.com/questions/414280/how-do-i-view-a-list-of-devices-from-the-command-line-in-windows
Hope this help
The subroutine that generates the "Location" string in Device Manager is devmgr.dll!GetLocationInformation.
The path in it that interests you - generating the value that is appended in brackets - can be represented with the following code (based on Hex-Rays' decompilation):
int __stdcall GetLocationInformation(DEVINST dnDevInst, wchar_t *lpsResult,
int cchBufferMax, HMACHINE hMachine)
{
int dwUiNumber;
HKEY hKey;
DWORD pulLength;
wchar_t sRawLocationInfo[260];
sRawLocationInfo[0] = 0;
DWORD Type = REG_SZ;
pulLength = 520;
if ( !CM_Open_DevNode_Key_Ex(dnDevInst, KEY_READ, 0, 1u, &hKey, 1u, hMachine) )
{
RegQueryValueExW(hKey, L"LocationInformationOverride", 0, &Type,
sRawLocationInfo, &pulLength);
RegCloseKey(hKey);
}
if ( !sRawLocationInfo[0] )
{
pulLength = 520;
CM_Get_DevNode_Registry_Property_ExW(
dnDevInst,
CM_DRP_LOCATION_INFORMATION,
0,
sRawLocationInfo,
&pulLength,
0,
hMachine);
}
pulLength = 4;
if ( CM_Get_DevNode_Registry_Property_ExW(
dnDevInst,
CM_DRP_UI_NUMBER,
0,
&dwUiNumber,
&pulLength,
0,
hMachine)
|| pulLength <= 0 )
{
<...> //this block always returns
}
else
{
<...>
if ( sRawLocationInfo[0] )
{
lstrcatW(lpsResult, L" (");
lstrcatW(lpsResult, sRawLocationInfo);
lstrcatW(lpsResult, L")");
}
return 0;
}
}
In a nutshell, the bracketed value is the device node's LocationInformationOverride or LocationInformation property and is only produced if the UiNumber property is absent (or bogus).
The CM_Open_DevNode_Key_Ex and CM_Get_DevNode_Registry_Property_ExW functions are marked "reserved" in the docs. You can
find their signatures e.g. in CM_Open_DevNode_Key_Ex - FileLog and Enumerate Properties of an Installed Device - The Code Project, respectively, or
use the publicly-documented CM_Open_DevNode_Key and CM_Get_DevNode_Registry_Property instead. They are exactly the same as the former ones save for missing the hMachine argument (they essentially directly call them substituting NULL for it).
There are corresponding SetupDi equivalents, SetupDiOpenDevRegKey and SetupDiGetDeviceRegistryProperty, as well but note that this API is new in Vista and uses different data types.
Seeing that you use it already though means that this is probably the way to go for you unless you need XP support.
If my guess is right, the "USB Serial Port (COM6)" you see in Device Manager is actually the name of the parent device (=the device this one is connected to as seen in Device Manager in "view devices by connection" mode). If this is correct, the "COM6" is but a part of the name rather than some independent property.
A window should stay on top of all other windows. Is this somehow possible with plain x11/xlib? Googling for "Always on top" and "x11" / "xlib" didn't return anything useful.
I'd avoid toolkits like GTK+, if somehow possible.
I'm using Ubuntu with gnome desktop. In the window menu, there's an option "Always On Top". Is this provided by the X server or the window manager? If the second is the case, is there a general function that can be called for nearly any wm? Or how to do this in an "X11-generic" way?
Edit: I implemented fizzer's answer, now having following code:
XSelectInput(this->display, this->window,
ButtonPressMask |
StructureNotifyMask |
ExposureMask |
KeyPressMask |
PropertyChangeMask |
VisibilityChangeMask );
// ...
// In a loop:
if (XPending(this->display) >= 0)
{
XNextEvent(this->display, &ev);
switch(ev.type) {
// ...
case VisibilityNotify:
XRaiseWindow(this->display, this->window);
XFlush(this->display);
break;
// ...
}
}
But the eventhandling and raising nearly never gets executed even my mask is correct?!
#define _NET_WM_STATE_REMOVE 0 // remove/unset property
#define _NET_WM_STATE_ADD 1 // add/set property
#define _NET_WM_STATE_TOGGLE 2 // toggle property
Bool MakeAlwaysOnTop(Display* display, Window root, Window mywin)
{
Atom wmStateAbove = XInternAtom( display, "_NET_WM_STATE_ABOVE", 1 );
if( wmStateAbove != None ) {
printf( "_NET_WM_STATE_ABOVE has atom of %ld\n", (long)wmStateAbove );
} else {
printf( "ERROR: cannot find atom for _NET_WM_STATE_ABOVE !\n" );
return False;
}
Atom wmNetWmState = XInternAtom( display, "_NET_WM_STATE", 1 );
if( wmNetWmState != None ) {
printf( "_NET_WM_STATE has atom of %ld\n", (long)wmNetWmState );
} else {
printf( "ERROR: cannot find atom for _NET_WM_STATE !\n" );
return False;
}
// set window always on top hint
if( wmStateAbove != None )
{
XClientMessageEvent xclient;
memset( &xclient, 0, sizeof (xclient) );
//
//window = the respective client window
//message_type = _NET_WM_STATE
//format = 32
//data.l[0] = the action, as listed below
//data.l[1] = first property to alter
//data.l[2] = second property to alter
//data.l[3] = source indication (0-unk,1-normal app,2-pager)
//other data.l[] elements = 0
//
xclient.type = ClientMessage;
xclient.window = mywin; // GDK_WINDOW_XID(window);
xclient.message_type = wmNetWmState; //gdk_x11_get_xatom_by_name_for_display( display, "_NET_WM_STATE" );
xclient.format = 32;
xclient.data.l[0] = _NET_WM_STATE_ADD; // add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
xclient.data.l[1] = wmStateAbove; //gdk_x11_atom_to_xatom_for_display (display, state1);
xclient.data.l[2] = 0; //gdk_x11_atom_to_xatom_for_display (display, state2);
xclient.data.l[3] = 0;
xclient.data.l[4] = 0;
//gdk_wmspec_change_state( FALSE, window,
// gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
// GDK_NONE );
XSendEvent( display,
//mywin - wrong, not app window, send to root window!
root, // <-- DefaultRootWindow( display )
False,
SubstructureRedirectMask | SubstructureNotifyMask,
(XEvent *)&xclient );
XFlush(display);
return True;
}
return False;
}
You don't want to use XRaiseWindow() to try to stay on top. Some window managers will ignore it entirely. For those that don't, consider what happens if more than one app tries to do this. Boom! That's why the window manager is in charge of stacking windows, not the app.
The way you do this is to use the protocols defined in the Extended Window Manager Hints (EWMH), see: http://www.freedesktop.org/wiki/Specifications/wm-spec
Specifically here you want _NET_WM_STATE_ABOVE which is how the "Always on Top" menu item works.
If you aren't using a toolkit you'll want to get used to scavenging in toolkit source code to figure out how to do things. In this case you could look at the function gdk_window_set_keep_above() in GTK+'s X11 backend. That will show how to use the _NET_WM_STATE_ABOVE hint.
I wrote something like this in Xlib many years ago. It's a few lines of code. When your window is partially obscured you get a VisibilityNotify event, then call XRaiseWindow. Watch out for the case where two of your 'always on top' windows overlap.
Use Actual Title Buttons (http://www.actualtools.com/titlebuttons/) for example. It allows to stay any windows always on top , roll up, make transparency and etc..
I have an executable which is part of a batch process. This one executable opens a console window, which is annoying since it's useless to the end user and steals focus away from their active task.
We can't compile a new version from of this EXE from source (easily). Is there an easy way to twiddle this setting in the PE?
Found it.
editbin.exe /subsystem:windows foo.exe
editbin.exe is part of MSVC
I have wrote it with python based on the PE specification
http://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
I'm not sure that Windows EXE binaries with console|windows subsystem have same
Entry Point Format (with same arguments), but it seem that it is so.
Python Code:
import sys
import struct
if len(sys.argv) < 4:
print "Change Exe Run Mode Application by burlachenkok#gmail.com\nNot sufficient parametrs. 'exe_src_name.exe' 'exe_dest_name.exe' 'to_console' or 'to_windows'"
sys.exit(-1)
source = open(sys.argv[1], "rb")
dest = open(sys.argv[2], "w+b")
dest.write(source.read())
dest.seek(0x3c)
(PeHeaderOffset,)=struct.unpack("H", dest.read(2))
dest.seek(PeHeaderOffset)
(PeSignature,)=struct.unpack("I", dest.read(4))
if PeSignature != 0x4550:
print "Error in Find PE header"
dest.seek(PeHeaderOffset + 0x5C)
if sys.argv[3].strip() == "to_console":
# console mode
dest.write(struct.pack("H", 0x03))
elif sys.argv[3].strip() == "to_windows":
# window mode
dest.write(struct.pack("H", 0x02))
else:
print "Wrong Format: '" + sys.argv[3] + "'"
source.close()
dest.close()
print "Completed succesfully.."
Here is a node version of the Python code :)
const fs = require('fs');
const bufferpack = require('bufferpack');
if(process.argv.length < 4) {
console.log("Change Exe Run Mode Application \nNot sufficient parameters. 'exe_src_name.exe' 'exe_dest_name.exe' 'to_console' or 'to_windows'");
process.exit(-1);
}
function read(f, size, offset) {
if(typeof size == 'undefined') size = 1;
if(typeof offset == 'undefined') offset = -1;
const buffer = Buffer.alloc(size);
fs.readSync(f, buffer, 0, size, offset);
return buffer;
}
const source = fs.openSync(process.argv[2], "r");
const dest = fs.openSync(process.argv[3], "w+");
fs.writeSync(dest, read(source, fs.statSync(process.argv[2]).size, 0));
const PeHeaderOffset = bufferpack.unpack('<H', read(dest, 2, 0x3c)).pop();
const PeSignature = bufferpack.unpack('<I', read(dest, 4, PeHeaderOffset)).pop();
if(PeSignature != 0x4550) {
console.log("Error in Find PE header");
process.exit(-1);
}
if(process.argv[4] == "to_console") {
// console mode
fs.writeSync(dest, bufferpack.pack('<H', [0x03]), 0, 1, PeHeaderOffset + 0x5C);
} else if(process.argv[4] == "to_windows") {
// window mode
fs.writeSync(dest, bufferpack.pack('<H', [0x02]), 0, 1, PeHeaderOffset + 0x5C);
} else {
console.log("Wrong Format: '" + process.argv[4] + "'");
}
fs.closeSync(source);
fs.closeSync(dest);
console.log("Completed succesfully.");