Changeset 22233 in vbox
- Timestamp:
- Aug 13, 2009 12:17:35 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/SharedClipboard/x11-clipboard.cpp
r22212 r22233 168 168 Widget widget; 169 169 170 /** Does VBox currently own the clipboard? */171 bool fOwnsClipboard;172 170 /** Should we try to grab the clipboard on startup? */ 173 171 bool fGrabClipboardOnStart; … … 181 179 /** What formats does VBox have on offer? */ 182 180 uint32_t vboxFormats; 183 /** Windows hosts and guests cache the clipboard data they receive.184 * Since we have no way of knowing whether their cache is still valid,185 * we always send a "data changed" message after a successful transfer186 * to invalidate it. */187 bool notifyVBox;188 181 /** Cache of the last unicode data that we received */ 189 182 void *pvUnicodeCache; … … 401 394 * @param pTargets the list of targets 402 395 * @param cTargets the size of the list in @a pTargets 403 * @param pChanged This is set to true if the formats available have changed404 * from VBox's point of view, and to false otherwise.405 * Somehow this didn't feel right as a return value.406 396 */ 407 397 static void clipGetFormatsFromTargets(CLIPBACKEND *pCtx, Atom *pTargets, 408 size_t cTargets, bool *pChanged) 409 { 410 bool changed = false; 398 size_t cTargets) 399 { 411 400 AssertPtrReturnVoid(pCtx); 412 Assert ReturnVoid(VALID_PTR(pTargets) || cTargets == 0);401 AssertPtrReturnVoid(pTargets); 413 402 CLIPX11FORMAT bestTextFormat; 414 403 bestTextFormat = clipGetTextFormatFromTargets(pCtx, pTargets, cTargets); 415 404 if (pCtx->X11TextFormat != bestTextFormat) 416 405 { 417 changed = true;418 406 pCtx->X11TextFormat = bestTextFormat; 419 407 #if defined(DEBUG) && !defined(TESTCASE) … … 429 417 } 430 418 pCtx->X11BitmapFormat = INVALID; /* not yet supported */ 431 if (pChanged)432 *pChanged = changed;433 419 } 434 420 … … 443 429 size_t cTargets) 444 430 { 445 bool changed = false;446 447 431 LogRel2 (("%s: called\n", __PRETTY_FUNCTION__)); 448 if (pCtx->fOwnsClipboard) 449 /* VBox raced us and we lost. So we don't want to report anything. */ 450 return; 451 clipGetFormatsFromTargets(pCtx, pTargets, cTargets, &changed); 432 clipGetFormatsFromTargets(pCtx, pTargets, cTargets); 452 433 clipReportFormatsToVBox(pCtx); 453 434 } 454 455 #ifdef TESTCASE456 static bool clipTestTargetUpdate(CLIPBACKEND *pCtx)457 {458 bool success = true;459 bool changed = true;460 clipGetFormatsFromTargets(pCtx, NULL, 0, &changed);461 clipGetFormatsFromTargets(pCtx, NULL, 0, &changed); /* twice */462 if (changed)463 success = false;464 Atom targets[3];465 targets[0] = clipGetAtom(NULL, "COMPOUND_TEXT");466 targets[1] = clipGetAtom(NULL, "text/plain");467 targets[2] = clipGetAtom(NULL, "TARGETS");468 clipGetFormatsFromTargets(pCtx, targets, RT_ELEMENTS(targets), &changed);469 if (!changed)470 success = false;471 clipGetFormatsFromTargets(pCtx, targets, RT_ELEMENTS(targets), &changed);472 if (changed)473 success = false;474 return success;475 }476 #endif477 435 478 436 /** … … 488 446 CLIPBACKEND *pCtx = 489 447 reinterpret_cast<CLIPBACKEND *>(pClientData); 490 Atom *pTargets = (*atomType == XT_CONVERT_FAIL) ? NULL /* timeout */491 : (Atom *)pValue;492 size_t cTargets = pTargets ? *pcLen : 0;493 448 LogRel2(("clipConvertX11Targets: pValue=%p, *pcLen=%u, *atomType=%d, XT_CONVERT_FAIL=%d\n", 494 449 pValue, *pcLen, *atomType, XT_CONVERT_FAIL)); 495 clipUpdateX11Targets(pCtx, pTargets, cTargets); 450 if ( (*atomType == XT_CONVERT_FAIL) /* timeout */ 451 || (pValue == NULL)) /* No data available */ 452 { 453 clipReportEmptyX11CB(pCtx); 454 return; 455 } 456 clipUpdateX11Targets(pCtx, (Atom *)pValue, *pcLen); 496 457 XtFree(reinterpret_cast<char *>(pValue)); 497 458 } … … 502 463 void clipQueryX11CBFormats(CLIPBACKEND *pCtx) 503 464 { 504 LogRel2 (("%s: called\n", __PRETTY_FUNCTION__)); 505 /* Get the current clipboard contents if we don't own it ourselves */ 506 if (!pCtx->fOwnsClipboard) 507 { 508 LogRel2 (("%s: requesting the targets that the X11 clipboard offers\n", 509 __PRETTY_FUNCTION__)); 510 XtGetSelectionValue(pCtx->widget, 511 clipGetAtom(pCtx->widget, "CLIPBOARD"), 512 clipGetAtom(pCtx->widget, "TARGETS"), 513 clipConvertX11Targets, pCtx, 514 CurrentTime); 515 } 465 LogRel2 (("%s: requesting the targets that the X11 clipboard offers\n", 466 __PRETTY_FUNCTION__)); 467 XtGetSelectionValue(pCtx->widget, 468 clipGetAtom(pCtx->widget, "CLIPBOARD"), 469 clipGetAtom(pCtx->widget, "TARGETS"), 470 clipConvertX11Targets, pCtx, 471 CurrentTime); 516 472 } 517 473 518 474 #ifndef TESTCASE 475 476 typedef struct { 477 int type; /* event base */ 478 unsigned long serial; 479 Bool send_event; 480 Display *display; 481 Window window; 482 int subtype; 483 Window owner; 484 Atom selection; 485 Time timestamp; 486 Time selection_timestamp; 487 } XFixesSelectionNotifyEvent; 488 519 489 /** 520 490 * Wait until an event arrives and handle it if it is an XFIXES selection … … 523 493 void clipPeekEventAndDoXFixesHandling(CLIPBACKEND *pCtx) 524 494 { 525 XEvent event = { 0 }; 526 527 if (XtAppPeekEvent(pCtx->appContext, &event)) 528 if ( !pCtx->fOwnsClipboard 529 && (event.type == pCtx->fixesEventBase)) 530 clipQueryX11CBFormats(pCtx); 495 union 496 { 497 XEvent event; 498 XFixesSelectionNotifyEvent fixes; 499 } event = { { 0 } }; 500 501 if (XtAppPeekEvent(pCtx->appContext, &event.event)) 502 if ( (event.event.type == pCtx->fixesEventBase) 503 && (event.fixes.owner != XtWindow(pCtx->widget))) 504 { 505 if ( (event.fixes.subtype == 0 /* XFixesSetSelectionOwnerNotify */) 506 && (event.fixes.owner != 0)) 507 clipQueryX11CBFormats(pCtx); 508 else 509 clipReportEmptyX11CB(pCtx); 510 } 531 511 } 532 512 … … 776 756 if (RT_SUCCESS(rc)) 777 757 { 778 pCtx->fOwnsClipboard = false;779 758 clipResetX11Formats(pCtx); 780 759 pCtx->fGrabClipboardOnStart = grab; … … 1160 1139 1161 1140 LogRelFlowFunc(("\n")); 1162 if ( !pCtx->fOwnsClipboard /* Drop requests we receive too late. */ 1163 || !clipIsSupportedSelectionType(pCtx->widget, *atomSelection)) 1141 if (!clipIsSupportedSelectionType(pCtx->widget, *atomSelection)) 1164 1142 return false; 1165 1143 if (*atomTarget == clipGetAtom(pCtx->widget, "TARGETS")) … … 1173 1151 } 1174 1152 1175 /**1176 * Notify VBox that we have returned the clipboard to X11.1177 */1178 static void clipReleaseCB(CLIPBACKEND *pCtx)1179 {1180 LogRelFlowFunc (("\n"));1181 /* The formats should be set to the right values as soon as X11 clipboard1182 * data becomes available. */1183 clipReportEmptyX11CB(pCtx);1184 pCtx->fOwnsClipboard = false;1185 }1186 1187 /**1188 * This is called by the X toolkit intrinsics to let us know that another1189 * X11 client has taken the clipboard. In this case we notify VBox that1190 * X11 wants ownership of the clipboard.1191 * @note X11 backend code, callback for XtOwnSelection1192 */1193 static void clipXtLoseSelectionProc(Widget widget, Atom *)1194 {1195 CLIPBACKEND *pCtx = clipLookupContext(widget);1196 LogRelFlowFunc (("\n"));1197 clipReleaseCB(pCtx);1198 }1199 1200 1153 /** Structure used to pass information about formats that VBox supports */ 1201 1154 typedef struct _CLIPNEWVBOXFORMATS … … 1222 1175 static void clipGrabX11CB(CLIPBACKEND *pCtx, uint32_t u32Formats) 1223 1176 { 1224 /* Make sure we don't try to query ourselves if we get the clipboard */1225 pCtx->fOwnsClipboard = true;1226 1177 if (XtOwnSelection(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"), 1227 CurrentTime, clipXtConvertSelectionProc, 1228 clipXtLoseSelectionProc, 0)) 1178 CurrentTime, clipXtConvertSelectionProc, NULL, 0)) 1229 1179 { 1230 1180 pCtx->vboxFormats = u32Formats; … … 1233 1183 CurrentTime, clipXtConvertSelectionProc, NULL, 0); 1234 1184 } 1235 else1236 /* Someone raced us to get the clipboard and they won. */1237 pCtx->fOwnsClipboard = false;1238 1185 } 1239 1186 … … 1591 1538 1592 1539 int rc = VINF_SUCCESS; 1593 /* Do not continue if we already own the clipboard */ 1594 if (pCtx->fOwnsClipboard == true) 1595 rc = VERR_TIMEOUT; 1540 /* 1541 * VBox wants to read data in the given format. 1542 */ 1543 if (pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 1544 { 1545 pReq->mTextFormat = pCtx->X11TextFormat; 1546 if (pReq->mTextFormat == INVALID) 1547 /* VBox thinks we have data and we don't */ 1548 rc = VERR_NO_DATA; 1549 else 1550 /* Send out a request for the data to the current clipboard 1551 * owner */ 1552 XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"), 1553 clipAtomForX11Format(pCtx->widget, 1554 pCtx->X11TextFormat), 1555 clipConvertX11CB, 1556 reinterpret_cast<XtPointer>(pReq), 1557 CurrentTime); 1558 } 1596 1559 else 1597 { 1598 /* 1599 * VBox wants to read data in the given format. 1600 */ 1601 if (pReq->mFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT) 1602 { 1603 pReq->mTextFormat = pCtx->X11TextFormat; 1604 if (pReq->mTextFormat == INVALID) 1605 /* VBox thinks we have data and we don't */ 1606 rc = VERR_NO_DATA; 1607 else 1608 /* Send out a request for the data to the current clipboard 1609 * owner */ 1610 XtGetSelectionValue(pCtx->widget, clipGetAtom(pCtx->widget, "CLIPBOARD"), 1611 clipAtomForX11Format(pCtx->widget, 1612 pCtx->X11TextFormat), 1613 clipConvertX11CB, 1614 reinterpret_cast<XtPointer>(pReq), 1615 CurrentTime); 1616 } 1617 else 1618 rc = VERR_NOT_IMPLEMENTED; 1619 } 1560 rc = VERR_NOT_IMPLEMENTED; 1620 1561 if (RT_FAILURE(rc)) 1621 1562 { … … 2436 2377 RTTestSub(hTest, "notification of switch to X11 clipboard"); 2437 2378 clipInvalidateFormats(); 2438 clipRe leaseCB(pCtx);2379 clipReportEmptyX11CB(pCtx); 2439 2380 RTTEST_CHECK_MSG(hTest, clipQueryFormats() == 0, 2440 2381 (hTest, "Failed to send a format update (release) notification\n")); … … 2456 2397 sizeof("hello world"), 8); 2457 2398 clipSetTargetsFailure(false, true); 2458 clipUpdateX11Targets(pCtx, NULL, 0); 2399 Atom atom = XA_STRING; 2400 long unsigned int cLen = 0; 2401 int format = 8; 2402 clipConvertX11Targets(NULL, (XtPointer) pCtx, NULL, &atom, NULL, &cLen, 2403 &format); 2459 2404 RTTEST_CHECK_MSG(hTest, clipQueryFormats() == 0, 2460 2405 (hTest, "Wrong targets reported: %02X\n", … … 2465 2410 RTTEST_CHECK_MSG(hTest, clipTestTextFormatConversion(pCtx), 2466 2411 (hTest, "failed to select the right X11 text formats\n")); 2467 RTTEST_CHECK_MSG(hTest, clipTestTargetUpdate(pCtx),2468 (hTest, "incorrect reporting of new selection targets\n"));2469 2412 2470 2413 /*** Utf-8 from VBox ***/ … … 2556 2499 /*** No data in VBox clipboard ***/ 2557 2500 RTTestSub(hTest, "an empty VBox clipboard"); 2501 clipSetSelectionValues("TEXT", XA_STRING, "", sizeof(""), 8); 2558 2502 clipEmptyVBox(pCtx, VINF_SUCCESS); 2559 RTTEST_CHECK_MSG(hTest, pCtx->fOwnsClipboard,2503 RTTEST_CHECK_MSG(hTest, g_ownsSel, 2560 2504 (hTest, "VBox grabbed the clipboard with no data and we ignored it\n")); 2561 2505 testStringFromVBoxFailed(hTest, pCtx, "UTF8_STRING"); … … 2563 2507 /*** An unknown VBox format ***/ 2564 2508 RTTestSub(hTest, "reading an unknown VBox format"); 2509 clipSetSelectionValues("TEXT", XA_STRING, "", sizeof(""), 8); 2565 2510 clipSetVBoxUtf16(pCtx, VINF_SUCCESS, "", 2); 2566 2511 ClipAnnounceFormatToX11(pCtx, 0xa0000); 2567 RTTEST_CHECK_MSG(hTest, pCtx->fOwnsClipboard,2512 RTTEST_CHECK_MSG(hTest, g_ownsSel, 2568 2513 (hTest, "VBox grabbed the clipboard with unknown data and we ignored it\n")); 2569 2514 testStringFromVBoxFailed(hTest, pCtx, "UTF8_STRING");
Note:
See TracChangeset
for help on using the changeset viewer.