Contents of /trunk/qt/patches/0002-dnd_active_window_fix.patch
Parent Directory | Revision Log
Revision 153 -
(show 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 | 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; |