儲存庫 vbox 的更動 63553
- 時間撮記:
- 2016-8-16 下午01:05:32 (8 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
r63492 r63553 14 14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 15 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 */17 18 /*19 * Things worth testing when changing this code:20 * * That automatic keyboard capture works.21 * * That the keyboard is captured when the mouse is.22 * * That the host key releases the keyboard when the keyboard is captured23 * but the mouse not, and both when both are.24 * * That the keyboard is captured when the mouse capture notification is25 * displayed.26 * * That keyboard capture works on X11 hosts when windows are dragged with27 * various window managers.28 * * That multiple machine windows do not fight for the focus on X11 hosts29 * (noticeable through strange modifier key and capitals behaviour).30 16 */ 31 17 … … 283 269 return; 284 270 285 /* On X11 we do not grab the keyboard as soon as it is captured, but delay it until the 286 * first keypress after the capture. We do this for several reasons. First, when several 287 * windows are created they all try to capture the keyboard when they get the focus. Due to 288 * the asynchronous nature of X11 the first window may only gets notified after the last is 289 * created, and there is a dance if they respond to the notifications by grabbing the keyboard 290 * and trigger new focus changes in the process. Second, it is sometimes inconvenient to 291 * grab the keyboard immediately on focus change: some window managers set the focus then 292 * try to grab the keyboard themselves, and sulk if they fail by refusing to e.g. drag a 293 * window using its title bar. This code uses a hack by taking (ulong)~0 as a parameter to 294 * finalise the capture. */ 271 #if defined(VBOX_WS_X11) && QT_VERSION >= 0x050000 272 /* Due to X11 async nature we may have lost the focus already by the time we get the focus 273 * notification, so we do a sanity check that we still have it. If we don't have the focus 274 * and grab the keyboard now that will cause focus change which we want to avoid. This change 275 * potentially leads to a loop where two windows are continually responding to outdated focus events. */ 276 const xcb_get_input_focus_cookie_t xcbFocusCookie = xcb_get_input_focus(QX11Info::connection()); 277 xcb_get_input_focus_reply_t *pFocusReply = xcb_get_input_focus_reply(QX11Info::connection(), xcbFocusCookie, NULL); 278 WId actualWinId = 0; 279 if (pFocusReply) 280 { 281 actualWinId = pFocusReply->focus; 282 free(pFocusReply); 283 } 284 else 285 LogRel(("GUI: UIKeyboardHandler::captureKeyboard: XCB error on acquiring focus information detected!\n")); 286 if (m_windows.value(uScreenId)->winId() != actualWinId) 287 return; 288 289 /* Delay capturing the keyboard if the mouse button is held down and the mouse is not 290 * captured to work around window managers which transfer the focus when the user 291 * clicks in the title bar and then try to grab the keyboard and sulk if they fail. 292 * If the click is inside of our views we will do the capture when it is released. */ 293 const xcb_query_pointer_cookie_t xcbPointerCookie = xcb_query_pointer(QX11Info::connection(), QX11Info::appRootWindow()); 294 xcb_query_pointer_reply_t *pPointerReply = xcb_query_pointer_reply(QX11Info::connection(), xcbPointerCookie, NULL); 295 if (!uisession()->isMouseCaptured() && pPointerReply && (pPointerReply->mask & XCB_KEY_BUT_MASK_BUTTON_1)) 296 { 297 free(pPointerReply); 298 return; 299 } 300 free(pPointerReply); 301 #endif /* VBOX_WS_X11 && QT_VERSION >= 0x050000 */ 295 302 296 303 /* If such view exists: */ 297 if (m_views.contains(uScreenId) 298 #if defined(VBOX_WS_X11) && QT_VERSION >= 0x050000 299 || ((uScreenId == (ulong)~0) && m_views.contains(m_idxDelayedKeyboardCaptureView)) 300 #endif 301 ) 304 if (m_views.contains(uScreenId)) 302 305 { 303 306 #if defined(VBOX_WS_MAC) … … 368 371 # else /* QT_VERSION >= 0x050000 */ 369 372 370 if (uScreenId != (ulong)~0)371 {372 m_idxDelayedKeyboardCaptureView = uScreenId;373 return;374 }375 uScreenId = m_idxDelayedKeyboardCaptureView;376 373 /* On X11, we are using XCB stuff to grab the keyboard. 377 374 * This stuff is a part of the active keyboard grabbing functionality. 378 * Active keyboard grabbing causes a problems on manywindow managers - a window cannot375 * Active keyboard grabbing causes a problems on certain old window managers - a window cannot 379 376 * be moved using the mouse. So we additionally grabbing the mouse as well to detect that user 380 377 * is trying to click outside of internal window geometry. */ 381 378 382 /* Grab the mouse button. We do not check for failure as we do not currently implement a 383 * back-up plan. */ 384 xcb_grab_button_checked(QX11Info::connection(), 0, QX11Info::appRootWindow(), 385 XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, 386 XCB_NONE, XCB_NONE, XCB_BUTTON_INDEX_1, XCB_MOD_MASK_ANY); 379 /* Grab the mouse button (if mouse is not captured), 380 * We do not check for failure as we do not currently implement a back-up plan. */ 381 if (!uisession()->isMouseCaptured()) 382 xcb_grab_button_checked(QX11Info::connection(), 0, QX11Info::appRootWindow(), 383 XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, 384 XCB_NONE, XCB_NONE, XCB_BUTTON_INDEX_1, XCB_MOD_MASK_ANY); 387 385 /* And grab the keyboard, using XCB directly, as Qt does not report failure. */ 388 386 xcb_grab_keyboard_cookie_t xcbGrabCookie = xcb_grab_keyboard(QX11Info::connection(), false, m_views[uScreenId]->winId(), … … 392 390 { 393 391 /* Try again later: */ 392 m_idxDelayedKeyboardCaptureView = uScreenId; 394 393 free(pGrabReply); 395 394 return; … … 1380 1379 /* If we were asked to grab the keyboard previously but had to delay it 1381 1380 * then try again on every key press and release event until we manage: */ 1382 captureKeyboard((ulong)~0); 1381 if (m_idxDelayedKeyboardCaptureView != -1) 1382 captureKeyboard(m_idxDelayedKeyboardCaptureView); 1383 1383 1384 1384 /* Cast to XCB key-event: */ … … 1484 1484 } 1485 1485 /* Else if the event happened outside of our view areas then release the keyboard, 1486 * but capture it again (delayed) immediately. If the event causes us to loose the1487 * focus then the delayed capture will not happen: */1486 * but set the delayed capture index so that it will be captured again if we still 1487 * have the focus after the event is handled: */ 1488 1488 releaseKeyboard(); 1489 captureKeyboard(uScreenId);1489 m_idxDelayedKeyboardCaptureView = uScreenId; 1490 1490 /* And re-send the event so that the window which it was meant for actually gets it: */ 1491 1491 xcb_allow_events_checked(QX11Info::connection(), XCB_ALLOW_REPLAY_POINTER, pButtonEvent->time); … … 1799 1799 if (!isAutoCaptureDisabled() && autoCaptureSetGlobally()) 1800 1800 #endif /* !VBOX_WS_WIN */ 1801 #if defined(VBOX_WS_X11) && QT_VERSION >= 0x050000 1802 m_idxDelayedKeyboardCaptureView = uScreenId; 1803 #else /* !VBOX_WS_X11 || QT_VERSION < 0x050000 */ 1801 1804 captureKeyboard(uScreenId); 1805 #endif /* !VBOX_WS_X11 || QT_VERSION < 0x050000 */ 1802 1806 /* Reset the single-time disable capture flag: */ 1803 1807 if (isAutoCaptureDisabled())
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器