Annotation of /trunk/qt/patches/0002-dnd_active_window_fix.patch
Parent Directory | Revision Log
Revision 153 -
(hide annotations)
(download)
Tue May 8 20:52:56 2007 UTC (17 years, 4 months ago) by niro
File size: 7289 byte(s)
Tue May 8 20:52:56 2007 UTC (17 years, 4 months ago) by niro
File size: 7289 byte(s)
-import
1 | niro | 153 | qt-bugs@ issue : 25122 |
2 | applied: no | ||
3 | author: Lubos Lunak <l.lunak@kde.org> | ||
4 | |||
5 | Hello, | ||
6 | |||
7 | for example: Open Konqueror window, showing some files. Start dragging one | ||
8 | desktop icon. If you press/release Ctrl, there'll be a '+' attached to the | ||
9 | icon, showing the DND operation. Now, while still doing DND, make the | ||
10 | Konqueror window active (Alt+Tab with KDE-3.1.2+, hover over its taskbar | ||
11 | entry, Ctrl+Fn to switch to a different virtual desktop, etc.). As soon as | ||
12 | the app performing DND is not the active application, and the mouse is not | ||
13 | moving, pressing/releasing Ctrl doesn't do anything, the state only updates | ||
14 | when the mouse is moved. | ||
15 | |||
16 | This is caused by the fact that Qt has only pointer grab when doing DND, but | ||
17 | doesn't have keyboard grab. I actually consider this a good thing, because | ||
18 | the only keys important for DND are modifiers, and they come together with | ||
19 | pointer events, and not having keyboard grab allows using keyboard shortcuts | ||
20 | like Alt+Tab while DND. However, when the mouse is not moved, and only a | ||
21 | modifier key is pressed/released, the app won't get any mouse event, and | ||
22 | won't also get the keyboard event. | ||
23 | |||
24 | The attached patch changes Qt to explicitly check the modifiers state using | ||
25 | XQueryPointer() if there's wasn't recently any mouse/keyboard event, which | ||
26 | ensures the state is updated even in the situation described above. | ||
27 | |||
28 | --- src/kernel/qapplication_x11.cpp.sav 2003-06-21 12:31:35.000000000 +0200 | ||
29 | +++ src/kernel/qapplication_x11.cpp 2003-06-21 12:35:44.000000000 +0200 | ||
30 | @@ -4053,7 +4053,7 @@ void QApplication::closePopup( QWidget * | ||
31 | // Keyboard event translation | ||
32 | // | ||
33 | |||
34 | -static int translateButtonState( int s ) | ||
35 | +int qt_x11_translateButtonState( int s ) | ||
36 | { | ||
37 | int bst = 0; | ||
38 | if ( s & Button1Mask ) | ||
39 | @@ -4119,7 +4119,7 @@ bool QETWidget::translateMouseEvent( con | ||
40 | pos.ry() = lastMotion.y; | ||
41 | globalPos.rx() = lastMotion.x_root; | ||
42 | globalPos.ry() = lastMotion.y_root; | ||
43 | - state = translateButtonState( lastMotion.state ); | ||
44 | + state = qt_x11_translateButtonState( lastMotion.state ); | ||
45 | if ( qt_button_down && (state & (LeftButton | | ||
46 | MidButton | | ||
47 | RightButton ) ) == 0 ) | ||
48 | @@ -4143,7 +4143,7 @@ bool QETWidget::translateMouseEvent( con | ||
49 | pos.ry() = xevent->xcrossing.y; | ||
50 | globalPos.rx() = xevent->xcrossing.x_root; | ||
51 | globalPos.ry() = xevent->xcrossing.y_root; | ||
52 | - state = translateButtonState( xevent->xcrossing.state ); | ||
53 | + state = qt_x11_translateButtonState( xevent->xcrossing.state ); | ||
54 | if ( qt_button_down && (state & (LeftButton | | ||
55 | MidButton | | ||
56 | RightButton ) ) == 0 ) | ||
57 | @@ -4155,7 +4155,7 @@ bool QETWidget::translateMouseEvent( con | ||
58 | pos.ry() = event->xbutton.y; | ||
59 | globalPos.rx() = event->xbutton.x_root; | ||
60 | globalPos.ry() = event->xbutton.y_root; | ||
61 | - state = translateButtonState( event->xbutton.state ); | ||
62 | + state = qt_x11_translateButtonState( event->xbutton.state ); | ||
63 | switch ( event->xbutton.button ) { | ||
64 | case Button1: button = LeftButton; break; | ||
65 | case Button2: button = MidButton; break; | ||
66 | @@ -4950,7 +4950,7 @@ bool QETWidget::translateKeyEventInterna | ||
67 | XKeyEvent xkeyevent = event->xkey; | ||
68 | |||
69 | // save the modifier state, we will use the keystate uint later by passing | ||
70 | - // it to translateButtonState | ||
71 | + // it to qt_x11_translateButtonState | ||
72 | uint keystate = event->xkey.state; | ||
73 | // remove the modifiers where mode_switch exists... HPUX machines seem | ||
74 | // to have alt *AND* mode_switch both in Mod1Mask, which causes | ||
75 | @@ -5064,7 +5064,7 @@ bool QETWidget::translateKeyEventInterna | ||
76 | } | ||
77 | #endif // !QT_NO_XIM | ||
78 | |||
79 | - state = translateButtonState( keystate ); | ||
80 | + state = qt_x11_translateButtonState( keystate ); | ||
81 | |||
82 | static int directionKeyEvent = 0; | ||
83 | if ( qt_use_rtl_extensions && type == QEvent::KeyRelease ) { | ||
84 | --- src/kernel/qdnd_x11.cpp.sav 2003-06-30 15:26:42.000000000 +0200 | ||
85 | +++ src/kernel/qdnd_x11.cpp 2003-06-30 15:32:23.000000000 +0200 | ||
86 | @@ -114,6 +114,8 @@ Atom qt_xdnd_finished; | ||
87 | Atom qt_xdnd_type_list; | ||
88 | const int qt_xdnd_version = 4; | ||
89 | |||
90 | +extern int qt_x11_translateButtonState( int s ); | ||
91 | + | ||
92 | // Actions | ||
93 | // | ||
94 | // The Xdnd spec allows for user-defined actions. This could be implemented | ||
95 | @@ -198,6 +200,8 @@ static Atom qt_xdnd_source_current_time; | ||
96 | static int qt_xdnd_current_screen = -1; | ||
97 | // state of dragging... true if dragging, false if not | ||
98 | bool qt_xdnd_dragging = FALSE; | ||
99 | +// need to check state of keyboard modifiers | ||
100 | +static bool need_modifiers_check = FALSE; | ||
101 | |||
102 | // dict of payload data, sorted by type atom | ||
103 | static QIntDict<QByteArray> * qt_xdnd_target_data = 0; | ||
104 | @@ -879,8 +883,20 @@ void qt_handle_xdnd_finished( QWidget *, | ||
105 | |||
106 | void QDragManager::timerEvent( QTimerEvent* e ) | ||
107 | { | ||
108 | - if ( e->timerId() == heartbeat && qt_xdnd_source_sameanswer.isNull() ) | ||
109 | - move( QCursor::pos() ); | ||
110 | + if ( e->timerId() == heartbeat ) { | ||
111 | + if( need_modifiers_check ) { | ||
112 | + Window root, child; | ||
113 | + int root_x, root_y, win_x, win_y; | ||
114 | + unsigned int mask; | ||
115 | + XQueryPointer( qt_xdisplay(), qt_xrootwin( qt_xdnd_current_screen ), | ||
116 | + &root, &child, &root_x, &root_y, &win_x, &win_y, &mask ); | ||
117 | + if( updateMode( (ButtonState)qt_x11_translateButtonState( mask ))) | ||
118 | + qt_xdnd_source_sameanswer = QRect(); // force move | ||
119 | + } | ||
120 | + need_modifiers_check = TRUE; | ||
121 | + if( qt_xdnd_source_sameanswer.isNull() ) | ||
122 | + move( QCursor::pos() ); | ||
123 | + } | ||
124 | } | ||
125 | |||
126 | static bool qt_xdnd_was_move = false; | ||
127 | @@ -948,6 +964,7 @@ bool QDragManager::eventFilter( QObject | ||
128 | updateMode(me->stateAfter()); | ||
129 | move( me->globalPos() ); | ||
130 | } | ||
131 | + need_modifiers_check = FALSE; | ||
132 | return TRUE; | ||
133 | } else if ( e->type() == QEvent::MouseButtonRelease ) { | ||
134 | qApp->removeEventFilter( this ); | ||
135 | @@ -986,9 +1003,11 @@ bool QDragManager::eventFilter( QObject | ||
136 | beingCancelled = FALSE; | ||
137 | qApp->exit_loop(); | ||
138 | } else { | ||
139 | - updateMode(ke->stateAfter()); | ||
140 | - qt_xdnd_source_sameanswer = QRect(); // force move | ||
141 | - move( QCursor::pos() ); | ||
142 | + if( updateMode(ke->stateAfter())) { | ||
143 | + qt_xdnd_source_sameanswer = QRect(); // force move | ||
144 | + move( QCursor::pos() ); | ||
145 | + } | ||
146 | + need_modifiers_check = FALSE; | ||
147 | } | ||
148 | return TRUE; // Eat all key events | ||
149 | } | ||
150 | @@ -1014,10 +1033,10 @@ bool QDragManager::eventFilter( QObject | ||
151 | |||
152 | |||
153 | static Qt::ButtonState oldstate; | ||
154 | -void QDragManager::updateMode( ButtonState newstate ) | ||
155 | +bool QDragManager::updateMode( ButtonState newstate ) | ||
156 | { | ||
157 | if ( newstate == oldstate ) | ||
158 | - return; | ||
159 | + return false; | ||
160 | const int both = ShiftButton|ControlButton; | ||
161 | if ( (newstate & both) == both ) { | ||
162 | global_requested_action = QDropEvent::Link; | ||
163 | @@ -1041,6 +1060,7 @@ void QDragManager::updateMode( ButtonSta | ||
164 | } | ||
165 | } | ||
166 | oldstate = newstate; | ||
167 | + return true; | ||
168 | } | ||
169 | |||
170 | |||
171 | @@ -1707,6 +1727,7 @@ bool QDragManager::drag( QDragObject * o | ||
172 | qt_xdnd_source_sameanswer = QRect(); | ||
173 | move(QCursor::pos()); | ||
174 | heartbeat = startTimer(200); | ||
175 | + need_modifiers_check = FALSE; | ||
176 | |||
177 | #ifndef QT_NO_CURSOR | ||
178 | qApp->setOverrideCursor( arrowCursor ); | ||
179 | --- src/kernel/qdragobject.h.sav 2003-05-19 22:34:43.000000000 +0200 | ||
180 | +++ src/kernel/qdragobject.h 2001-01-01 01:01:00.000000000 +0100 | ||
181 | @@ -248,7 +248,7 @@ private: | ||
182 | |||
183 | private: | ||
184 | QDragObject * object; | ||
185 | - void updateMode( ButtonState newstate ); | ||
186 | + bool updateMode( ButtonState newstate ); | ||
187 | void updateCursor(); | ||
188 | |||
189 | QWidget * dragSource; |