OS X Quartz Events and the usage of some event flags - c

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.

Related

X11 drawing on resize [duplicate]

I'm writing a program that has an X11/Xlib interface, and my event processing loop looks like this:
while (XNextEvent(display, &ev) >= 0) {
switch (ev.type) {
// Process events
}
}
The problem is when the window is resized, I get a bunch of Expose events telling me which parts of the window to redraw. If I redraw them in direct response to the events, the redraw operation lags terribly because it is so slow (after resizing I get to see all the newly invalidated rectangles refresh one by one.)
What I would like to do is to record the updated window size as it changes, and only run one redraw operation on the entire window (or at least only two rectangles) when there are no more events left to process.
Unfortunately I can't see a way to do this. I tried this:
do {
XPeekEvent(display, &ev);
while (XCheckMaskEvent(display, ExposureMask | StructureNotifyMask, &ev)) {
switch (ev.type) {
// Process events, record but don't process redraw events
}
}
// No more events, do combined redraw here
}
Which does actually work, but it's a little inefficient, and if an event arrives that I am not interested in the XCheckMaskEvent call doesn't remove it from the queue, so it stays there stopping XPeekEvent from blocking, resulting in 100% CPU use.
I was just wondering whether there is a standard way to achieve the delayed/combined redraw that I am after? Many of the Xlib event processing functions seem to block, so they're not really suitable to use if you want to do some processing just before they block, but only if they would block!
EDIT: For the record, this is the solution I used. It's a simplified version of n.m.'s:
while (XNextEvent(display, &ev) >= 0) {
switch (ev.type) {
// Process events, remember any redraws needed later
}
if (!XPending(display)) {
// No more events, redraw if needed
}
}
FWIW a UI toolkit such as GTK+ does it this way:
for each window, maintains a "damage region" (union of all expose events)
when the damage region becomes non-empty, adds an "idle handler" which is a function the event loop will run when it doesn't have anything else to do
the idle handler will run when the event queue is empty AND the X socket has nothing to read (according to poll() on ConnectionNumber(dpy))
the idle handler of course repaints the damage region
In GTK+, they're changing this over to a more modern 3D-engine oriented way (clean up the damage region on vertical sync) in a future version, but it's worked in the fairly simple way above for many years.
When translated to raw Xlib, this looks about like n.m.'s answer: repaint when you have a damage region and !XPending(). So feel free to accept that answer I just figured I'd add a little extra info.
If you wanted things like timers and idles, you could consider something lke libev http://software.schmorp.de/pkg/libev.html it's designed to just drop a couple of source files in your app (it isn't set up to be an external dependency). You would add the display's file descriptor to the event loop.
For tracking damage regions, people often cut-and-paste the file "miregion.c" which is from the "machine independent" code in the X server. Just google for miregion.c or download the X server sources and look for it. A "region" here is simply a list of rectangles which supports operations such as union and intersect. To add damage, union it with the old region, to repair damage, subtract it, etc.
Try something like the following (not actually tested):
while (TRUE) {
if (XPending(display) || !pendingRedraws) {
// if an event is pending, fetch it and process it
// otherwise, we have neither events nor pending redraws, so we can
// safely block on the event queue
XNextEvent (display, &ev);
if (isExposeEvent(&ev)) {
pendingRedraws = TRUE;
}
else {
processEvent(&ev);
}
}
else {
// we must have a pending redraw
redraw();
pendingRedraws = FALSE;
}
}
It could be beneficial to wait for 10 ms or so before doing the redraw. Unfortunately the raw Xlib has no interface for timers. You need a higher-level toolkit for that (all toolkits including Xt have some kind of timer interface), or work directly with the underlying socket of the X11 connection.

Drawing in WM_MOUSEMOVE

Good day,
What is best practice for drawing in mouse movement?
I see many examples (at MSDN also) when drawing is performed in WM_MOUSEMOVE.
But I think that better approach is all drawing in WM_PAINT.
Example:
Version 1
case WM_MOUSEMOVE:
{
DummyFunctionForClientCoords();
DummyFunctionForDrawing();
}
break;
Version 2
case WM_MOUSEMOVE:
{
DummyFunctionForClientCoords();
InvalidateRect(hwnd, &rc, TRUE); /* For sake of simplicity, update region is all area. */
}
break;
case WM_PAINT:
{
DummyFunctionForDrawing();
}
break;
Maybe this question is opinion based, but I want know advantages and disadvantages Version 1 vs. Version 2.
Unless you have a striking reason not to, rendering should always be performed in a WM_PAINT handler. A WM_PAINT message is generated on demand, if the update region is non-empty and there are no other higher priority messages in the message queue. This has two immediate consequences:
Input messages are handled before (potentially costly) rendering happens. This leads to a more responsive UI.
Multiple calls to InvalidateRect are coalesced into a single WM_PAINT message. This reduces overall cost of rendering.
The code you posted under Version 2 is able to profit from the system provided optimizations.
A disadvantage of Version 1 is, that whatever it renders to the screen will be overwritten, when the system decides to generate a WM_PAINT message. It is both more wasteful, and potentially doesn't render the desired result.
Not specifically asked in the question, but if you need higher-precision mouse move events than those coalesced into a single WM_MOUSEMOVE message, you can call GetMouseMovePointsEx to get up to 64 previous (intermediate) mouse pointer positions.

Patch scrolling back in suckless ST terminal to support mouse wheel

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.

Ncurses mouse wheel scroll up

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.

g_signal delays (C, GTK+)

I've got a little GTK-Application with two buttons (A, B) and a drawing area (C).
When I click on A, C's size should be recalculated and set with gtk_widget_set_size_request(). This will cause an expose-event, whose handler will calculate some data. Further, the click on A will emit a clicked signal at B, whose handler needs the data calculated by C's expose-event.
In fact everything works fine, but the expose-event delays somehow, and the clicked handler is called before and the data (you may guess it) is missing.
a_handler() {
new_size = calculate_size();
gtk_widget_set_size_request(C, new_size); //Will cause expose-event
g_signal_emit_by_name(B, "clicked");
}
b_handler() {
calculate_something(data); //Error
}
c_handler() {
draw_something();
data = calcluate_data();
}
What can I do?
Gtk (and most other GUI toolkits) does the painting and event handling all in one thread. Therefore when the expose event is emitted, it goes into a queue and will be handled only after a_handler returns.
The best approach in my opinion would be to move the calculation somewhere else, if there is not some good reason to tie it into GUI drawing. For example, there could be a separate method calculate_data that is called both from b_handler and c_handler.
The next best way is to call gdk_window_process_updates to force the expose event to be handled immediately:
http://developer.gnome.org/gdk/stable/gdk-Windows.html#gdk-window-process-updates
The ugly fix is typically to add calls to gtk_main_iteration(), for instance between the call to gtk_widget_set_size_request() and the signal-emission.

Resources