mouse buttons - my view from X11 upwards into Qt

Rick Stockton rickstockton at reno-computerhelp.com
Sun Feb 20 21:57:15 GMT 2011


PREAMBLE:
Hi. I'm the X11-oriented "mouse guy" whom Todd mentioned in his "last 
call for GSOC, what about shortcuts?" post (Topic #1 in Vol 95, Issue 69).

His focus is within KDE itself, while I'm focusing from the lower 
layers, moving "up" into KDE Development tools, API, and UI from those 
lower layers. (X11, the qt-X11 interface, and upwards into signal 
handling.) I have some ideas about Co-Requisite enhancements to the KDE 
System Settings Mouse/Pointer Module, and uses within Kwin, Shortcuts, 
and some other places. This email will NOT address those higher-level 
KDE modules. There's a lot of fundamental stuff, for which which I will 
need design advice, and I've been unable to get it so far. I'll be 
discussing those other areas in follow-up emails, if that's OK.

I'm going to need some direction from KDE visionaries, because there are 
four alternative "levels" at which we could do this. But first let me 
show the naming convention which I will be using.
"ButtonX" means the button number which gets emitted from X11. Here's 
the translation layout which I want to use. Please use it, because we'll 
get the numbers confused if some replies and new comments INCLUDE "wheel 
events" as numbered buttons, while others EXCLUDE the two pairs. And 
also, lots of existing hardware is built with "wrong" numbers.

   Button1 = "left button"
   Button2 = "right button", AKA "context menu button"
   Button3 = "middle button"
   Button4 = "scroll wheel up"
   Button5 = "scroll wheel down"
   Button6 = "tilt wheel left", AKA "scroll wheel left"
   Button7 = "tilt wheel right", AKA "scroll wheel right"
   Button8 = "back button", AKA "XButton1"
   Button9 = "forward button" AKA "XButton2"
  Button10 = first additional "gamer" button
  Button11 = 2nd additional "gamer" button
  Button12 = 3rd additional "gamer" button       ... and so on.

Within Qt, the Devs have recognized that Button8 and Button9 are 
frequently implemented "backwards". Thus they assigned the more cryptic 
names "XButton1" and "XButton2". But Qt has not considered the 
possibility of horizontal tilt wheels (or genuine horizontal wheels) 
implemented on a different pair. And unfortunately, many mice are built 
with "nonstandard" numbers. (Even products from a single manufacturer 
can vary. For example, Logitech emits 6/7 from some models, and 13/14 
from different ones- usually older models, but still in widespread use.)

Here are the 3 alternatives (within Qt4.x, using XI 1.5) which I've 
identified for KDE to build upon:

(A) Do absolutely nothing in Qt, simply enhance KWin, KDevelop, and etc. 
to "support" the buttons which Qt now provides.
(B) Add 3 more buttons (Button10 thru Button12), extending the defined 
enum and mask bits (Qt::MouseButton and QAt::MouseButtons) until they 
hit a byte boundary.
(C) Use 31, bytes.

- - - - -
ALTERNATIVE (A): DO NOTHING ALL IN QT.

I hate this approach, because it's manifestly easy and risk-free for 
even a child to "extend" Qt's bit definitions to at least a byte 
boundary. (With X11; I don't know about other platforms, such as Win32 
or OSX, or Symbian. And anyway, OSX support is broken with just 3 
buttons, and the authors of the Button8/Button9 updates didn't actually 
bother with doing the whole job: The automated testing code tools, among 
other "non-production" parts of Qt, still don't have them.




ALTERNATIVE (B): EXTEND SUPPORT FOR MORE BUTTONS, BUT ONLY TO THE 1ST 
BYTE BOUNDARY IN THE BUTTON MASK.

Add Button10 through Button12. That's a LOT of buttons (although my 
"test mouse", like most "gamer" mice, has even more). Very safe, with no 
possibility of compilers "doing the wrong thing".




ALTERNATIVE (C): DEFINE AND SUPPORT AT LEAST 31 POSSIBLE BUTTONS.

This is my recommendation, but it depends on something I don't know: The 
current enum for Qt::MouseButton defines all values as 32-bit hex values 
(with leading zeroes):

Qt::NoButton 	0x00000000 	The button state does not refer to any button 
(see QMouseEvent::button 
<http://doc.qt.nokia.com/4.7-snapshot/qmouseevent.html#button>()).
Qt::LeftButton 	0x00000001 	The left button is pressed, or an event 
refers to the left button. (The left button may be the right button on 
left-handed mice.)
Qt::RightButton 	0x00000002 	The right button.
Qt::MidButton 	0x00000004 	The middle button.
Qt::MiddleButton 	MidButton 	The middle button.
Qt::XButton1 	0x00000008 	The first X button.
Qt::XButton2 	0x00000010 	The second X button.


I think that an enumerated item with an explicit value will NEVER be 
compressed, even though a Compiler which wanted to squeeze an enum of 7 
items (defined without specific values) into a SINGLE BYTE would be free 
to do so. If my understanding is correct on all platforms, then we can 
safely use the entire Uint32. If it isn't, then we'd better stay with 
ALTERNATIVE-B. BTW, I don't want to define or support Button32 in Qt -- 
no existing mouse needs it, and it might be useful as some kind of flag 
bit within a migration of XI --> XI2.

Finally, let me describe the special "trick" which I'll be using within 
qapplication_x11.cpp, in order to offer an "ALMOST-reliable" Button 
State Mask. (As you know, Xinput 1.5 events provide a Button Sate Mask 
which is only one byte in length.) Credit for this suggestion goes to 
Daniel Stone: After receiving the event (and deciding not to ignore it), 
query the state of the core pointer buttons, and use the response to set 
the mask bits for higher-order buttons which are in "pressed" State. The 
information isn't absolutely reliable, because Event State precedes 
Query State in priority (within X11). We wouldn't want to do anything 
like this for pointer motion, or for keyboard ;) But mouse button 
states, especially after Qt has "compressed" the X11 wheel events before 
pushing them up into the state machine, remain constant for relatively 
long time. This makes a query-based mask pretty reliable -- at least in 
the *local* case, on a machine which isn't suffering CPU or memory problems.

In the remote case, maybe not so good... but I can't do better without 
moving to XI2. If the network and machines are really slow, then users 
will have to learn to hold down any high-order "modifier" mouse buttons 
until they see the App respond on their screen. And the I think that the 
situation of an App treating TWO concurrent high-order buttons as a 
unique event is going to be uncommon- and our doco should advise against it.

Because of the delay, and the lack of reliability, a User who really, 
really wants to get the FULL Button Mask should do so via a separate 
function call (new API). With Event and Standard Signals, I think that 
Qt should present Mask as now stands... with the reliable, low-order 
mask included (from X11, in Event State), but the higher order bits of 
other buttons zeroed out. This keeps it fast and efficient for 
programmers who aren't doing anything crazy.

- - - - -
This portion of "more mouse buttons", the part within Qt, isn't big 
enough for GSOC. Perhaps the KDE follow-ups are, and I will touch on a 
few in separate messages. I intend to write and fully document the Qt 
Updates myself, after I receive your comments and recommendation -- and, 
I hope, a similar input from a Qt person working in the "input devices" 
area. (I know that they have other, big things to think about, but I'd 
hate to do a bunch of work and be told "this isn't the right design" 
AFTERWARDS.) So, if you can link me up with such a Qt person, please do 
so. This is a REAL email address and a good contact point for me.

Thanks for reading, and all upcoming replies.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20110220/6fd31448/attachment.htm>


More information about the kde-core-devel mailing list