I want to handle scroll with the mouse wheel using ncurses but I am having a problem similar to this issue :
http://lists.gnu.org/archive/html/bug-ncurses/2012-01/msg00011.html
Besides, mouse wheel-up event is only reported as mask 02000000
(BUTTON4_PRESSED) just one time, even if I scroll the wheel continuously.
I tried ncurses 5.7 to 5.9 on debian 5,6,7 and archlinux.
Every single ncurses lib had NCURSES_MOUSE_VERSION 1, tried recompiling with --enable-ext-mouse.
Scrolling down works perfectly, ncurses reports multiple REPORT_MOUSE_POSITION 0x8000000 per scroll and a single BUTTON2_PRESSED 0x128.
Scrolling up causes only a single report of BUTTON4_PRESSED 0x80000
MEVENT event;
mousemask(BUTTON1_CLICKED|BUTTON4_PRESSED|BUTTON2_PRESSED, NULL); // Tried with REPORT_MOUSE_POSITION also
while(run)
{
switch(in = getch())
{
case KEY_MOUSE:
if(getmouse(&event) == OK)
{
else if (event.bstate & BUTTON4_PRESSED)
line_up();
else if (event.bstate & BUTTON2_PRESSED || event.bstate == 0x8000000)
line_down();
}
break;
}
}
Add mouseinterval(0); somewhere outside of your main loop. (Perhaps right after keypad(stdscr, TRUE);)
This command causes there to be no delay with mouse events, so you won't be able to detect BUTTON1_CLICKED or BUTTON1_DOUBLE_CLICKED and similar things (though you can implement that yourself by keeping track of BUTTON1_PRESSED, BUTTON1_RELEASED, and the time between mouse events).
A small caveat though, when I tested this with C everything worked, except that getmouse returned ERR on scroll wheel down events. This could potentially still be useful though, as it was the only event which gave this result. When I tested the same code in Rust it worked perfectly though, so your mileage may vary.
ncurses5 does not support wheel mouse, except as an optional feature. That is because the layout of bits in mousemask_t chose in the mid-1990s left insufficient space for a fifth mouse-button. At the time, some other devices (for playing games) seemed more important; this was before X provided a protocol for wheel mice.
The "extended mouse" is an optional feature (since it would change the application binary interface), and has not been incorporated in ncurses5 packages, although it has been available for some time.
For reference, see the discussion of --enable-ext-mouse in the ncurses changelog, starting in 2005.
ncurses6 does support wheel mouse (see release notes). Perhaps that will be standard in Debian 9.
Related
I've written a program in C that activates commands when the user flicks from the edges of the screen. For instance, flicking upward from the bottom edge brings up the keyboard. This portion of my code is working fine.
The issue I am having is that the very making of the flicking motion also interrupts applications, as one's fingers need to drag across some of the screen to activate the trigger. I don't want this action to affect apps that are on screen while the user flicks the screen edge.
I would like to add some C code that will temporarily mask touch events. I can handle the code that activates the masking properly (such as events which originate from the edges of the screen) and when to unmask.
I can handle all of the above with exception to the code that does the masking and unmask of the touch events. I am not asking for a full complete code but just a pointer in the right direction. I would like to know what library to use and the appropriate command which does the masking.
I'll not post the code as it is a couple hundred lines long and would surely lead to straying from the question; the code works fine, aside from the issue above.
I am on a Raspberry Pi 3b+ with Rasbian OS and an Official Raspberry Pi 7" touch screen. The main C libraries which I am using for the program are linux/input.h and X11/extensions/XTest.h.
I will supply any additional info if asked.
* EDIT *
Finally figured it out! The biggest issue what finding what to search for...
I masked the pointer/touch events with the following command:
XGrabPointer(dpy, root, False, PointerMotionMask, GrabModeSync, GrabModeAsync, None, None, CurrentTime);
In the code above, the touch motion is masked (PointerMotionMask), the pointer/touch for windows is masked (GrabModeSync), and the keyboard key events are not masked (GrabModeAsync).
To unmask, I used these commands:
XQueryPointer(dpy, RootWindow (dpy, 0),
&event.xbutton.root, &event.xbutton.window,
&event.xbutton.x_root, &event.xbutton.y_root,
&event.xbutton.x, &event.xbutton.y,
&event.xbutton.state);
usleep(10000);
XUngrabPointer(dpy, CurrentTime);
usleep(10000);
XQueryPointer(dpy, RootWindow (dpy, 0),
&event.xbutton.root, &event.xbutton.window,
&event.xbutton.x_root, &event.xbutton.y_root,
&event.xbutton.x, &event.xbutton.y,
&event.xbutton.state);
I'm still learning Xlib, so I don't entirely know why one needs to add usleep and XQueryPointer, but I found that it's needed or the program is unpredictable. I merely copied this type of code from my buttonPress() function. I couldn't find any complete, simple, and clear answer, so a lot of try/fail was required on this one.
Now, I am able to swipe from the edges on my Raspberry Pi touchscreen, and there is no interruption to the currently active window.
If anyone wants to see the code, just ask and I'll post it in full. And if anyone knows how this code works and why I need to add usleep and XQueryPointer, I'd like to hear.
Sources used:
X11: will XGrabPointer prevent other apps from any mouse event?
https://tronche.com/gui/x/xlib/input/pointer-grabbing.html
I'm implementing virtual keyboard that is using modifier flags to enable input key events with this modification keys like: cmd, alt/opt, shift.
I would like to know two things:
what is the aim of kCGEventFlagMaskNonCoalesced and kCGEventFlagMaskNumericPad, can I map them to any key defined in kVK_* key codes?
What is the difference between kCGEventFlagMaskAlphaShift, kCGEventFlagMaskShift and how they corresponds to kVK_Shift, kVK_RightShift?
Is kCGEventFlagMaskSecondaryFn corresponding to kVK_Function?
I have done my modifier keys to modifier flags mapping function like this:
static uint64_t mod_key_code_to_mod_flag(uint16_t mod_key_code) {
switch(mod_key_code) {
case kVK_Shift:
return kCGEventFlagMaskAlphaShift;
case kVK_RightShift:
return kCGEventFlagMaskShift;
case kVK_Control:
return kCGEventFlagMaskControl;
case kVK_Option:
case kVK_RightOption:
return kCGEventFlagMaskAlternate;
case kVK_Command:
return kCGEventFlagMaskCommand;
case kVK_Help:
return kCGEventFlagMaskHelp;
case kVK_Function:
return kCGEventFlagMaskSecondaryFn;
default:
return 0;
}
}
Is it complete?
The purpose of kCGEventFlagMaskNonCoalesced isn't easily searchable at this point in time. Since one point of this site is to archive information necessary for answers, here is the definition of mouse coalescing in Cocoa (well, Carbon) from earlier documentation for IsMouseCoalescingEnabled:
If mouse coalescing is enabled, intemediate [sic] mouse movement events are merged into the most recent event, so that only one mouse moved or mouse dragged event is in the event queue at any time. For example, when the user moves the mouse across the screen, more mouse moved events are generated than most applications care about. Rather than place all these events in the queue (which would probably slow down the application), the Carbon Event Manager first checks to see if a mouse moved event already exists. If if does, that event is updated with the position and delta information from the more recently-generated event.
For some reason, current documentation leaves out this definition (the mouseCoalescingEnabled property might no longer be supported, even though it's in the documents). It's intended for consumers of mouse events. If your virtual keyboard isn't generating mouse events, this modifier can be largely ignored.
The ST terminal has a patch for scrolling back. I want to update said patch to enable mouse wheel up and down signals in additions to "PageUp" and "PageDown". I suspect that a small change in config.h is what is needed but I have no experience in terminal code thus my plea for help.
In the source code, in config.h these lines appear:
static Mousekey mshortcuts[] = {
/* button mask string */
{ Button4, XK_ANY_MOD, "\031" },
{ Button5, XK_ANY_MOD, "\005" },
};
So, clearly, we know what Button4/5 are. In addition, we have these:
static Shortcut shortcuts[] = {
/* mask keysym function argument */
[...]
{ ShiftMask, XK_Page_Up, kscrollup, {.i = -1} },
{ ShiftMask, XK_Page_Down, kscrolldown, {.i = -1} },
};
So, naively, I a assuming that adding another two raw (one for wheel up, one for wheel down) would do the trick. However, what?
Note: I know that suckless recommends using a terminal multiplexer such as tmux. I use that already. However, sometimes (rarely) I just want to use a terminal without tmux and this feature would be useful. Please do not comment/answer to use tmux, this is not what this question is about.
It is not that simple. This question occasionally arises when someone wants left/right scrolling for a mouse trackball.
On the left column of the tables is an X event. Those are limited to combinations of predefined symbols.
Button4 and Button5 are mentioned because those are conventionally used to pass the mouse wheel events. That has been the case for quite a while; there was a resource file used before modifying xterm in 1999 (patch #120) to make this a built-in feature.
The possible X events are laid out in C header files — X.h — and tables in the X source code; no wheel mouse events are provided for as such. For instance, there is a table in the X Toolkit library which lists all of the possibilities (for clients using X Toolkit such as xterm). xev uses the header-definitions.
If X were to support wheel mouse events in a different way, it would probably use new function calls for this purpose since the existing information may be packed into bit-fields in a way that precludes easy extensibility.
There is now a standalone program scroll that provides scrollback buffer for any terminal emulator. At the time of writing this answer, it is still in an experimental state, a lot of bugs are expected. In spite of that, it already handles scrollback better than the scrollback patches for st. E.g. resizing the terminal will wrap previous output instead of cut off and lose them.
To enable it, first of course download/clone the source code from suckless website and build it locally.
Then modify this line in config.def.h of st (you have to fetch the recent git commits to get support for scroll)
char *scroll = NULL;
to
char *scroll = "/path/to/scroll";
Now rebuild st, and run st. It will automatically use scroll to provide the scrollback buffer.
As stated in the manual, another way without modifying st's source code is to run st with the following command after you have installed both st and scroll:
/path/to/st -e /path/to/scroll /bin/sh
From the suckless site, there are some scroll back patches that allow scrolling using Shift+MouseWheel as well as full mouse scroll. The last patch might break other mkeys excluding scrolling functions.
void myDisplay(void) //glutDIsplayFunc(mydisplay)
{
while(1)
{
glClear(GL_COLOR_BUFFER_BIT);
x=rand()%680;
y=rand()%680;
sx=(x-p)/100;
sy=(y-q)/100;
glColor3f(0.7+sx,0.1-sy,0.6);
for(g=0;g<120;g++)
{
p+=sx;
q+=sy;
glBegin(GL_POINTS);
glVertex2i(p,q);
glEnd();
glutSwapBuffers();
}
}
}
This code just chooses one arbitrary point on screen and do smooth translation.
I compiled this same code in visual C++ and on linux and I noticed that the translation (from one point to another) happens fast on windows while on linux it drags slow.
why this is so?
Your are using a movement vector which is totally independent of the fps. This means that it will run with a different speed on a different machine.From your description I guess that on your Linux machine, sync to vblank is enabled, limiting your framerate to the refresh rate of the display (typically 60Hz), while on the windows machine, it is disabled, running with a much higher frequency.
You should use a timer to control animations, and define your animation speeds in sapce-units per time-unit.
Furthermore, you should follow Andon M. Coleman's advice: The GLUT display callback is mean to draw a single frame. If you want an animation over many frames, use some variables to store your current state (for example, the current position and direction vector) and update them for each step. The way you currently implemented it, GLUT's event handling will by blocked for the whole duration of the animation. On windows, this might even trigger "the application is not responding" warning, when your animation takes too long.
This happens when compiling for Any Cpu as well as compiling to x86. Sections of the GUI doesn't redraw unless it's resized, for instance if the main form is maximized some of the controls don't resize with it, and others have sections that don't redraw and displays the what was previously there.
This works fine on 32-bit machines, both XP and Vista, but on 64-bit Vista (don't have x64 XP to test with) the redrawing just isn't working properly.
Anyone have any ideas on where to start tracking this down?
Edit: This occurs on 2 separate machines, and at least the one I'm currently on has the latest drivers from NVidia.
Edit2: Running a 32-bit XP virtual machine on my 64-bit machine and the application doesn't exhibit the redrawing issue in the VM
Edit3: It may be a driver issue, but we don't know if or when drivers will fix the issue. A co-worker says there's fewer issues with an ATI card at home than with NVidia, but I've been updating my video drivers pretty much monthly for the past few months and it's still not resolved, so we can't just release our product and just tell our customers that some day the driver manufacturers may get around to fixing this.
Does anyone have any insight on what things to try to avoid? We're compiling as x86 and all our components are x86. I can't seem to reproduce this issue with any of the components in test projects, and I haven't heard anyone else report these issues on most of the the component forums, so it is fairly likely that it's something we're doing.
That sounds horribly like this problem.
When resizing windows on Windows you typically get a chain where each window receives a WM_SIZE message and then calls MoveWindow() (or similar) on its children which in turn receive a WM_SIZE and so on. I'm sure that .NET does the same thing under the covers.
On x64, Windows limits the depth of this nesting, and after a certain point (12-15 nested windows) it will just not send the WM_SIZE messages anymore. This limitation does not appear to exist on x86. This limitation affects both x86 and x64 code running on x64 versions of Windows.
This foxed us for ages, as different x64 installs would show different symptoms. The MSDN blog posting above has some possible workarounds - we ended up using a secondary thread to do the window sizes asynchronously, this solved the problem fairly neatly.
If you're using Windows Forms, it could be to do with nesting limitation issues on Windows 64-bit.
Details here: http://www.feedghost.com/Blogs/BlogEntry.aspx?EntryId=17829
In summary...
From the MS source, in Control.SetBoundsCore:
SafeNativeMethods.SetWindowPos(new HandleRef(window, Handle), NativeMethods.NullHandleRef, x, y, width, height, flags);
// NOTE: SetWindowPos causes a WM_WINDOWPOSCHANGED which is processed
// synchonously so we effectively end up in UpdateBounds immediately following
// SetWindowPos.
//
//UpdateBounds(x, y, width, height);
And from MSDN:
http://social.msdn.microsoft.com/forums/en-US/windowsuidevelopment/thread/25181bd5-394d-4b94-a6ef-06e3e4287527/
"A little investigation showed that Windows stops sending WM_SIZE
when it reaches some certain nesting
level. In other words, it won't send
WM_SIZE to your child windows if you
try to resize them when you process
WM_SIZE in the parent ones. Depending
on the USER stuff/updates/serivice
packs the maximum nesting level at
which it stops propagating WM_SIZE may
vary from 15 to 31 and even much
higher (effectively unreachable) under
latest XP 32bit/sp2.
But it still too little under XP x64 and still some similar ugly things
happen to other messages under some
builds of Vista.
So it is certainly a Windows bug."
You have two choices: either reduce the depth of your control hierarchy (the more ideal solution), or else derive "fixed" controls from each of the system ones that you use, as follows:
public class FixedPanel : Panel
{
protected override void SetBoundsCore( int x, int y, int width, int height, BoundsSpecified specified )
{
base.SetBoundsCore( x, y, width, height, specified );
if( specified != BoundsSpecified.None )
{
if( ( specified & BoundsSpecified.X ) == BoundsSpecified.None )
{
x = Left;
}
if( ( specified & BoundsSpecified.Y ) == BoundsSpecified.None )
{
y = Top;
}
if( ( specified & BoundsSpecified.Width ) == BoundsSpecified.None )
{
width = Width;
}
if( ( specified & BoundsSpecified.Height ) == BoundsSpecified.None )
{
height = Height;
}
}
if( x != Left || y != Top || width != Width || height != Height )
{
UpdateBounds( x, y, width, height );
}
}
}
I think the most likely cause of this problem is a redraw issue in your application. It's possible that there is a subtle windows message ordering difference on 64 bit that is exposing this issue in your code.
You can experiment with this by doing the following.
Add a timer to your application.
In the event handler call flakyControl.Update()
I would set the timer to something long like 5 seconds. Then run the application on Win64 and see if that fixes the issue. If so then the most likely cause is one of your controls is not properly signaling that it's been invalidated.
I would start with any custom controls in the application. Systematically add an Update call to every overriden method and event handler in the code. Eventually you'll find the one that fixes the issue and then you'll know where the bug actually is.
If you use the BeginInvoke() solution described on the MSDN blog make sure to disable docking of the children of the control that overrides OnSizeChanged(). I had Dock = DockStyle.Fill and had to change to DockStyle.None for the fix to work.
Sounds like a display-driver problem to me...
Try updating to the latest drivers and see if that fixes the problem? The 64/32 bit difference is probably a red-herring...
I would agree with Gordon. I've seen issues where brand new 64-bit machines had display issues with programs that looked fine under 32-bit, but would exhibit odd issues on 64-bit machines. Updating to the latest/recommended drivers almost always fixed the issue.
The fact that you can run the program on a virtual OS without issues suggests that it is a driver issue, because (at least in VirtualPC) the graphics card is emulated. This means that some things which the graphics card would normally handle is now done by the CPU, and thus not interacting with the graphics driver. Mind you that I'm not an expert on virtualization and I suppose the virtualization layer could affect the issue in other ways.
I believe this is related to the number nested HWND's in the tree. I don't know the specific details, but there were some restrictions placed on nested HWNDs with 64bit. The times I've seen it occur, I work around it by dropping back from the full vista basic (or aero) theme, to windows classic. At this point the issues go away.
Try switching to classic, and if that resolves it, see if you can reduce the number of nested HWNDs.