I've fought for a couple of hours with a bug due to a behavior of SDL2 of which I didn't know anything.
In particular, I didn't know that, on mobile, whenever the user touches the screen, two events are sent:
The first one was quite obvious to me: a finger down event.
The second one was indeed less obvious: a mouse button down event.
The same applies for the finger up/mouse button up events.
Because of them, an internal command was thrown twice giving me an headache.
The target is to support both mobile and desktop environments for reasons that are beyond the purpose of the question.
Also, I can guess SDL2 works like that in order to support smooth migration of already existent codebase.
Anyway, is there a (let me say) SDL2-way to inhibit the mouse related events on mobile?
Honestly, they don't make much sense from my point of view and I would like to get rid of them, unless the software is executed on a desktop environment.
Also, I don't want neither to use compile time parameters nor to have dedicated parts of code the aim of which is to suppress those events on mobile.
The code is quite simple. Below a (maybe) meaningful, reduced example:
SDL_Event ev;
while(SDL_PollEvent(&ev)) {
switch(event.type) {
case SDL_FINGERDOWN:
// read it and throw an internal event E
break;
case SDL_MOUSEBUTTONDOWN:
// read it and throw an internal event E
break;
}
}
Unfortunately, both the events above are read when the user touches the screen, as explained.
* EDIT *
I didn't mention that I was testing my application on an Android device and I'm far to be sure that the same problem arises on iOS.
See the response below. It seems indeed that the issue (that so far I've understood it is not exactly an issue) is mainly due to the way SDL2 treats by default finger events on Android.
Even though I really like the idea of Christophe to add an event filter, I've found that SDL2 already gives support for this problem in terms of an hint on Android.
In particular, there exists the hint SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH.
One can set it by means of the function SDL_SetHint. See here for further details.
It's as simple as:
SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1");
As from the documentation of the hint, by default it is set to 0 and that means that:
mouse events will be handled as touch events and touch will raise fake mouse events
That's true, it was my problem, but by setting it to 1 we can get what follows:
mouse events will be handled separately from pure touch events
So, no longer fake mouse events on Android devices.
The reason behind the default value is not so clear to me, but this one sounds really like the right way to achieve it.
EDIT (more details)
This change seems to be recent.
Here is a link to the libsdl forum where they were discussing the issues that arose as a consequence of the patch that introduced this behavior.
Someone had the same problem I had and some others were trying also to explain why the patch had been accepted.
EDIT: alternative solution
The hint SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH is available since SDL v2.0.4, so it seems that the only viable solution for lower versions of SDL2 is to use an event filter.
Anyway, I discourage to query the platform by using SDL_GetPlatform in order to decide if to set or not to set an event filter.
Instead, as from the documentation of both SDL_MouseMotionEvent and SDL_MouseButtonEvent, there exists the which parameter that:
[...] may be SDL_TOUCH_MOUSEID, for events that were generated by a touch input device, and not a real mouse. You might want to ignore such events, if your application already handles SDL_TouchFingerEvent.
Because of that, I suggest to set an event filter no matter of what's the underlying platform, thus to queue the events or to filter them if needed.
Unfortunately, there is no such platform specific deactivation parameter.
The cleanest way to do it would hence be in the initialisation code to query for the platform with SDL_GetPlatform() and, if mobile, set an eventfilter with SDL_SetEventFilter() which prevents the mouse events from being queued.
It's not exactly the answer you expect, but I see no other sdl alternative.
A simpler approach, if you control the code of your event loop, would be to set a flag instead of an event filter, and if the flag is set do nothing on the mouse event. This second approach is however not so clean, as you have to take care of platform specific behaviour in all your code, whereas it's much more isolated in the first alternative.
Related
In Windows 7(I am not sure about other OS) when you are on a webpage, pressing the space-bar scrolls a few pixels down the page. But when you are in an interface where typing can be done(like an input element, textarea, word editor, code editor, search bar, etc), pressing the space-bar obviously types a space.
Similarly, when all the open windows or menus are minimized, and you are viewing the desktop, and you press a letter key, instead of the letter being typed somewhere, a beep sound is produced.
This shows that the availability of a typing functionality can be "detected". And if it can be detected, it can most likely be done so using C++.
I don't know what to call this. I tried to find out using google but everything I got seemed unrelated to this. I was probably not using the correct keywords.
Whatever this is, I am creating a C++ program where I need to be able to detect it(in an if condition). Something like this
if (/*typing can be done*/) {
//Do something..........
}
Or this
if (/*typing can NOT be done*/) {
if( GetKeyState(VK_SPACE) & 0x8000 ) {
//Do something..........
}
}
And I need to be able to do so natively. Not specific to a particular console window or UI.
If you can help me in any way in figuring this out than please do so. And please feel free to make or suggest relevant edits to improve this question and make it less vague and more detailed and to-the-point.
The functionality you describe belongs to the program running the window with focus, not to the operating system (although the operating system will, at least in part, ultimately power that functionality). It shouldn't come as a surprise that programs can detect keystrokes, because otherwise you wouldn't be able to use your keyboard to input any characters into your computer.
However, you cannot just "detect" a random event with an if statement. "if" is not "when". Your computer will not repeatedly check all if statements in your program and jump to that location in the code whenever one matches. Imagine the chaos!
A program sufficiently complex to have a graphical interface almost certainly has an "event loop", be this in its own code or buried within an API call (as in the case of native Windows applications); such an event loop typically polls for keys being sent to the window(s) managed by the program. If you do not have an event loop (and if your operating system cannot generate a "signal" when a keystroke otherwise goes unhandled), you will have to make one.
Exact specifics are beyond the scope of a Stack Overflow answer, but by pointing you in the direction of a textbook about how to create graphical programs, I am enabling you to discover how input and output is handled in those cases.
I'm writing a program in C++ to implement the keyboard backlight feature from OS X on MacBook Pro's running a Linux distro. So far, it turns the backlight on, on boot and if no keyboard and mouse events are registered for 20 seconds, it will turn it back off, and of course turn it on yet again when an event is registered. Next thing I need the program to do, is to capture keypresses on the keyboard-backlight-up/down keys, but I'm not sure how to approach this.
I am currently using XScreenSaverQueryInfo to get the idle time of keyboard and mouse events, so a method using X11 API would be okay. I have done a lot of googling but havent found a way that I felt sure about going with. The problem I'm seeing with lots of the methods I found, is that they use keycode to identify the key, but I dont think that would be a viable solution since the program should work for any keyboard-layout available.
Any idea of a method and API I should go with? What would work the best?
Regards,
The normal way to do this is with XGrabKey(). It uses keycodes, but you wouldn't hardcode the keycode, you'd get it with XKeysymToKeycode(). To be more correct you'd also want to redo the grab when you get a MappingNotify (XMappingEvent). (Note, MappingNotify, not MapNotify.) If there isn't a keysym for these keys - there probably isn't on old X versions, but hopefully newer X.org versions have one - then you just have to hardwire the keycode. Which won't be very robust or portable but probably works for everyone on Linux with the same hardware model.
Be prepared that key grabs are global, so if you try to XGrabKey() and something else has already grabbed that key, you'll get an X error - by default that exits the program. Another quirk of XGrabKey() is that it grabs the key with a precise modifier set. For example, to handle both with and without NumLock, you need to grab twice. See Global Hotkey with X11/Xlib
In a normal Linux setup (if you wanted to get a feature like this into upstream projects), the desktop environments don't want lots of separate apps fighting over the key grabs and getting errors. So there will be some central coordination points, such as the window manager or a special daemon might do all the keybindings and forward commands to other processes as needed. So you would probably want to look at patching the same upstream code that handles other special keys like this, if you were trying to get your feature integrated into distributions by default.
Another thing to be aware of is the Xkb API, which is a lot more complicated. There is some brain-bending way to grab keys with Xkb but I don't know of any advantage to going that route.
If you haven't done that yet, familiarize yourself with xev. Start it, give it the focus, and press the keys, to see what's happening.
i'm writing some low level window code for a window in x (in c++), and I want to prevent the user from either maximising or minimising the window. i don't mind whether this is done by rejecting the request to resize, or by removing the buttons themselves. however, i am tied to x and can't use qt or other higher-level libraries which i know provide this functionality.
at the moment all i have managed to do is intercept the ResizeRequest event and then set the window size back using XResizeWindow... but this causes the window to momentarily maximise and then return to its original state. is there a way to directly reject a ResizeRequest, that would seem to be the proper way to handle this but a fair bit of googling and document trawling has not come up with a solution.
thanks,
james
you can't.
essentially you would fight like hell against the window manager (and against the user in the end).
eg, you could watch PropertyNotify events to check if your window (or rather the window your window is attached to (provided by the window manager)) gets minimized. and then you unminimize it. and then the user minimizes it, or the window manager. technically, you can fight against it, but i would strongly advise against it.
that said: you can try to give the window manager some hints about what you think is appropriate for the window. see http://standards.freedesktop.org/wm-spec/1.3/ar01s05.html#id2523223:
_NET_WM_ALLOWED_ACTIONS
is a property the window manager manages per window (to tell other tools what is possible with that window). one of such actions is
_NET_WM_ACTION_RESIZE indicates that the window may be resized.
(Implementation note: Window Managers can identify a non-resizable
window because its minimum and maximum size in WM_NORMAL_HINTS will
be the same.)
so, if your users are using a window manager which interpretes WM_NORMAL_HINTS correctly and drops any resizing, maximizing, minimizing: then you can feel lucky.
what do you really want to achieve? some kind of kiosk-mode? some kind of fair-trade mode where people walking by can not "shutdown", close, resize, fiddle around with the app you are presenting?
if so: consider running a xsession without any window manager involved at all. just start your app as big as you need it and done.
Technically you can't prevent anything, as WMs can do whatever they want, but most reasonable window managers will let you control this.
The preferred modern way to do it is to set _NET_WM_WINDOW_TYPE semantic type if any of those are applicable. For example, in many WMs a dialog type may imply not-maximizable.
http://standards.freedesktop.org/wm-spec/1.3/
It sounds like none of these apply to your app though probably, so you'll have to set the specific hints.
To avoid maximization you just want to make the window not-resizable. As you've discovered, "fighting" the resize by just resizing back is a Bad Idea. It has infinite loop potential among other things.
XSetWMSizeHints() is the correct way to avoid maximization. Set min size = max size. voila, not resizable.
To avoid minimization, you have to use a bit of old legacy cruft called the Mwm hints. Unfortunately this involves cut-and-pasting a struct definition and then setting a property to the bits of the struct.
I just googled for MWM hints docs, and one of the results is me suggesting documenting them, 9 years ago ;-)
http://mail.gnome.org/archives/wm-spec-list/2001-December/msg00044.html
Unfortunately, none of the results are actual docs.
You can likely figure it out from http://git.gnome.org/browse/gtk+/tree/gdk/x11/MwmUtil.h and gdk_window_set_mwm_hints() http://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkwindow-x11.c#n4389
MwmUtil.h is the struct that's cut-and-pasted everywhere (into most WMs and toolkits).
The _NET_WM_ALLOWED_ACTIONS hint is set on your window by the WM indicating which features the WM has decided to put on the window. The main purpose of this hint is that pagers and task lists and other desktop components can then offer the matching actions for the window.
The specs that cover all this are the ICCCM (old spec, still mostly valid) and EMWH (new extensions and clarifications, since ICCCM left lots of things unaddressed).
For gory details, try the source code... for example recalc_window_features() in metacity's window.c file, currently on line 6185 http://git.gnome.org/browse/metacity/tree/src/core/window.c#n6185
A philosophical adjustment when coding for X: mileage will vary with window manager. The "mainstream" ones lots of people use generally will follow the specs and work about as you'd expect. However, there are all kinds of WMs out there, some broken, others deliberately quirky. The worst thing you can do is try to "fight" or work around the WM, because basically all ways of doing that will end up breaking the app when running with a sane WM. Your best bet is make things follow the specs, work with the normal WMs, and if you get users upset that they can resize your not-resizable window because their WM allows that, you just have to tell them to complain to whoever provides that WM. The whole point of the pluggable WM design is that the WM determines some of this behavior, rather than the app.
Good luck. Modern X is pretty complex and coding Xlib with no toolkit is kind of asking for things to be... not quite right. But you can probably get it going well enough. :-P
It's an old question, but, there is an unofficial, yet supported by most Window managers way to do such things - _MOTIF_WM_HINTS.
Look here: Disable actions, move, resize, minimize, etc using python-xlib for sample code.
I am writing a simple Windows app in c++, that will be able to send commands to windows media player. My problem is that I want my app to move to the previous song in the playlist.
IWMPControls::previous() seems to do the job, but its behavior differs from what is written in msdn. In fact this function rewinds current media to the beginning and then (if current position is less than 2-3 seconds) it switches to the previous song.
I would like to implement two different buttons (please, don't ask me why :)) - one for rewinding to the beginning, and one - to moving to previous song. Is there any easy way to do this through IWMPControls (or any other WMP-related COM interface)?
p.s. I could handle this if I could get the position (index) of the current song in the list. But as far as I read MSDN, it seems to me that there is no easy way to get the current item index from playlist...
I think, the easiest way to control a WMP application from outside is by sending messages. So, you stick to basic WinAPI and you have to get your WMP window handle.
After you've retrieved it's handle, it's easy to transfer certain commands to it using plain Windows messages.
Basically, you just invoke SendMessage to retrieved earlier HWND wmp_windows_handle. The control messages are generally a WM_COMMAND messages where a wParam specifies what you want your player to do.
For example, Stop command can be transfered if you specify 0x00004979 as your wParam.
Stick to Google or Windows Media Player SDK for more specific information on these command codes and you'll definitely find what you are looking for.
Also to mention, I'm not proficient with that IWMPStuff you described above, so if I were you and I wanted a concrete answer about it, I would probably refer to it's SDK.
Well, I think I figured it out. You can force the previous song by 1) first calling IWMPControls::put_currentPosition(0.0), 2) then calling IWMPControls::previous().
There can be some problems, as it seems that some time must pass between 1) and 2). The obvious solution is to use ::PostMessage() inside your program (NOT ::PostMessage to WMP), so you make step 1), then PostMessage and, while processing your message, make step 2).
Basically what I am trying to do is write my own pseudo task bar in C++. The program needs to idle until another program is started up, at which point it needs to visually depict that the other program is running. For each other program that is running, the user should be able to click on the visual representation and have Windows switch focus to the selected program.
The big underlying question at this point: is this even a possibility? Or has Windows hidden most/all of its fiddly-bits to make this close to, if not completely, impossible?
[EDIT:] restructured the question
The obvious starting point would be SetWindowsHookEx(WH_SHELL,...); which will get you notifications when top-level windows are created or destroyed (along with some other related events, like a different window being activated, a window's title changing, etc.)
Think ahead to actually bringing the window to the front, as I once researched myself.
SetForegroundWindow() won't work unless issued from the foreground process - neither SwitchToThisWindow() nor the AttachThreadInput() kludge seemed to always work, but maybe I just wasn't doing it right. Anyway as far as I know there no way to make a window foreground as good as Windows does, please enlighten me if say you discover say an undocumented call which actually Works.
It seems possible to me at least in a basic way:
1. Set up a shell hook as described by Jerry
2. figure the executable file from the module handle to access it's icons using shell services
The Vista-like feature of keeping a 'live' miniature of the screen seems much more challenging.