Changeset 86712 in vbox for trunk/src/VBox/GuestHost/SharedClipboard
- Timestamp:
- Oct 26, 2020 4:19:35 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 141096
- Location:
- trunk/src/VBox/GuestHost/SharedClipboard
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp
r86710 r86712 81 81 *********************************************************************************************************************************/ 82 82 #ifdef TESTCASE 83 extern void tst ClipQueueToEventThread(void (*proc)(void *, void *), void *client_data);83 extern void tstThreadScheduleCall(void (*proc)(void *, void *), void *client_data); 84 84 extern void tstClipRequestData(SHCLX11CTX* pCtx, SHCLX11FMTIDX target, void *closure); 85 85 extern void tstRequestTargets(SHCLX11CTX* pCtx); … … 93 93 SHCL_X11_DECL(Atom) clipGetAtom(PSHCLX11CTX pCtx, const char *pszName); 94 94 SHCL_X11_DECL(void) clipQueryX11Formats(PSHCLX11CTX pCtx); 95 96 static int clipInitInternal(PSHCLX11CTX pCtx); 97 static void clipUninitInternal(PSHCLX11CTX pCtx); 95 98 96 99 … … 395 398 * writing to the wakeup pipe which it monitors. 396 399 */ 397 static int clip QueueToEventThread(PSHCLX11CTX pCtx,400 static int clipThreadScheduleCall(PSHCLX11CTX pCtx, 398 401 void (*proc)(void *, void *), 399 402 void *client_data) 400 403 { 401 404 LogFlowFunc(("proc=%p, client_data=%p\n", proc, client_data)); 402 403 int rc = VINF_SUCCESS;404 405 405 406 #ifndef TESTCASE … … 407 408 (XtPointer)client_data); 408 409 ssize_t cbWritten = write(pCtx->wakeupPipeWrite, WAKE_UP_STRING, WAKE_UP_STRING_LEN); 410 Assert(cbWritten == WAKE_UP_STRING_LEN); 409 411 RT_NOREF(cbWritten); 410 412 #else 411 413 RT_NOREF(pCtx); 412 tst ClipQueueToEventThread(proc, client_data);413 #endif 414 415 LogFlowFuncLeaveRC( rc);416 return rc;414 tstThreadScheduleCall(proc, client_data); 415 #endif 416 417 LogFlowFuncLeaveRC(VINF_SUCCESS); 418 return VINF_SUCCESS; 417 419 } 418 420 … … 843 845 * @param pvUser Pointer to the X11 clipboard context to use. 844 846 */ 845 static DECLCALLBACK(int) clip EventThread(RTTHREAD hThreadSelf, void *pvUser)847 static DECLCALLBACK(int) clipThreadMain(RTTHREAD hThreadSelf, void *pvUser) 846 848 { 847 849 RT_NOREF(hThreadSelf); 848 850 AssertPtrReturn(pvUser, VERR_INVALID_POINTER); 849 851 850 LogRel (("Shared Clipboard: Starting X11 event thread\n"));852 LogRel2(("Shared Clipboard: Starting X11 event thread\n")); 851 853 852 854 PSHCLX11CTX pCtx = (SHCLX11CTX *)pvUser; 855 856 clipInitInternal(pCtx); 853 857 854 858 if (pCtx->fGrabClipboardOnStart) … … 865 869 } 866 870 867 LogRel(("Shared Clipboard: X11 event thread terminated successfully\n")); 871 clipUninitInternal(pCtx); 872 873 LogRel2(("Shared Clipboard: X11 event thread terminated successfully\n")); 868 874 return VINF_SUCCESS; 869 }870 #endif871 872 /**873 * X11 specific uninitialisation for the shared clipboard.874 *875 * @param pCtx The X11 clipboard context to use.876 */877 static void clipUninit(PSHCLX11CTX pCtx)878 {879 AssertPtrReturnVoid(pCtx);880 if (pCtx->pWidget)881 {882 /* Valid widget + invalid appcontext = bug. But don't return yet. */883 AssertPtr(pCtx->appContext);884 clipUnregisterContext(pCtx);885 XtDestroyWidget(pCtx->pWidget);886 }887 pCtx->pWidget = NULL;888 if (pCtx->appContext)889 XtDestroyApplicationContext(pCtx->appContext);890 pCtx->appContext = NULL;891 if (pCtx->wakeupPipeRead != 0)892 close(pCtx->wakeupPipeRead);893 if (pCtx->wakeupPipeWrite != 0)894 close(pCtx->wakeupPipeWrite);895 pCtx->wakeupPipeRead = 0;896 pCtx->wakeupPipeWrite = 0;897 875 } 898 876 … … 903 881 * @param pvUserData Pointer to the X11 clipboard context to use. 904 882 */ 905 static void clipStopEventThreadWorker(void *pvUserData, void *) 906 { 907 883 static void clipThreadSignalStop(void *pvUserData, void *) 884 { 908 885 PSHCLX11CTX pCtx = (PSHCLX11CTX)pvUserData; 909 886 … … 917 894 } 918 895 919 #ifndef TESTCASE920 896 /** 921 897 * Sets up the XFixes library and load the XFixesSelectSelectionInput symbol. … … 980 956 * @param pvUserData Pointer to the X11 clipboard context to use. 981 957 */ 982 static void clip DrainWakeupPipe(XtPointer pvUserData, int *, XtInputId *)958 static void clipThreadDrainWakeupPipe(XtPointer pvUserData, int *, XtInputId *) 983 959 { 984 960 LogFlowFuncEnter(); … … 991 967 992 968 /** 993 * X11 specific initialisation for the shared clipboard. 969 * X11-specific initialisation for the Shared Clipboard. 970 * 971 * Note: Must be called from the thread serving the Xt stuff. 994 972 * 995 973 * @returns VBox status code. 996 * @param pCtx The X11 clipboard context to use. 997 */ 998 static int clipInit(PSHCLX11CTX pCtx) 999 { 1000 /* Create a window and make it a clipboard viewer. */ 1001 int cArgc = 0; 1002 char *pcArgv = 0; 1003 int rc = VINF_SUCCESS; 1004 Display *pDisplay; 974 * @param pCtx The X11 clipboard context to init. 975 */ 976 static int clipInitInternal(PSHCLX11CTX pCtx) 977 { 978 LogFlowFunc(("pCtx=%p\n", pCtx)); 1005 979 1006 980 /* Make sure we are thread safe. */ … … 1013 987 */ 1014 988 XtToolkitInitialize(); 989 990 int rc = VINF_SUCCESS; 991 992 Assert(pCtx->appContext == NULL); /* No nested initialization. */ 1015 993 pCtx->appContext = XtCreateApplicationContext(); 1016 pDisplay = XtOpenDisplay(pCtx->appContext, 0, 0, "VBoxShCl", 0, 0, &cArgc, &pcArgv); 1017 if (NULL == pDisplay) 994 if (pCtx->appContext == NULL) 995 { 996 LogRel(("Shared Clipboard: Failed to create Xt application context\n")); 997 return VERR_NOT_SUPPORTED; /** @todo Fudge! */ 998 } 999 1000 /* Create a window and make it a clipboard viewer. */ 1001 int cArgc = 0; 1002 char *pcArgv = 0; 1003 Display *pDisplay = XtOpenDisplay(pCtx->appContext, 0, 0, "VBoxShCl", 0, 0, &cArgc, &pcArgv); 1004 if (pDisplay == NULL) 1018 1005 { 1019 1006 LogRel(("Shared Clipboard: Failed to connect to the X11 clipboard - the window system may not be running\n")); 1020 1007 rc = VERR_NOT_SUPPORTED; 1021 1008 } 1009 1022 1010 #ifndef TESTCASE 1023 1011 if (RT_SUCCESS(rc)) … … 1035 1023 pDisplay, XtNwidth, 1, XtNheight, 1036 1024 1, NULL); 1037 if ( NULL == pCtx->pWidget)1038 { 1039 LogRel(("Shared Clipboard: Failed to construct the X11 window for the shared clipboard manager\n"));1040 rc = VERR_NO_MEMORY; 1025 if (pCtx->pWidget == NULL) 1026 { 1027 LogRel(("Shared Clipboard: Failed to construct the X11 window\n")); 1028 rc = VERR_NO_MEMORY; /** @todo r=andy Improve this. */ 1041 1029 } 1042 1030 else … … 1048 1036 XtSetMappedWhenManaged(pCtx->pWidget, false); 1049 1037 XtRealizeWidget(pCtx->pWidget); 1038 1050 1039 #ifndef TESTCASE 1051 1040 /* Enable clipboard update notification. */ … … 1056 1045 } 1057 1046 1058 /*1059 * Create the pipes.1060 */1061 int pipes[2];1062 if (!pipe(pipes))1063 {1064 pCtx->wakeupPipeRead = pipes[0];1065 pCtx->wakeupPipeWrite = pipes[1];1066 if (!XtAppAddInput(pCtx->appContext, pCtx->wakeupPipeRead,1067 (XtPointer) XtInputReadMask,1068 clipDrainWakeupPipe, (XtPointer) pCtx))1069 rc = VERR_NO_MEMORY; /* What failure means is not doc'ed. */1070 if ( RT_SUCCESS(rc)1071 && (fcntl(pCtx->wakeupPipeRead, F_SETFL, O_NONBLOCK) != 0))1072 rc = RTErrConvertFromErrno(errno);1073 if (RT_FAILURE(rc))1074 LogRel(("Shared Clipboard: Failed to setup the termination mechanism\n"));1075 }1076 else1077 rc = RTErrConvertFromErrno(errno);1078 1047 if (RT_FAILURE(rc)) 1079 clipUninit(pCtx); 1080 if (RT_FAILURE(rc)) 1048 { 1081 1049 LogRel(("Shared Clipboard: Initialisation failed: %Rrc\n", rc)); 1050 clipUninitInternal(pCtx); 1051 } 1052 1053 LogFlowFuncLeaveRC(rc); 1082 1054 return rc; 1083 1055 } 1084 1056 1085 1057 /** 1086 * Initializes the X11 context of the Shared Clipboard. 1058 * X11-specific uninitialisation for the Shared Clipboard. 1059 * 1060 * Note: Must be called from the thread serving the Xt stuff. 1061 * 1062 * @param pCtx The X11 clipboard context to uninit. 1063 */ 1064 static void clipUninitInternal(PSHCLX11CTX pCtx) 1065 { 1066 AssertPtrReturnVoid(pCtx); 1067 1068 LogFlowFunc(("pCtx=%p\n", pCtx)); 1069 1070 if (pCtx->pWidget) 1071 { 1072 /* Valid widget + invalid appcontext = bug. But don't return yet. */ 1073 AssertPtr(pCtx->appContext); 1074 clipUnregisterContext(pCtx); 1075 1076 XtDestroyWidget(pCtx->pWidget); 1077 pCtx->pWidget = NULL; 1078 } 1079 1080 if (pCtx->appContext) 1081 { 1082 XtDestroyApplicationContext(pCtx->appContext); 1083 pCtx->appContext = NULL; 1084 } 1085 1086 LogFlowFuncLeaveRC(VINF_SUCCESS); 1087 } 1088 1089 /** 1090 * Initializes a X11 context of the Shared Clipboard. 1087 1091 * 1088 1092 * @returns VBox status code. … … 1098 1102 AssertPtrReturn(pParent, VERR_INVALID_POINTER); 1099 1103 #endif 1104 1105 LogFlowFunc(("pCtx=%p\n", pCtx)); 1106 1107 int rc = VINF_SUCCESS; 1100 1108 1101 1109 RT_BZERO(pCtx, sizeof(SHCLX11CTX)); … … 1120 1128 #endif 1121 1129 1122 LogFlowFuncLeaveRC(VINF_SUCCESS); 1123 return VINF_SUCCESS; 1124 } 1125 1126 /** 1127 * Destructs the Shared Clipboard X11 context. 1130 #ifdef TESTCASE 1131 if (RT_SUCCESS(rc)) 1132 { 1133 /** @todo The testcases currently do not utilize the threading code. So init stuff here. */ 1134 rc = clipInitInternal(pCtx); 1135 } 1136 #endif 1137 1138 LogFlowFuncLeaveRC(rc); 1139 return rc; 1140 } 1141 1142 /** 1143 * Destroys a Shared Clipboard X11 context. 1128 1144 * 1129 1145 * @param pCtx The X11 clipboard context to destroy. … … 1133 1149 if (!pCtx) 1134 1150 return; 1151 1152 LogFlowFunc(("pCtx=%p\n", pCtx)); 1153 1154 #ifdef TESTCASE 1155 /** @todo The testcases currently do not utilize the threading code. So uninit stuff here. */ 1156 clipUninitInternal(pCtx); 1157 #endif 1135 1158 1136 1159 if (pCtx->fHaveX11) … … 1143 1166 } 1144 1167 1145 /** 1146 * Announces to the X11 backend that we are ready to start. 1168 #ifndef TESTCASE 1169 /** 1170 * Starts our own Xt even thread for handling Shared Clipboard messages. 1147 1171 * 1148 1172 * @returns VBox status code. … … 1160 1184 return VINF_SUCCESS; 1161 1185 1162 int rc = clipInit(pCtx); 1186 pCtx->fGrabClipboardOnStart = fGrab; 1187 1188 clipResetX11Formats(pCtx); 1189 1190 int rc; 1191 1192 /* 1193 * Create the pipes. 1194 ** @todo r=andy Replace this with RTPipe API. 1195 */ 1196 int pipes[2]; 1197 if (!pipe(pipes)) 1198 { 1199 pCtx->wakeupPipeRead = pipes[0]; 1200 pCtx->wakeupPipeWrite = pipes[1]; 1201 if (!XtAppAddInput(pCtx->appContext, pCtx->wakeupPipeRead, 1202 (XtPointer) XtInputReadMask, 1203 clipThreadDrainWakeupPipe, (XtPointer) pCtx)) 1204 rc = VERR_NO_MEMORY; /* What failure means is not doc'ed. */ 1205 if ( RT_SUCCESS(rc) 1206 && (fcntl(pCtx->wakeupPipeRead, F_SETFL, O_NONBLOCK) != 0)) 1207 rc = RTErrConvertFromErrno(errno); 1208 if (RT_FAILURE(rc)) 1209 LogRel(("Shared Clipboard: Failed to setup the termination mechanism\n")); 1210 } 1211 else 1212 rc = RTErrConvertFromErrno(errno); 1213 1163 1214 if (RT_SUCCESS(rc)) 1164 1215 { 1165 clipResetX11Formats(pCtx);1166 pCtx->fGrabClipboardOnStart = fGrab;1167 1168 #ifndef TESTCASE1169 1216 LogRel2(("Shared Clipboard: Starting X11 event thread ...\n")); 1170 1217 1171 rc = RTThreadCreate(&pCtx->Thread, clip EventThread, pCtx, 0,1218 rc = RTThreadCreate(&pCtx->Thread, clipThreadMain, pCtx, 0, 1172 1219 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLX11"); 1173 1220 if (RT_SUCCESS(rc)) … … 1177 1224 { 1178 1225 LogRel(("Shared Clipboard: Failed to start the X11 event thread with %Rrc\n", rc)); 1179 clipUninit (pCtx);1226 clipUninitInternal(pCtx); 1180 1227 } 1181 1228 else 1182 1229 LogRel2(("Shared Clipboard: X11 event thread started\n")); 1183 #endif 1184 } 1185 1230 } 1231 1232 LogFlowFuncLeaveRC(rc); 1186 1233 return rc; 1187 1234 } 1188 1235 1189 1236 /** 1190 * S huts down the shared clipboard X11 backend.1237 * Stops the Shared Clipboard Xt even thread. 1191 1238 * 1192 1239 * @note Any requests from this object to get clipboard data from VBox … … 1206 1253 return VINF_SUCCESS; 1207 1254 1208 LogRel2(("Shared Clipboard: S topping X11 event thread ...\n"));1255 LogRel2(("Shared Clipboard: Signalling the X11 event thread to stop\n")); 1209 1256 1210 1257 /* Write to the "stop" pipe. */ 1211 clipQueueToEventThread(pCtx, clipStopEventThreadWorker, (XtPointer)pCtx); 1212 1213 int rc; 1214 1215 #ifndef TESTCASE 1258 clipThreadScheduleCall(pCtx, clipThreadSignalStop, (XtPointer)pCtx); 1259 1216 1260 LogRel2(("Shared Clipboard: Waiting for X11 event thread to stop ...\n")); 1217 1261 1218 1262 int rcThread; 1219 rc = RTThreadWait(pCtx->Thread, RT_MS_30SEC /* msTimeout */, &rcThread);1263 int rc = RTThreadWait(pCtx->Thread, RT_MS_30SEC /* msTimeout */, &rcThread); 1220 1264 if (RT_SUCCESS(rc)) 1221 1265 rc = rcThread; 1222 1223 if (RT_FAILURE(rc)) 1266 if (RT_SUCCESS(rc)) 1267 { 1268 if (pCtx->wakeupPipeRead != 0) 1269 { 1270 close(pCtx->wakeupPipeRead); 1271 pCtx->wakeupPipeRead = 0; 1272 } 1273 1274 if (pCtx->wakeupPipeWrite != 0) 1275 { 1276 close(pCtx->wakeupPipeWrite); 1277 pCtx->wakeupPipeWrite = 0; 1278 } 1279 } 1280 1281 if (RT_SUCCESS(rc)) 1282 { 1283 LogRel2(("Shared Clipboard: X11 event thread stopped successfully\n")); 1284 } 1285 else 1224 1286 LogRel(("Shared Clipboard: Stopping X11 event thread failed with %Rrc\n", rc)); 1225 #else 1226 rc = VINF_SUCCESS; 1227 #endif 1228 1229 LogRel2(("Shared Clipboard: X11 event thread stopped\n")); 1230 1231 clipUninit(pCtx); 1287 1288 LogFlowFuncLeaveRC(rc); 1232 1289 return rc; 1233 1290 } 1291 #endif /* !TESTCASE */ 1234 1292 1235 1293 /** … … 1754 1812 pFormats->Formats = uFormats; 1755 1813 1756 rc = clip QueueToEventThread(pCtx, ShClX11ReportFormatsToX11Worker,1814 rc = clipThreadScheduleCall(pCtx, ShClX11ReportFormatsToX11Worker, 1757 1815 (XtPointer)pFormats); 1758 1816 } … … 2150 2208 2151 2209 /* We use this to schedule a worker function on the event thread. */ 2152 rc = clip QueueToEventThread(pCtx, ShClX11ReadDataFromX11Worker, (XtPointer)pX11Req);2210 rc = clipThreadScheduleCall(pCtx, ShClX11ReadDataFromX11Worker, (XtPointer)pX11Req); 2153 2211 } 2154 2212 else -
trunk/src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardGH-X11.cpp
r86702 r86712 56 56 void tstRequestTargets(SHCLX11CTX* pCtx); 57 57 void tstClipRequestData(PSHCLX11CTX pCtx, SHCLX11FMTIDX target, void *closure); 58 void tst ClipQueueToEventThread(void (*proc)(void *, void *), void *client_data);58 void tstThreadScheduleCall(void (*proc)(void *, void *), void *client_data); 59 59 60 60 … … 76 76 /* For the purpose of the test case, we just execute the procedure to be 77 77 * scheduled, as we are running single threaded. */ 78 void tst ClipQueueToEventThread(void (*proc)(void *, void *), void *client_data)78 void tstThreadScheduleCall(void (*proc)(void *, void *), void *client_data) 79 79 { 80 80 proc(client_data, NULL); … … 670 670 */ 671 671 SHCLX11CTX X11Ctx; 672 rc = ShClX11Init(&X11Ctx, NULL , false);672 rc = ShClX11Init(&X11Ctx, NULL /* pParent */, false /* fHeadless */); 673 673 AssertRCReturn(rc, RTEXITCODE_FAILURE); 674 674 675 char *pc; 675 676 uint32_t cbActual; 676 677 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)&pReq, *pReqRet = NULL; 677 rc = ShClX11ThreadStart(&X11Ctx, false /* fGrab */);678 AssertRCReturn(rc, RTEXITCODE_FAILURE);679 678 680 679 /* UTF-8 from X11 */ … … 889 888 tstBadFormatRequestFromHost(hTest, &X11Ctx); 890 889 891 rc = ShClX11ThreadStop(&X11Ctx);892 AssertRCReturn(rc, RTEXITCODE_FAILURE);893 890 ShClX11Destroy(&X11Ctx); 894 891 … … 896 893 * Headless clipboard tests 897 894 */ 898 rc = ShClX11Init(&X11Ctx, NULL, true); 899 AssertRCReturn(rc, RTEXITCODE_FAILURE); 900 rc = ShClX11ThreadStart(&X11Ctx, false /* fGrab */); 895 rc = ShClX11Init(&X11Ctx, NULL /* pParent */, true /* fHeadless */); 901 896 AssertRCReturn(rc, RTEXITCODE_FAILURE); 902 897 … … 919 914 tstNoSelectionOwnership(&X11Ctx, "reading from VBox, headless clipboard"); 920 915 921 rc = ShClX11ThreadStop(&X11Ctx);922 AssertRCReturn(rc, RTEXITCODE_FAILURE);923 924 916 ShClX11Destroy(&X11Ctx); 917 /* Note: Doing this twice is intentional. */ 918 ShClX11Destroy(&X11Ctx); 925 919 926 920 return RTTestSummaryAndDestroy(hTest);
Note:
See TracChangeset
for help on using the changeset viewer.