X11/Xlib: Window always on top - user-interface

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..

Related

In WinAPI, how to make a stretchable OpenGL window with correct mouse, trapped properly for games?

I have read a lot of Stack Overflow over the years when struggling with making sense of Microsoft Windows' strange world of CreateWindowEx() .. etc. This question, when originally asked was "What is the best way to create a fluidly resizable OpenGL window in WinAPI?"
I've been struggling with getting WinAPI to make a window that:
Has an OpenGL context
Is properly centered on the main monitor (or any monitor determined by command line signal) in both multi-monitor and single-monitor displays when in "Windowed" mode or in "Fullscreen" mode
Has a fixed internal client screen size (viewport 2d)
Doesn't allow you to click outside causing it to lose focus at the wrong times or in special cases for multi-monitor
Can be resized fluidly, but doesn't change internal "client size" (meaning that it stretches the OpenGL content which is a fixed size to the new screen size) ... the idea here is to add a layer of virtualization, so that all pixels are expressed in the same 1920x1080 (1080p) coordinate system. This part is no problem for me.
Correctly handles mouse event translation from screen_size -> client_size equivalent via the screen->client ratio
In my homegrown App framework, I have to set the display size, and even then, Windows doesn't give me the right sized window. (Sometimes the title bar is subtracted, sometimes the scrollbars are subtracted, but the context draws under the title bar, for example.)
Also, recently when moving from 2010 EE (Win32 / Windows 7) to 2015 (win32 / Windows 10), I had to change the parameters to recenter the view because it was off-centered on the main display. Now, only sometimes are these values correct or incorrect. If I go "fullscreen" for example, the same values will draw above the top of the screen such that there is an area at the bottom of the screen that shows the "gl clear color" (in my case, orange)
I can play with these things by providing the following command line parameters:
-bordered (default, and has no effect really, is the default windowed mode with the title bar and such)
-borderless (seems to go into fullscreen mode, with the app off-center where win 0,0 is actually in screen center)
-windowed (or -window)
If I don't provide -window, it defaults to "full screen" resolution-adjusted (but only if supported I assume, otherwise it might throw an error).
Anyway, all of this is very bad because
a) I have to write a bajillion cases for each resolution I'm working in, rather than write everything for 1080p and have it adjust to display size, which is what i want because it handles most new displays on laptops and desktops (this is Windows remember) (and only slightly squishes things in those corner cases)
b) I cannot resize the window fluidly, also i have to trap the mouse at center and recalculate the mouse position, so I record only the deltas -- this is to avoid the mouse leaving the window and clicking the desktop, or floating off the monitor to some other monitor, even when it is hidden. I also have to make the mouse cursor invisible so the user doesn't see this, then show a simulated mouse cursor.
c) Users who don't support specifically 1920x1080 won't be able to use full screen mode
Someone pointed this article out in another question (window border width and height in Win32 - how do I get it?):
https://web.archive.org/web/20120716062211/http://suite101.com/article/client-area-size-with-movewindow-a17846
And I've read through this, learning that AdjustWindowRectEx() has some issues:
AdjustWindowRectEx() and GetWindowRect() give wrong size with WS_OVERLAPPED
I don't use WS_OVERLAPPED, so this was only moderately helpful:
AdjustWindowRectEx() and GetWindowRect() give wrong size with WS_OVERLAPPED
Here's how I do it now:
display.Resized(display.w,display.h);
// Fill in the window class structure for testing display type.
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WinProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
// Save the game instance handle
display.hinstance = game_instance = hinstance;
// Register the window class
if (!RegisterClassEx(&winclass)) return(0);
if (!gl.Init(hinstance, display.bits)) {
return(0);
}
// Detect the display size and create the final display profile
DWORD winStyle=
WS_EX_APPWINDOW |
WS_EX_TOPMOST /*|
WS_EX_ACCEPTFILES*/ ;
// Adjust Window, Account For Window Borders
int xPos = GetSystemMetrics(SM_CXSCREEN) - display.w;
int yPos = GetSystemMetrics(SM_CYSCREEN) - display.h;
RECT windowRect = {0, 0, display.w, display.h}; // Define Our Window Coordinates
AdjustWindowRectEx (&windowRect, WS_POPUP, 0, winStyle );
// Create the window
if (!(hwnd = CreateWindowEx(
winStyle, // extended style
WINDOW_CLASS_NAME, // class
gl.winTitle.c_str(), // title
( gl.borderless || CmdLine.Option("-borderless") ) ? (WS_POPUPWINDOW | WS_VISIBLE)
: (gl.noFullscreen ? ((CmdLine.Option("-bordered") ? WS_BORDER : 0) | WS_VISIBLE)
: (WS_POPUP | WS_VISIBLE)), // use POPUP for full screen
gl.noFullscreen && !CmdLine.Option("-recenter") ? xPos / 2 : 0,
gl.noFullscreen && !CmdLine.Option("-recenter") ? yPos / 2 : 0, // initial game window x,y
display.w, // initial game width
display.h, // initial game height
HWND_DESKTOP, // handle to parent
NULL, // handle to menu
hinstance, // instance of this application
NULL)
) // extra creation parms
) {
OUTPUT("WinAPI ERROR: Could not open window.\n");
return(0);
}
if (gl.borderless || CmdLine.Option("-borderless") ) {
LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
SetWindowLong(hwnd, GWL_STYLE, lStyle);
LONG lExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
SetWindowLong(hwnd, GWL_EXSTYLE, lExStyle);
SetWindowPos(hwnd, NULL, 0, 0, display.w, display.h, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
// Temporary change to full screen mode
ZeroMemory(&game_screen, sizeof(game_screen)); // clear out size of DEVMODE struct
game_screen.dmSize = sizeof(game_screen);
game_screen.dmPelsWidth = display.w;
game_screen.dmPelsHeight = display.h;
game_screen.dmBitsPerPel = display.bits;
game_screen.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
ChangeDisplaySettings(&game_screen, CDS_FULLSCREEN);
// save the game window handle
display.hwnd = game_window = hwnd;
display.hdc = game_dc = GetDC(display.hwnd = game_window); // get the GDI device context
// set up the pixel format desc struct
pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this PFD
1, // version number
PFD_DRAW_TO_WINDOW | // supports window
PFD_SUPPORT_OPENGL | // supports OpenGL
PFD_DOUBLEBUFFER, // support double buff
PFD_TYPE_RGBA, // request RGBA format
(BYTE)display.bits, // select color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buff
0, // shift bit ignored
0, // no accum buff
0, 0, 0, 0, // accum bits ignored
16, // 16-bit Z-buff (depth buff)
0, // no stencil buff
0, // no aux buff
PFD_MAIN_PLANE, // main drawing layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int pf; // pixel format
if (!gl.arbMultisampleSupported) {
if (!(pf = ChoosePixelFormat(game_dc, &pfd))) // match the pixel format
{
MessageBox(game_window, "OpenGL could not be initialized -- ChoosePixelFormat Error ; report this to program authors for help!", "OpenGL Error", MB_OK);
return FALSE; // error returned
}
} else {
pf = gl.arbMultisampleFormat;
}
if (!SetPixelFormat(game_dc, pf, &pfd)) // set the pixel format
{
MessageBox(game_window, "OpenGL could not be initialized -- SetPixelFormat Error ; report this to program authors for help!", "OpenGL Error", MB_OK);
return FALSE; // error returned
}
if (!(game_rc = wglCreateContext(game_dc))) // create the rendering context
{
MessageBox(game_window, "OpenGL could not be initialized -- CreateContext Error ; report this to program authors for help!", "OpenGL Error", MB_OK);
return FALSE; // error returned
}
if (!(upload_rc = wglCreateContext(game_dc))) // create the rendering context
{
MessageBox(game_window, "Multiple OpenGL contexts could not be initialized -- CreateContext Error ; report this to program authors for help!", "OpenGL Error", MB_OK);
return FALSE; // error returned
} else { // Share as much as you can between two contexts
if (!wglShareLists(game_rc, upload_rc)) {
// could use GetLastError here
MessageBox(game_window, "wglShareLists -- Error ; report this to program authors for help!", "OpenGL Error", MB_OK);
return FALSE; // error returned
}
}
if (!wglMakeCurrent(game_dc, display.hglrc = game_rc)) // make it current
{
MessageBox(game_window, "OpenGL could not be initialized -- MakeCurrent Error ; report this to program authors for help!", "OpenGL Error", MB_OK);
return FALSE; // error returned
}
ShowCursor(false);
ShowWindow(game_window, SW_SHOWNORMAL);
SetForegroundWindow(game_window);
In the above code, what I get is a window that has no resize functionality, hides the OS mouse cursor, and can only be exitted with ALT-TAB (or ALT-F4), and when it is exitted appears at the back of the windows Z-order. I always open my window using a parameter that sets display.w to 1920 and display.h to 1080, either in full screen or in Windowed mode. WM_SIZE is then called to adjust it to the client area.
Please note that the following WM_SIZE is called during the WinProc right after the initial time I set display.Resized(w,h):
case WM_SIZE:
{
display.Resized(LOWORD(lparam), HIWORD(lparam));
return (0);
}
break;
This is executed exactly once during app load, and in the first case it looks like the values are: 1918,1078
UPDATE: If I use the result of GetWindowRect() here, or GetClientRect() as shown below, the window mysteriously moves to Center-X,Center-Y of screen! What gives??
// RECT rect;
// if ( GetClientRect(hwnd,&rect) ) {
// display.Resized((int)rect.right,(int)rect.bottom);
// }
//if ( GetWindowRect( hwnd, &rect ) ) {
// display.Resized((int)ADIFF(rect.left,rect.right),(int)ADIFF(rect.top,rect.bottom));
//}
display.Resized(LOWORD(lparam), HIWORD(lparam));
return (0);
What steps do I need to take to make the window stretchable such that the context is resized to the view, and the mouse is properly adjusted based on the screen ratio?
Basically, there are too many edge cases to make sense of all of this. As time has gone on since the 2 years ago that I asked this question, I've had other inconsistencies between full screen and window emerge.
From what I understand there are basically 3 types of windows:
Your normal on-screen moveable/resizable window for windowing GUIs, like this browser window (if you are not on mobile)
One matched to a display's resolution support (including resolutions smaller than its native) -- we call this "Full screen" (or Fullscreen, which isn't even a word)
One that is a normal on-screen window, but lacks a title bar, borders and scroll bars, and appears as large as the screen. Referred to "on the street" as a "Borderless Window"
I want to master all of these but in a way that makes them all accessible and doesn't require special cases. I've basically given up on doing so with WinAPI, but obviously multiple companies do this. Following Microsoft's documentation isn't very helpful, and I've experimented with a lot of different CreateWindow CreateWindowEx -- many of these features are deprecated by the way, or don't work at all.
(Maybe the best question is, WHEN WILL MICROSOFT CLEAN UP THIS CRAP? But I think we all know the answer.) .. any help to get it working would be appreciated.
I'm now working in: C++, Windows API, OpenGL 3.x / 4.x, Windows 10.

Find com-port used by serial mouse

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.

Joystick won't work using SDL

I'm building a simple game in SDL. I've been through countless tutorials and I've clearly missed something as it still ignoring my Joystick completely
In my constructor
SDL_JoystickEventState(SDL_ENABLE);
joystick = SDL_JoystickOpen(0);
In my update I'm calling a test to check I have actually initialized the joystick
if (SDL_NumJoysticks() <= 0)
{
done = true;
}
Here is my player update as well
void World::playerMovement()
{
SDL_Event event;
while (SDL_PollEvent (&event))
{
switch (event.type)
{
case SDL_QUIT:
done = true;
break;
case SDL_JOYAXISMOTION:
if ( ( event.jaxis.value < -3200 ) || (event.jaxis.value > 3200 ) )
{
test = true;
}
break;
}
}
}
Test is simply a bool which once true will mean my enemies start spawning. I also run a check in main
if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0)
{
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
done = true;
}
When I run the game it loads as normal but no matter how much I move the joystick it won't set test to true.
I also tried using the following in the while poll event loop instead.
if (event.type == SDL_JOYAXISMOTION)
{
if(SDL_JoystickGetAxis(joystick, 1) > 0)
{
test = true;
}
}
Any idea's what I have missed?
I think emartel has the best answer to make sure SDL_joystick is working.
When does World::playerMovement() happen? The overall flow of your program is hard to determine from these snippets.
I'm happy to share with you my code for handling joysticks, which keeps track of: multiple joysticks, axes scaled [-1,1] with deadzone removed, and buttons held down.
http://www.raptor007.com/code/RaptorEngine_Joystick.zip
And here's a snippet of how that would be utilized as part of your main loop:
// FIXME: SDL needs to be initialized before we get here.
JoystickManager Joy;
Joy.Initialize();
double deadzone = 0.02;
// Main loop.
bool done = false;
while( ! done )
{
// Keep the list of joysticks up-to-date.
Joy.FindJoysticks();
// Handle all user input.
SDL_Event event;
while( SDL_PollEvent( &event ) )
{
// Let the JoystickManager track events relevant to it.
Joy.TrackEvent( &event );
// FIXME: Handle single-press events here (next target, etc).
// Don't handle button-held-down events like firing (see below).
if( event.type == SDL_QUIT )
done = true;
}
// Read joystick 0 analog axes.
double roll = Joy.Axis( 0, 0, deadzone );
double pitch = Joy.Axis( 0, 1, deadzone );
double yaw = Joy.Axis( 0, 3, deadzone );
double throttle = Joy.AxisScaled( 0, 2, 1., 0., 0., deadzone );
// Read joystick 0 buttons held down.
bool firing = Joy.ButtonDown( 0, 0 );
// FIXME: Update game objects and draw graphics.
}
I found a weird behaviour in SDL2:
If no events are put into the queue, try adding the following before the SDL_Init call:
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1");
Are you sure joystick points to a valid joystick?
You state that you're getting it in your Constructor... does that contructor happen to be called before you initialize SDL with SDL_INIT_JOYSTICK? This could happen if your player is a global variable.
Make sure that in order you:
Init the Joystick subsystem, either by adding it to your SDL_Init with | SDL_INIT_JOYSTICK or by calling SDL_InitSubSystem(SDL_INIT_JOYSTICK);
Check SDL_NumJoysticks() > 0
Get joystick 0: joystick = SDL_JoystickOpen(0);
Enable events: SDL_JoystickEventState(SDL_ENABLE);
Process your events with SDL_PollEvent
At the end of your program, close your joystick: SDL_JoystickClose(joystick);
Also, make sure the joystick is properly detected in Windows and reports its inputs properly.
Looks like your SDL isn't init proper.
replace
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK)
with
SDL_Init(SDL_INIT_EVERYTHING)
Is this SDL 1.2 or 2.0? In my case, on 2.0 SDL_PollEvent(&event) didn't actually put any data in the event struct. After that call, I had to use SDL_JoystickGetAxis(joystick_id, axis) and friends to get data.
So in your case, try to move the SDL_JoystickGetAxis call out of the if-test on event-type.
If you call SDL_NumJoysticks to get the number of controllers connected, then call SDL_JoystickOpen which returns a joystick identifier before your game loop then you will receive the SDL_JOYAXISMOTION events.
e.g.
int num_joy;
num_joy = SDL_NumJoysticks();
printf("%d joysticks found\n", num_joy);
for(int i = 0; i < num_joy; i++)
{
SDL_Joystick *joystick = SDL_JoystickOpen(i);
printf("Joystick name: %s\n", SDL_JoystickName(joystick));
}
SDL_Event event;
bool quit = false;
// Game loop
while(!quit)
{
// event loop
while(SDL_PollEvent(&event))
{
if (event.type == SDL_JOYAXISMOTION)
{
printf("Joystick______EVENT!\n");
}
// etc.....
See https://wiki.libsdl.org/SDL_JoystickName
I do not know how this can help you, but I do know that pygame supports joystick. And pygame is the python port of the SDL library. If everything fails, I guess you can always write that particular piece of code in python.

Best algorithm for syntax highlight (WINAPI)

I write a program on WINAPI. I must to implement syntax highlight. At this moment the I using following algorithm:
void PaintWords(const char *SearchWord,COLORREF rgb)
{
counter = TabCtrl_GetCurSel(TabControl_hWnd);
ft.chrg.cpMin = 0;
ft.chrg.cpMax = GetWindowTextLength(hWnd);
ft.lpstrText = (LPCSTR)SearchWord; //keyword
do
{
int poe_p = SendMessage(hWnd, EM_FINDTEXTEX, FR_DOWN | FR_WHOLEWORD | FR_MATCHCASE, (LPARAM)&ft);
if(poe_p != -1)
{
int selword = SendMessage(hWnd, EM_EXSETSEL,0,(LPARAM)&ft.chrgText);
ZeroMemory(&chd, sizeof(chd));
chd.cbSize = sizeof(CHARFORMAT);
chd.dwMask = CFM_SIZE | CFM_FACE | CFM_COLOR | CFM_CHARSET;
chd.crTextColor = rgb;
chd.bPitchAndFamily = FW_THIN;
lstrcpy(chd.szFaceName , "Courier New");
SendMessage(hWnd,EM_SETCHARFORMAT,SCF_WORD|SCF_SELECTION,(LPARAM)&chd);
ft.chrg.cpMin = ft.chrgText.cpMax;
}
else
{
break;
}
}while(ft.chrg.cpMin != ft.chrg.cpMax);
}
This code is too slow, because this is not best option, flicker is visible.
I interested in other variants.
I think you need to use double buffering to reduce the flicker. Other than that, you should not use SendMessage (or even PostMessage) to any window (within same thread). Why selection must happen in your syntax-highlighting paint code?
One of the article on double buffer is this.
I have come across this project's RichTextbox, which is used as an xml editor: http://xpathvisualizer.codeplex.com/SourceControl/changeset/view/42057#XPathVisualizer/CustomControls/RichTextBoxEx.cs
it's in C#, but the messages sent are visible.
When using this TextBox, before highlighting the text the BeginUpdateAndSuspendEvents function should be called.
public IntPtr BeginUpdateAndSuspendEvents()
{
// Stop redrawing:
User32.SendMessage(this.Handle, (int) User32.Msgs.WM_SETREDRAW, 0, IntPtr.Zero);
// Stop sending of events:
IntPtr eventMask = User32.SendMessage(this.Handle, User32.Msgs.EM_GETEVENTMASK, 0, IntPtr.Zero);
return eventMask;
}
This function prevents redrawing while you are working on the text, after you finish editing, you should call
public void EndUpdateAndResumeEvents(IntPtr eventMask)
{
// turn on events
User32.SendMessage(this.Handle, User32.Msgs.EM_SETEVENTMASK, 0, eventMask);
// turn on redrawing
User32.SendMessage(this.Handle, User32.Msgs.WM_SETREDRAW, 1, IntPtr.Zero);
NeedRecomputeOfLineNumbers();
this.Invalidate();
}
Double buffering does not solve this problem because it will not stop the paints from occurring, highlighting an editor without disabling the paint event can cause the program to halt for more than 5 minutes depending on the size of the file and the number of words to be highlighted.

How to detect a specific System Tray Popup/Tooltip

I need to detect a specific Windows System Tray Tooltip/Popup (USB Device Not Recognized). I don't seem to be having much luck polling with FindWindow. Is there a hook or something that will show me each one that pops up?
I have managed it doing the following:
HWND HMyTooltip = NULL, HNew = FindWindow( "tooltips_class32", NULL );
// Cycle through all visible tooltip windows looking for the one we want
while (HNew && !HMyTooltip)
{
if (IsWindowVisible(HNew))
{
HMyTooltip = HNew;
// If you want to find a particular tooltip, check the text (Note: GetWindowText doesn't work)
SendMessage( HMyTooltip, WM_GETTEXT, ARRAYSIZE(Title), (LPARAM)Title );
if (_strnicmp( Title, "USB Device Not Recognised", 22 ) != 0)
HMyTooltip = NULL;
}
HNew = GetWindow( HNew, GW_HWNDNEXT );
}

Resources