New on 01-Aug-2011: I have a way to support *ALL* MOUSE BUTTONS in Qt, while staying compatible wth the 4.x series!
-
Ignore the Poll, and the responses from June. This is all NEW.
I can provide FULL SUPPORT for all possible mouse buttons, 1-32, on x11 (and in the future, perhaps on Wayland and other plugins too.) This require the addition of 4 new functions to Qt's QMouseEvent class. Current functions and and data values, referenced in programs, remain 100% compatible with today -- there's no need for a "new compile".
(1) Qt would emit QMouseEvents (of type MouseButtonPress, MouseButtonRelease, and MouseButtonDblClick) for buttons emitting hardware Button Identifiers greater than 9. (Raw Button 9, an integer, corresponds to the enumerated name "XButton2".) All Buttons, with raw numbers as high as #32, would create such events. Implementation would use a new value in the current enumeration/flags byte. The value 'x00000080' (the uppermost unused bit) would be assigned as an indication that Qt::ButtonNumber () contains a value HIGHER THAN 12, and the programmer must invoke that new 'READ'-type function in order to obtain the Button Number which was responsible for the Event.
As a quick-and-dirty, I would also add raw Buttons 10 and 11 into the current mask, enum, and flags. (These would use values x00000020 and x00000040, respectively.) This is just like the adding of XButton1 ("BACK") and XButton2 ("FORWARD" ) in Qt 4.7, providing support for the next two buttons. (Persons with 4-button thumb layouts would benefit.) Programmers would not HAVE TO use the new function to work with these two buttons. Control Structure for these two, and all of the current buttons as well, can be written either way. (With tests based on enumerated values, OR the new way -- with tests based on the raw Qt::ButtonNumber () value.)
The READ function which becomes necessary for the programmer to obtain the "raw" button number shall be as follows.
*int QMouseEvent::ButtonNumber () const*
The integer value being provided is the Raw Button number which caused the most recent MouseButtonPress, MouseButtonRelease, or MouseButtonDblClick Event. (Occurrences of Buttons 4, 5, 6, and 7, which correspond to wheel motion, will never appear as the value, and will not modify the value which was value set by the most recent ButtonPress, MouseButtonRelease, or DoubleClick Event.)
Existing code, (i.e., code which uses the current enumeration to distinguish between buttons) could be re-written to use the function instead. The 'type safety' of the enumeration would be lost, but with cryptic names like "XButton2" appearing in current control structures, the code might read better. Use of integer values from the function are mandatory for the high buttons, of course.
A new function can be provided, returning a (full) 32-bit Button mask. A corresponding enumeration will be given names in the following way:
Qt::MouseButton1Mask (value = x00000001)
Qt::MouseButton2Mask (value = x00000002)
Qt::MouseButton3Mask (value = x00000004) ... and so on.An important difference between this mask and the current Qt::MouseButtons flags is the fact that this mask WILL include bits for the buttons which Qt translates into wheel events (I.e., raw buttons 4, 5, 6, and 7). Lower-level code presents all Buttons in the Mouse State mask, and we should present that data unchanged. Doing otherwise introduces some translation overhead (i.e., setting another mask with the 4 "wheel" button numbers left out, then doing a logical AND on the data from the Mouse Driver.) But it loses conceptual synergy in the minds of Qt programmers, and that's more important. (People read one thing in their mouse manuals, or online, but Qt takes the numbering scheme they just learned and turns it into something else completely different. Button8, the "BACK" Button, became 'XButton1' in Qt, and things magically shifted to numbers which weren't presented from the Driver. WHY?)
If others think that we should be able to support MORE than 32 buttons in the future, the design should be changed to allow for that possibility now: return at least one set of 32-bit mask values, but ALSO provide an integer count for the number of additional "CARD32" data segments being provided. I think that this isn't necessary, and it would create a need for the Qt programmer to de-allocate the structure which we return after the program has finished using it-- because such a variable-length return would have to be allocated and built dynamically.
Finally, the enhancement should provide WRITE Methods to set the otherwise-private Mask and ButtonNumber fields. These would support Qt-internal test routines (automatic and manual); Window Manager programming; and tests by Qt programmers themselves, allowing such Programmers to simulate the execution of mouse-based branch conditions very easily.
-
-
-
-
- This USED TO be a complicated discussion of difficult alternatives I no longer need to consider. - - - - -
It's a lot more simple now. The new question becomes, Do we bother with any enhancements to fix broken-by-design Qt4, when Qt 4.8 has already reached a tentative API freeze? THOUSANDS of KDE users have voted for Bugs on insufficient mouse buttons and the weak poor short-cut facility which it creates.
- This USED TO be a complicated discussion of difficult alternatives I no longer need to consider. - - - - -
-
-
-
It's not an enhancement. When the BROKEN DESIGN ignores half of the mouse, it's more like ignoring half of the user's keyboard: it's a BUG, and it needs to be fixed. How many "votes" do we demand to get, before we do something?
-
-
Here are my alternative implementations, and a poll for Qt Developers (i.e., Developers of Qt itself) to also make quick-and-dirty "votes" -- even though I do prefer actual Replies to tell me why I should write the code in one way, versus another.
(Alternative 1:) Really EASY, but (IMO) absolutely not good enough: Just add values for the 3 bits which remain unused (x20, x40, and x80).
Why isn't it good enough? That leaves a lot of buttons which people would LIKE to use in the exact same situation they have now. On my own Mouse, Logitech model 700, buttons #13 and #14 are much easier to press than the "Back" and "Forward" buttons. But this half-baked "enhancement" would leave my mouse, and many others, in pretty much the situation which I have now: Qt receives all the button events from X11, but all the high-numbered cases are ignored.
As we have seen with the addition of Button_8 and Button_9 (Qt::XButton1 and Qt::XButton2) in Qt 4.7, this "Partial Implementation" would probably be ignored by most Developers. They want the whole mouse, not "a button here", "another button over there", as we did in 4.7.
(Alternative 2) We could define new Members, which return an integer button number (from the first number which is NOT included in the current events, "n" up to 32). as the Button which caused the event. Qt would receive and dispatch all the button press and button release events.
In my initial idea, the current API members would remain present for handling the "small" numbers (X11 button number <= 12). We would NOT provide a “full-width” ButtonStateMask within these events. Qt would receive and dispatch all the ButtonPress and ButtonRelease release events coming from X11, and it would create DblClick as well, but it would use separate event types for the High-numbered (new) versus Low-numbered (current) buttons. (Again, Qt5 almost certainly WILL be doing that full-width mask, and re-unify the API... so this creates a future incompatibility.)
If it would be better to "extend" the current Class events, rather than create new event types, Please advise.
In this alternative, I would subsequently implement an entirely separate getFullWidthButtonMask() method, to be called only when users NEED to have the full 32-bit ButtonStateMask. That implementation would be under an entirely separate BugID.
(Alternative 3:) Provide the full-width ButtonStateMask as a value, inside the event signature (for each of the 3 events). Personally, I don't like this very much -- but I can do it. Since we don't get them directly from X11 when using "legacy" XI 1.x, I would have to perform inter-process Request and Response work within the event processing code. I hate the notion of adding inline, unconditional request/response code inside our event handler! But please advise if I should be thinking differently. Maybe it's not as terrible as I think it is.
In nearly all cases which I would choose to support in KDE multi-button shortcuts, we could just limit the choice of "modifier" button to one of the buttons which we do get from XI 1.0. (With my hand, the most "natural" combination consists of holding down the right button as the modifier, while clicking another with my thumb or index finger (i.e., "pointing finger")). And so, I think that a Qt programmer would only use the full mask in exceptional cases. (It's not just messy to write and execute at runtime; IMO, it's also not NEEDED.)
My last argument against this alternative, and for a separate "get" function, concerns reliability. Qt 4.8 will be running on a lot of "semi-buggy, proprietary" implementations of X11. "More Buttons" in events, without the mask, is child's play for me to write. But with the extended mask creating a mandatory X11 request before passing the event, it could become noticeably slow to respond. Above all else, we want ZERO BUGS. Right?
The advantage is in having "somewhat more" compatibility with Qt5. But I think the risks are too high, and the overhead should not occur within our Event Handling logic.
-
- Thanks! - -
Thanks in advance for your reading, and your responses. Please limit your responses to technical advice-- We already have hundreds of posts, and thousands of votes, over on KDE Bugzilla, saying nicely (and way too often, not nicely) that those buttons are needed in Qt code and KDE libraries. I've created this Thread to get design advice from the Developers of Qt itself, and to get a hint about the time limits which I facing in getting this done.
The Qt bugtracker seems to be oriented towards bugs and code, and not discussion of "design documents". And so, I'm putting it here ;)
-
-
If you want advice from the current developers of Qt, I would suggest you head over to #qt-labs on the freenode irc network and discuss this there. You can point users there to this excellent and detailed post as a background to the issues to solve and the alternatives you have come up with. I am afraid that there are not many core Qt developers active here. I don't have technical advice to offer, but I do know that not heaving code break between Qt 4 and 5 is an important goal. Breaking that needs a very good reason. Last, I think it will be expected of you to think about a solution for the other major platforms (Windows and Mac) too. Otherwise, I doubt the feature will be accepted. If you aim for 4.8, you'd better hurry up too.
-
Thanks, Andre. I will visit there again, and point to this Thread.
I understand that Qt5 will have as much Source Code compatibility as possible. For the case of the Qt::MouseButtons ENUM, and many others, a re-compile will be needed if the field is widened. If a "setQt4SupportMode(true)" situation will be needed, then the Qt5 "full-width" event can very easily be translated into the 4.8 and earlier events as follows:
For 4.8 -- Do it as I plan for 4.8. If it's a high-numbered button, then dispatch them as the "new in 4.8" events- which should probably include the button number (although I might use the current ENUM scheme instead, with a 32-bit wide enum.) If it's a low-numbered button, then dispatch as a 4.x series event.
For 4.7 and earlier-- if it's a high-numbered button, pull in the X11 event and do NOTHING. Trash it, exactly as now. For a low-numbered button, do as in 4.8.
It would be absolute lunacy to keep the current 1-byte ENUM unchanged. It was a fundamentally defective design right from the start of the 4.x Series. But for people who won't recompile (or can't, because they don't have the Source code available), it's an easy translation to provide within a Qt4 "compatibility mode".
Andre, if I will be using new names for these "Gamer" mouse button presses -- do you have any advice on names which make sense for i10n purposes?
Thanks so much for posting!