From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621601944; cv=none; d=zohomail.com; s=zohoarc; b=m7wlyehluvFEy5bQ33TkS3TdjS8PcniEALoB3B8xKzWRhEhxWan8iZmJB51RcgkEJE/Qp+oPpzF8tybG3GMe5BfiYb79pF/sOJMlaXE51Irx0w5fh69Z5Kx/m7cKlwa2gJgwbVcBxuIn4ZC2MuJnBB1VGcP3rYJ+xikXQ/aBtcU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621601944; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ov1Os6JUMA/qSEiClpfphRJ1Q5lU0+6PNvwPHjclB2A=; b=bqrfFE/2k5HdaZnxVqtkgtw7dcA9oqMMXBbWJOAjBllR0Zwk4qjITGz+gxUqAYn0h8hBsIOWU15RIQ7jQtI6a7Y35bbxGe9rizx3mypMFn4WYtIOx1WOMK/+lgrgWVzBOt4lRewl/DVhNe3R0IAVg5u9YAHAu4AdTJiR+YO+hcc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621601944373252.1926653422986; Fri, 21 May 2021 05:59:04 -0700 (PDT) Received: from localhost ([::1]:54888 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4k2-0000hg-P2 for importer@patchew.org; Fri, 21 May 2021 08:59:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52626) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4eI-0005sc-MS for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:06 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:29887) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4eH-0007tV-7U for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:06 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-212-S4aBkGTfNsuWyW8SLn4w_w-1; Fri, 21 May 2021 08:53:02 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D7B641926DA3; Fri, 21 May 2021 12:53:01 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8555059468; Fri, 21 May 2021 12:52:46 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 46B0818003A4; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601584; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ov1Os6JUMA/qSEiClpfphRJ1Q5lU0+6PNvwPHjclB2A=; b=icniUeEzU2WYxY1nV8vulPXyfSl7Mx2ZqSIPhpcsrEymNHuW3QUKxdxQyX3uWRfUs695DH K9G2kTdxvf5Xa/EXuifv89AuYZk9DtYoWXn2mSHsHeiPD6k/JkTet58RBxX1OlwLggVmOC PC3ftSQhNPhHC8pcl5jIJc8LV3tXC4o= X-MC-Unique: S4aBkGTfNsuWyW8SLn4w_w-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 01/11] vnc: spelling fix (enable->enabled) Date: Fri, 21 May 2021 14:51:09 +0200 Message-Id: <20210521125119.3173309-2-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Tokarev , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) From: Michael Tokarev Signed-off-by: Michael Tokarev Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20210508092558.351102-1-mjt@msgid.tls.msk.ru> Signed-off-by: Gerd Hoffmann --- ui/vnc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/vnc.c b/ui/vnc.c index 456db47d713d..2bea46b2b3f8 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -596,7 +596,7 @@ bool vnc_display_reload_certs(const char *id, Error **e= rrp) } =20 if (!vd->tlscreds) { - error_setg(errp, "vnc tls is not enable"); + error_setg(errp, "vnc tls is not enabled"); return false; } =20 --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621601842; cv=none; d=zohomail.com; s=zohoarc; b=ZuBS9XTjJdeInfn6OOxhxO0W6ByzxKnhxGcFeENBOtaaZ3tW39BSFpEJAULvrEpsFQ1ECiyD2o+mpuiUuUuCWQAkf6/MDrw/0Jn5pAMahbuKmXUZQqyYe+R1JwgtY4BtDXLX06jBdAu8qBy/zujdAOb6HAl6hbuhYf0j0809XYc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621601842; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=bRU+uGCTs+4KNsAW5Vo/HZG4V1u3wULdCWXqgWvdMkw=; b=L9miwWopmAQZ1LDmtKDtG/W2TKlWmh6wiMSk/xEHBMZZDR8fyFkEqsTGRYZTT7BXXBZk1zYMLsS6tzI36YBHwQ95Qf/ofILLSliAZxeQe8f0MCiDKud5bItYfY/xX7ppJpy6baUNaoIextRZ4+11vBkYcf0rIDGGOBJQbmV0B9Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621601842511673.263607549639; Fri, 21 May 2021 05:57:22 -0700 (PDT) Received: from localhost ([::1]:51090 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4iO-0006Xe-Ha for importer@patchew.org; Fri, 21 May 2021 08:57:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52666) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4eK-0005vM-SZ for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:08 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:45419) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4eI-0007tb-BH for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:08 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-233-bYxxyKTMPBmH-QsgIaVCKQ-1; Fri, 21 May 2021 08:53:02 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D42C71926DA2; Fri, 21 May 2021 12:53:01 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A13C759472; Fri, 21 May 2021 12:52:49 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 51E59180079A; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601585; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bRU+uGCTs+4KNsAW5Vo/HZG4V1u3wULdCWXqgWvdMkw=; b=YGFtSNTQ9PHeP9v7+/qJeulbN0Pwj8VkzXk5pAxyzIlIoNwV6WGLSpZcZCGewKkIFIpIjO gMNZnwxIRwKa9H1Gf/4AfPEm2R6duDPVbnJT/xu4UBMjEPXfj9ic0tq3sqMXrT/ixJ3JZy 6tpF9A/GFQkt9xkAGVOX0io7yVe5jTM= X-MC-Unique: bYxxyKTMPBmH-QsgIaVCKQ-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 02/11] ui/spice-display: check NULL pointer in interface_release_resource() Date: Fri, 21 May 2021 14:51:10 +0200 Message-Id: <20210521125119.3173309-3-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mauro Matteo Cascella , Prasad J Pandit , Yu Lu , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Paolo Bonzini Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Mauro Matteo Cascella Check rext.info to avoid potential NULL pointer dereference. A similar check exists in interface_release_resource() in hw/display/qxl.c. Reported-by: Yu Lu Signed-off-by: Mauro Matteo Cascella Reviewed-by: Prasad J Pandit Message-Id: <20210520105833.183160-1-mcascell@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/spice-display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/spice-display.c b/ui/spice-display.c index d22781a23d06..f59c69882d91 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -561,6 +561,10 @@ static void interface_release_resource(QXLInstance *si= n, SimpleSpiceCursor *cursor; QXLCommandExt *ext; =20 + if (!rext.info) { + return; + } + ext =3D (void *)(intptr_t)(rext.info->id); switch (ext->cmd.type) { case QXL_CMD_DRAW: --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621601841; cv=none; d=zohomail.com; s=zohoarc; b=OV5H0BuEGU+8mwt1po8pONZtuUEVds6Das1umlNZeQHuV4z//QzKySLnBYRjNIWveacrzhb/lqHryOB8/fiRelibg3IErjMFONANsDBjgAzQJf6uX96LQf2nw3CJNiOVjHyi7QQhLvTz5wtAgZW3Y6s651dU7CG0E7lGrIT/AwI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621601841; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=DvS2lA1LIz9bbsInz9wVxHEThudVqUdsdU1VrezB0IM=; b=imnwskWwpsG2WgZ9HJHZpZ6sxYEDfSWuhvcKn5qrgaX4gTINrxpADXwlS8sKm0LRagxjSscry3FDKTxun2hPu+UoGR0nv3HL3hELQybxYhrmK6GWgRcq2xljADA4aMgYE79VAMVi7lh64iXX4LNArFIHOJCqyaj7UAhvqGmXHMA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621601841104318.65625292820675; Fri, 21 May 2021 05:57:21 -0700 (PDT) Received: from localhost ([::1]:50990 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4iO-0006Ts-4g for importer@patchew.org; Fri, 21 May 2021 08:57:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52776) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4ek-0006sq-Dp for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:20924) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4ei-0007xG-K2 for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:34 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-104-OGWMm_70Mr-whMHgygvf3A-1; Fri, 21 May 2021 08:53:30 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B162C8A9F43 for ; Fri, 21 May 2021 12:53:29 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id EAB195D9D5; Fri, 21 May 2021 12:53:04 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 5EA3818007A1; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601612; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DvS2lA1LIz9bbsInz9wVxHEThudVqUdsdU1VrezB0IM=; b=OP8xzgdlxc4wWdWuZZW0Z09EsjDUY7aLa8hoBpjVv48m1k0uzOQUQT74ifZ2vtANnl7BbM zzxtGX8szp3+35UwbBo0zZ7bbxZI6zcJl8hmuqcUKZK7HbMribIXV1S/NM/87HHtbeHppN hSSBAEnUFFVaZ/wcE8AhKCsCelVW51A= X-MC-Unique: OGWMm_70Mr-whMHgygvf3A-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 03/11] build: add separate spice-protocol config option Date: Fri, 21 May 2021 14:51:11 +0200 Message-Id: <20210521125119.3173309-4-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) When implementing spice vdagent protocol in qemu we only need the spice-protocol package for that, spice-server is not needed. So go split those two build dependencies. Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-Andr=C3=A9 Lureau Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-2-kraxel@redhat.com> --- configure | 36 ++++++++++++++++++++++++++++++++---- meson.build | 4 ++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 9470fff09ab7..676239c69707 100755 --- a/configure +++ b/configure @@ -389,6 +389,7 @@ qom_cast_debug=3D"yes" trace_backends=3D"log" trace_file=3D"trace" spice=3D"$default_feature" +spice_protocol=3D"auto" rbd=3D"auto" smartcard=3D"$default_feature" u2f=3D"auto" @@ -1132,7 +1133,15 @@ for opt do ;; --disable-spice) spice=3D"no" ;; - --enable-spice) spice=3D"yes" + --enable-spice) + spice_protocol=3D"yes" + spice=3D"yes" + ;; + --disable-spice-protocol) + spice_protocol=3D"no" + spice=3D"no" + ;; + --enable-spice-protocol) spice_protocol=3D"yes" ;; --disable-libiscsi) libiscsi=3D"disabled" ;; @@ -1870,6 +1879,7 @@ disabled with --disable-FEATURE, default is enabled i= f available vhost-user-blk-server vhost-user-blk server support vhost-vdpa vhost-vdpa kernel backend support spice spice + spice-protocol spice-protocol rbd rados block device (rbd) libiscsi iscsi support libnfs nfs support @@ -4153,6 +4163,19 @@ fi =20 ########################################## # spice probe +if test "$spice_protocol" !=3D "no" ; then + spice_protocol_cflags=3D$($pkg_config --cflags spice-protocol 2>/dev/nul= l) + if $pkg_config --atleast-version=3D0.12.3 spice-protocol; then + spice_protocol=3D"yes" + else + if test "$spice_protocol" =3D "yes" ; then + feature_not_found "spice_protocol" \ + "Install spice-protocol(>=3D0.12.3) devel" + fi + spice_protocol=3D"no" + fi +fi + if test "$spice" !=3D "no" ; then cat > $TMPC << EOF #include @@ -4161,13 +4184,13 @@ EOF spice_cflags=3D$($pkg_config --cflags spice-protocol spice-server 2>/dev= /null) spice_libs=3D$($pkg_config --libs spice-protocol spice-server 2>/dev/nul= l) if $pkg_config --atleast-version=3D0.12.5 spice-server && \ - $pkg_config --atleast-version=3D0.12.3 spice-protocol && \ + test "$spice_protocol" =3D "yes" && \ compile_prog "$spice_cflags" "$spice_libs" ; then spice=3D"yes" else if test "$spice" =3D "yes" ; then feature_not_found "spice" \ - "Install spice-server(>=3D0.12.5) and spice-protocol(>=3D0.12.3)= devel" + "Install spice-server(>=3D0.12.5) devel" fi spice=3D"no" fi @@ -5836,9 +5859,14 @@ fi if test "$posix_memalign" =3D "yes" ; then echo "CONFIG_POSIX_MEMALIGN=3Dy" >> $config_host_mak fi + +if test "$spice_protocol" =3D "yes" ; then + echo "CONFIG_SPICE_PROTOCOL=3Dy" >> $config_host_mak + echo "SPICE_PROTOCOL_CFLAGS=3D$spice_protocol_cflags" >> $config_host_mak +fi if test "$spice" =3D "yes" ; then echo "CONFIG_SPICE=3Dy" >> $config_host_mak - echo "SPICE_CFLAGS=3D$spice_cflags" >> $config_host_mak + echo "SPICE_CFLAGS=3D$spice_cflags $spice_protocol_cflags" >> $config_ho= st_mak echo "SPICE_LIBS=3D$spice_libs" >> $config_host_mak fi =20 diff --git a/meson.build b/meson.build index 1559e8d873a7..632b380738d3 100644 --- a/meson.build +++ b/meson.build @@ -458,11 +458,15 @@ if 'CONFIG_LIBJACK' in config_host endif spice =3D not_found spice_headers =3D not_found +spice_protocol =3D not_found if 'CONFIG_SPICE' in config_host spice =3D declare_dependency(compile_args: config_host['SPICE_CFLAGS'].s= plit(), link_args: config_host['SPICE_LIBS'].split()) spice_headers =3D declare_dependency(compile_args: config_host['SPICE_CF= LAGS'].split()) endif +if 'CONFIG_SPICE_PROTOCOL' in config_host + spice_protocol =3D declare_dependency(compile_args: config_host['SPICE_P= ROTOCOL_CFLAGS'].split()) +endif rt =3D cc.find_library('rt', required: false) libdl =3D not_found if 'CONFIG_PLUGIN' in config_host --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621601708; cv=none; d=zohomail.com; s=zohoarc; b=homN3X0qlAx7/EwRnY6Yg2XljWrr2k4x4Txk49xtdvuJa746CgGzm+j365c8yVU3vmvwkw1WhzI2FQFpKBDwCLYNVyEsGQCB3/b0UHo4tiYMn9lbW+rgJYmKa+dc3vHTPXV9khiNg9jC+WDbLd5ZbvKAjDO9quyXy8637ocnj1Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621601708; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Ka/cQLhtvKobc8iWAYdhUTaAo6+fO3HHkbu2dBlUls4=; b=WywALXUbk6DJpcK9YDffQ73yhyZvX5Q+0KBmzijlzWPdx4bMwsrcnI0ImAPp/+j0uTWLaU6luwbizpO6DHMcpdTAAyEf8bHH9s/w5sXpLBl0frroqXl4FZVP+3cwRral+UxV6L3eACqDRqdmHuB73Sm2EKHopZEtbdTmjWtG5CU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621601708507554.5977135127409; Fri, 21 May 2021 05:55:08 -0700 (PDT) Received: from localhost ([::1]:41712 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4gE-00007V-QX for importer@patchew.org; Fri, 21 May 2021 08:55:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52682) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4eV-00064o-Jz for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:19 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:32797) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4eT-0007um-Mp for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:19 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-54-YyvWEqkmPtewS4VVaHJlTQ-1; Fri, 21 May 2021 08:53:13 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9D61913E0 for ; Fri, 21 May 2021 12:53:12 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D272860D52; Fri, 21 May 2021 12:53:04 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 6E42818007A4; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601595; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ka/cQLhtvKobc8iWAYdhUTaAo6+fO3HHkbu2dBlUls4=; b=MDGv5Ou5JoPvDe3580W5pczwqZjlo6EH2hsFp62gcTIDUwmxnzSFAzkvZ30KI2nEncMtVH M5cM25P9v6lhmdRntM3TjT1okw7J8HbnhmN9AAchCmZwzR6aEPvVibhUbJ+10LNIfFz05z HJB5XAv4rMNUav/RkhqbdPT6NzxEOMQ= X-MC-Unique: YyvWEqkmPtewS4VVaHJlTQ-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 04/11] ui: add clipboard infrastructure Date: Fri, 21 May 2021 14:51:12 +0200 Message-Id: <20210521125119.3173309-5-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Add some infrastructure to manage the clipboard in qemu. Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-Andr=C3=A9 Lureau Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-3-kraxel@redhat.com> --- include/ui/clipboard.h | 62 ++++++++++++++++++++++++++++ ui/clipboard.c | 92 ++++++++++++++++++++++++++++++++++++++++++ ui/meson.build | 1 + 3 files changed, 155 insertions(+) create mode 100644 include/ui/clipboard.h create mode 100644 ui/clipboard.c diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h new file mode 100644 index 000000000000..876de7621911 --- /dev/null +++ b/include/ui/clipboard.h @@ -0,0 +1,62 @@ +#ifndef QEMU_CLIPBOARD_H +#define QEMU_CLIPBOARD_H + +#include "qemu/notify.h" + +typedef enum QemuClipboardType QemuClipboardType; +typedef enum QemuClipboardSelection QemuClipboardSelection; +typedef struct QemuClipboardPeer QemuClipboardPeer; +typedef struct QemuClipboardInfo QemuClipboardInfo; + +enum QemuClipboardType { + QEMU_CLIPBOARD_TYPE_TEXT, /* text/plain; charset=3Dutf-8 */ + QEMU_CLIPBOARD_TYPE__COUNT, +}; + +/* same as VD_AGENT_CLIPBOARD_SELECTION_* */ +enum QemuClipboardSelection { + QEMU_CLIPBOARD_SELECTION_CLIPBOARD, + QEMU_CLIPBOARD_SELECTION_PRIMARY, + QEMU_CLIPBOARD_SELECTION_SECONDARY, + QEMU_CLIPBOARD_SELECTION__COUNT, +}; + +struct QemuClipboardPeer { + const char *name; + Notifier update; + void (*request)(QemuClipboardInfo *info, + QemuClipboardType type); +}; + +struct QemuClipboardInfo { + uint32_t refcount; + QemuClipboardPeer *owner; + QemuClipboardSelection selection; + struct { + bool available; + bool requested; + size_t size; + void *data; + } types[QEMU_CLIPBOARD_TYPE__COUNT]; +}; + +void qemu_clipboard_peer_register(QemuClipboardPeer *peer); +void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer); + +QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, + QemuClipboardSelection selectio= n); +QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info); +void qemu_clipboard_info_unref(QemuClipboardInfo *info); + +void qemu_clipboard_update(QemuClipboardInfo *info); +void qemu_clipboard_request(QemuClipboardInfo *info, + QemuClipboardType type); + +void qemu_clipboard_set_data(QemuClipboardPeer *peer, + QemuClipboardInfo *info, + QemuClipboardType type, + uint32_t size, + void *data, + bool update); + +#endif /* QEMU_CLIPBOARD_H */ diff --git a/ui/clipboard.c b/ui/clipboard.c new file mode 100644 index 000000000000..abf2b98f1f89 --- /dev/null +++ b/ui/clipboard.c @@ -0,0 +1,92 @@ +#include "qemu/osdep.h" +#include "ui/clipboard.h" + +static NotifierList clipboard_notifiers =3D + NOTIFIER_LIST_INITIALIZER(clipboard_notifiers); + +void qemu_clipboard_peer_register(QemuClipboardPeer *peer) +{ + notifier_list_add(&clipboard_notifiers, &peer->update); +} + +void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) +{ + notifier_remove(&peer->update); +} + +void qemu_clipboard_update(QemuClipboardInfo *info) +{ + notifier_list_notify(&clipboard_notifiers, info); +} + +QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, + QemuClipboardSelection selectio= n) +{ + QemuClipboardInfo *info =3D g_new0(QemuClipboardInfo, 1); + + info->owner =3D owner; + info->selection =3D selection; + info->refcount =3D 1; + + return info; +} + +QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info) +{ + info->refcount++; + return info; +} + +void qemu_clipboard_info_unref(QemuClipboardInfo *info) +{ + uint32_t type; + + if (!info) { + return; + } + + info->refcount--; + if (info->refcount > 0) { + return; + } + + for (type =3D 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { + g_free(info->types[type].data); + } + g_free(info); +} + +void qemu_clipboard_request(QemuClipboardInfo *info, + QemuClipboardType type) +{ + if (info->types[type].data || + info->types[type].requested || + !info->types[type].available || + !info->owner) + return; + + info->types[type].requested =3D true; + info->owner->request(info, type); +} + +void qemu_clipboard_set_data(QemuClipboardPeer *peer, + QemuClipboardInfo *info, + QemuClipboardType type, + uint32_t size, + void *data, + bool update) +{ + if (!info || + info->owner !=3D peer) { + return; + } + + g_free(info->types[type].data); + info->types[type].data =3D g_memdup(data, size); + info->types[type].size =3D size; + info->types[type].available =3D true; + + if (update) { + qemu_clipboard_update(info); + } +} diff --git a/ui/meson.build b/ui/meson.build index e8d3ff41b905..fc4fb75c2869 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -2,6 +2,7 @@ softmmu_ss.add(pixman) specific_ss.add(when: ['CONFIG_SOFTMMU'], if_true: pixman) # for the inc= lude path =20 softmmu_ss.add(files( + 'clipboard.c', 'console.c', 'cursor.c', 'input-keymap.c', --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621601749; cv=none; d=zohomail.com; s=zohoarc; b=gj6+bIT93YjCpRDGJ9awq+wIPuaUfLpc+Pq//goXTHnDPLoBQwH2n760Sk10XP0WxsuKhneKHFwGtJx8AXEzf9NGmyqNORUXUDfg+DhmTM41uAqn/e3xVd84oFPC2Mi6Uht4xvbNivQBcYMoI/8Vx8p7TCmQFSSLlEC0hPdf8NI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621601749; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=40cv9l8b6pVemAIs+Ylmvkdb9KVDFmVGvRKpm1oIvIY=; b=bctojCAVnjJ9WyA7vCf34rBG5kdOezY2aVBqiveXNliSNIQwBKhk6T3DlLHH76QUuo826F2I1uUm81esjxFUzCAuwoTOwJRXwhmhCvbd1exrpHzfk1lc4kxAVSnDcPM3p+zWbbRjiKNwTyv1Nca78qBh9dxy+xOfHrSLWrtmQqU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621601749636816.245994270764; Fri, 21 May 2021 05:55:49 -0700 (PDT) Received: from localhost ([::1]:42894 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4gp-00011s-6s for importer@patchew.org; Fri, 21 May 2021 08:55:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52746) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4ee-0006SA-0Y for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:28 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:22844) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4ec-0007vU-1h for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:27 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-6-sdiKznu7Nv2Hygy9SN86tA-1; Fri, 21 May 2021 08:53:22 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2D0A1107ACE3 for ; Fri, 21 May 2021 12:53:22 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9430560C17; Fri, 21 May 2021 12:53:14 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 7E38418007BF; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601605; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=40cv9l8b6pVemAIs+Ylmvkdb9KVDFmVGvRKpm1oIvIY=; b=PNi4k+wXJhcwk1OrfpjCqjC8m/vVPyH1uNYi2RpXDKaWs0KY5uYXTKJvzuUIXBLjsTEbbV atbb3RQ7eIKUcBH1RlAzh2W36vQv21pMceZ+s4uTlLvuL5IQOMLPq+RY7HY0FRdYIP6zfp KaV4dpzCfL6EPQn6yuUdsoAy5XWgyOA= X-MC-Unique: sdiKznu7Nv2Hygy9SN86tA-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 05/11] ui: add clipboard documentation Date: Fri, 21 May 2021 14:51:13 +0200 Message-Id: <20210521125119.3173309-6-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Document clipboard infrastructure in qemu. Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-Andr=C3=A9 Lureau Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-4-kraxel@redhat.com> --- include/ui/clipboard.h | 133 ++++++++++++++++++++++++++++++++++++++++- docs/devel/index.rst | 1 + docs/devel/ui.rst | 8 +++ 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 docs/devel/ui.rst diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index 876de7621911..e5bcb365ed62 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -3,17 +3,47 @@ =20 #include "qemu/notify.h" =20 +/** + * DOC: Introduction + * + * The header ``ui/clipboard.h`` declares the qemu clipboard interface. + * + * All qemu elements which want use the clipboard can register as + * clipboard peer. Subsequently they can set the clipboard content + * and get notifications for clipboard updates. + * + * Typical users are user interfaces (gtk), remote access protocols + * (vnc) and devices talking to the guest (vdagent). + * + * Even though the design allows different data types only plain text + * is supported for now. + */ + typedef enum QemuClipboardType QemuClipboardType; typedef enum QemuClipboardSelection QemuClipboardSelection; typedef struct QemuClipboardPeer QemuClipboardPeer; typedef struct QemuClipboardInfo QemuClipboardInfo; =20 +/** + * enum QemuClipboardType + * + * @QEMU_CLIPBOARD_TYPE_TEXT: text/plain; charset=3Dutf-8 + * @QEMU_CLIPBOARD_TYPE__COUNT: type count. + */ enum QemuClipboardType { - QEMU_CLIPBOARD_TYPE_TEXT, /* text/plain; charset=3Dutf-8 */ + QEMU_CLIPBOARD_TYPE_TEXT, QEMU_CLIPBOARD_TYPE__COUNT, }; =20 /* same as VD_AGENT_CLIPBOARD_SELECTION_* */ +/** + * enum QemuClipboardSelection + * + * @QEMU_CLIPBOARD_SELECTION_CLIPBOARD: clipboard (explitcit cut+paste). + * @QEMU_CLIPBOARD_SELECTION_PRIMARY: primary selection (select + middle m= ouse button). + * @QEMU_CLIPBOARD_SELECTION_SECONDARY: secondary selection (dunno). + * @QEMU_CLIPBOARD_SELECTION__COUNT: selection count. + */ enum QemuClipboardSelection { QEMU_CLIPBOARD_SELECTION_CLIPBOARD, QEMU_CLIPBOARD_SELECTION_PRIMARY, @@ -21,6 +51,15 @@ enum QemuClipboardSelection { QEMU_CLIPBOARD_SELECTION__COUNT, }; =20 +/** + * struct QemuClipboardPeer + * + * @name: peer name. + * @update: notifier for clipboard updates. + * @request: callback for clipboard data requests. + * + * Clipboard peer description. + */ struct QemuClipboardPeer { const char *name; Notifier update; @@ -28,6 +67,16 @@ struct QemuClipboardPeer { QemuClipboardType type); }; =20 +/** + * struct QemuClipboardInfo + * + * @refcount: reference counter. + * @owner: clipboard owner. + * @selection: clipboard selection. + * @types: clipboard data array (one entry per type). + * + * Clipboard content data and metadata. + */ struct QemuClipboardInfo { uint32_t refcount; QemuClipboardPeer *owner; @@ -40,18 +89,100 @@ struct QemuClipboardInfo { } types[QEMU_CLIPBOARD_TYPE__COUNT]; }; =20 +/** + * qemu_clipboard_peer_register + * + * @peer: peer information. + * + * Register clipboard peer. Registering is needed for both active + * (set+grab clipboard) and passive (watch clipboard for updates) + * interaction with the qemu clipboard. + */ void qemu_clipboard_peer_register(QemuClipboardPeer *peer); + +/** + * qemu_clipboard_peer_unregister + * + * @peer: peer information. + * + * Unregister clipboard peer. + */ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer); =20 +/** + * qemu_clipboard_info_new + * + * @owner: clipboard owner. + * @selection: clipboard selection. + * + * Allocate a new QemuClipboardInfo and initialize it with the given + * @owner and @selection. + * + * QemuClipboardInfo is a reference-counted struct. The new struct is + * returned with a reference already taken (i.e. reference count is + * one). + */ QemuClipboardInfo *qemu_clipboard_info_new(QemuClipboardPeer *owner, QemuClipboardSelection selectio= n); +/** + * qemu_clipboard_info_ref + * + * @info: clipboard info. + * + * Increase @info reference count. + */ QemuClipboardInfo *qemu_clipboard_info_ref(QemuClipboardInfo *info); + +/** + * qemu_clipboard_info_unref + * + * @info: clipboard info. + * + * Decrease @info reference count. When the count goes down to zero + * free the @info struct itself and all clipboard data. + */ void qemu_clipboard_info_unref(QemuClipboardInfo *info); =20 +/** + * qemu_clipboard_update + * + * @info: clipboard info. + * + * Update the qemu clipboard. Notify all registered peers (including + * the clipboard owner) that the qemu clipboard has been updated. + * + * This is used for both new completely clipboard content and for + * clipboard data updates in response to qemu_clipboard_request() + * calls. + */ void qemu_clipboard_update(QemuClipboardInfo *info); + +/** + * qemu_clipboard_request + * + * @info: clipboard info. + * @type: clipboard data type. + * + * Request clipboard content. Typically the clipboard owner only + * advertises the available data types and provides the actual data + * only on request. + */ void qemu_clipboard_request(QemuClipboardInfo *info, QemuClipboardType type); =20 +/** + * qemu_clipboard_set_data + * + * @peer: clipboard peer. + * @info: clipboard info. + * @type: clipboard data type. + * @size: data size. + * @data: data blob. + * @update: notify peers about the update. + * + * Set clipboard content for the given @type. This function will make + * a copy of the content data and store that. + */ void qemu_clipboard_set_data(QemuClipboardPeer *peer, QemuClipboardInfo *info, QemuClipboardType type, diff --git a/docs/devel/index.rst b/docs/devel/index.rst index 6cf7e2d2330c..cbdbb9049182 100644 --- a/docs/devel/index.rst +++ b/docs/devel/index.rst @@ -36,6 +36,7 @@ Contents: multi-thread-tcg tcg-plugins bitops + ui reset s390-dasd-ipl clocks diff --git a/docs/devel/ui.rst b/docs/devel/ui.rst new file mode 100644 index 000000000000..06c7d622ce74 --- /dev/null +++ b/docs/devel/ui.rst @@ -0,0 +1,8 @@ +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Qemu UI subsystem +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Qemu Clipboard +-------------- + +.. kernel-doc:: include/ui/clipboard.h --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621602001; cv=none; d=zohomail.com; s=zohoarc; b=A7H1rlkaZPIwg8tH29zoLHWOeGFUyMlM+Bbow4jo61hhQws/MKTiOJsy/8nB7gtnebvskPTluHXfEB+oMyw8B+OIuzv7JOIvH7lneNsvwXT1JpmPnvUZ6rDGs9/UBli+5mSN8pH40j8N6URMs5ubaivGgdnuEOCWDGLgDsSGk88= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621602001; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=giU9Ln+ljFE+RcnyyDPeUGXaA1T8XijYcP7djyYrhgA=; b=lgu7bEsjxeJekSvw3k2WdnF110DrYyIUZekYt1T2roe7hzkD7t6W0ofQhBoUTDB3rAOKqXk9niAFcPYMwDI+naW8omZSvNhdp7pBSbouxiI2r6GtbdR/2pTRvMvew4NUxE9y0bKIfEiD2aUjBPrxH2rGyp1Uu18JIY6ilE/DROM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621602000993177.65655119292353; Fri, 21 May 2021 06:00:00 -0700 (PDT) Received: from localhost ([::1]:57534 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4kx-0002Tv-UU for importer@patchew.org; Fri, 21 May 2021 08:59:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52800) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4es-0007DG-TM for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:43 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:42045) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4eq-0007yq-J4 for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:42 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-186-B0MALUpqNIOTO-Zsm5Ujlg-1; Fri, 21 May 2021 08:53:38 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5355910082E0 for ; Fri, 21 May 2021 12:53:37 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 12123E141; Fri, 21 May 2021 12:53:27 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 911841800840; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601619; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=giU9Ln+ljFE+RcnyyDPeUGXaA1T8XijYcP7djyYrhgA=; b=QGxQsGCn1D2gm9rt1hzVxknoAQugxwmkvB0N69yA+72O2Ub0Yx2BmGnHqDQDFsL5kxwZQ5 6pTT75QJe0VWuSqHaF4yJt3XH9SN11PYGsAktxKrage4HKBAHxgHD6kJ1FKY36bm1aIF0X HBVNuYpXdQcEYJtaXO/xR8vSFTxnlkg= X-MC-Unique: B0MALUpqNIOTO-Zsm5Ujlg-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 06/11] ui/vdagent: core infrastructure Date: Fri, 21 May 2021 14:51:14 +0200 Message-Id: <20210521125119.3173309-7-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) The vdagent protocol allows the guest agent (spice-vdagent) and the spice client exchange messages to implement features which require guest cooperation, for example clipboard support. This is a qemu implementation of the spice client side. This allows the spice guest agent talk to qemu directly when not using the spice protocol. usage: qemu \ -chardev qemu-vdagent,id=3Dvdagent \ -device virtserialport,chardev=3Dvdagent,name=3Dcom.redhat.spice.0 This patch adds just the protocol basics: initial handshake and capability negotiation. The following patches will add actual functionality and also add fields to the initially empty ChardevVDAgent qapi struct. Signed-off-by: Gerd Hoffmann Acked-by: Markus Armbruster Reviewed-by: Marc-Andr=C3=A9 Lureau Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-5-kraxel@redhat.com> --- ui/vdagent.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++ qapi/char.json | 17 ++- ui/meson.build | 1 + ui/trace-events | 8 ++ 4 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 ui/vdagent.c diff --git a/ui/vdagent.c b/ui/vdagent.c new file mode 100644 index 000000000000..21e55a41eaba --- /dev/null +++ b/ui/vdagent.c @@ -0,0 +1,361 @@ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "include/qemu-common.h" +#include "chardev/char.h" +#include "qemu/buffer.h" +#include "qemu/units.h" +#include "trace.h" + +#include "qapi/qapi-types-char.h" + +#include "spice/vd_agent.h" + +#define VDAGENT_BUFFER_LIMIT (1 * MiB) + +struct VDAgentChardev { + Chardev parent; + + /* guest vdagent */ + uint32_t caps; + VDIChunkHeader chunk; + uint32_t chunksize; + uint8_t *msgbuf; + uint32_t msgsize; + uint8_t *xbuf; + uint32_t xoff, xsize; + Buffer outbuf; +}; +typedef struct VDAgentChardev VDAgentChardev; + +#define TYPE_CHARDEV_QEMU_VDAGENT "chardev-qemu-vdagent" + +DECLARE_INSTANCE_CHECKER(VDAgentChardev, QEMU_VDAGENT_CHARDEV, + TYPE_CHARDEV_QEMU_VDAGENT); + +/* ------------------------------------------------------------------ */ +/* names, for debug logging */ + +static const char *cap_name[] =3D { + [VD_AGENT_CAP_MOUSE_STATE] =3D "mouse-state", + [VD_AGENT_CAP_MONITORS_CONFIG] =3D "monitors-config", + [VD_AGENT_CAP_REPLY] =3D "reply", + [VD_AGENT_CAP_CLIPBOARD] =3D "clipboard", + [VD_AGENT_CAP_DISPLAY_CONFIG] =3D "display-config", + [VD_AGENT_CAP_CLIPBOARD_BY_DEMAND] =3D "clipboard-by-demand= ", + [VD_AGENT_CAP_CLIPBOARD_SELECTION] =3D "clipboard-selection= ", + [VD_AGENT_CAP_SPARSE_MONITORS_CONFIG] =3D "sparse-monitors-con= fig", + [VD_AGENT_CAP_GUEST_LINEEND_LF] =3D "guest-lineend-lf", + [VD_AGENT_CAP_GUEST_LINEEND_CRLF] =3D "guest-lineend-crlf", + [VD_AGENT_CAP_MAX_CLIPBOARD] =3D "max-clipboard", + [VD_AGENT_CAP_AUDIO_VOLUME_SYNC] =3D "audio-volume-sync", + [VD_AGENT_CAP_MONITORS_CONFIG_POSITION] =3D "monitors-config-pos= ition", + [VD_AGENT_CAP_FILE_XFER_DISABLED] =3D "file-xfer-disabled", + [VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS] =3D "file-xfer-detailed-= errors", +#if 0 + [VD_AGENT_CAP_GRAPHICS_DEVICE_INFO] =3D "graphics-device-inf= o", + [VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB] =3D "clipboard-no-releas= e-on-regrab", + [VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL] =3D "clipboard-grab-seri= al", +#endif +}; + +static const char *msg_name[] =3D { + [VD_AGENT_MOUSE_STATE] =3D "mouse-state", + [VD_AGENT_MONITORS_CONFIG] =3D "monitors-config", + [VD_AGENT_REPLY] =3D "reply", + [VD_AGENT_CLIPBOARD] =3D "clipboard", + [VD_AGENT_DISPLAY_CONFIG] =3D "display-config", + [VD_AGENT_ANNOUNCE_CAPABILITIES] =3D "announce-capabilities", + [VD_AGENT_CLIPBOARD_GRAB] =3D "clipboard-grab", + [VD_AGENT_CLIPBOARD_REQUEST] =3D "clipboard-request", + [VD_AGENT_CLIPBOARD_RELEASE] =3D "clipboard-release", + [VD_AGENT_FILE_XFER_START] =3D "file-xfer-start", + [VD_AGENT_FILE_XFER_STATUS] =3D "file-xfer-status", + [VD_AGENT_FILE_XFER_DATA] =3D "file-xfer-data", + [VD_AGENT_CLIENT_DISCONNECTED] =3D "client-disconnected", + [VD_AGENT_MAX_CLIPBOARD] =3D "max-clipboard", + [VD_AGENT_AUDIO_VOLUME_SYNC] =3D "audio-volume-sync", +#if 0 + [VD_AGENT_GRAPHICS_DEVICE_INFO] =3D "graphics-device-info", +#endif +}; + +#define GET_NAME(_m, _v) \ + (((_v) < ARRAY_SIZE(_m) && (_m[_v])) ? (_m[_v]) : "???") + +/* ------------------------------------------------------------------ */ +/* send messages */ + +static void vdagent_send_buf(VDAgentChardev *vd) +{ + uint32_t len; + + while (!buffer_empty(&vd->outbuf)) { + len =3D qemu_chr_be_can_write(CHARDEV(vd)); + if (len =3D=3D 0) { + return; + } + if (len > vd->outbuf.offset) { + len =3D vd->outbuf.offset; + } + qemu_chr_be_write(CHARDEV(vd), vd->outbuf.buffer, len); + buffer_advance(&vd->outbuf, len); + } +} + +static void vdagent_send_msg(VDAgentChardev *vd, VDAgentMessage *msg) +{ + uint8_t *msgbuf =3D (void *)msg; + uint32_t msgsize =3D sizeof(VDAgentMessage) + msg->size; + uint32_t msgoff =3D 0; + VDIChunkHeader chunk; + + trace_vdagent_send(GET_NAME(msg_name, msg->type)); + + msg->protocol =3D VD_AGENT_PROTOCOL; + + if (vd->outbuf.offset + msgsize > VDAGENT_BUFFER_LIMIT) { + error_report("buffer full, dropping message"); + return; + } + + while (msgoff < msgsize) { + chunk.port =3D VDP_CLIENT_PORT; + chunk.size =3D msgsize - msgoff; + if (chunk.size > 1024) { + chunk.size =3D 1024; + } + buffer_reserve(&vd->outbuf, sizeof(chunk) + chunk.size); + buffer_append(&vd->outbuf, &chunk, sizeof(chunk)); + buffer_append(&vd->outbuf, msgbuf + msgoff, chunk.size); + msgoff +=3D chunk.size; + } + vdagent_send_buf(vd); +} + +static void vdagent_send_caps(VDAgentChardev *vd) +{ + g_autofree VDAgentMessage *msg =3D g_malloc0(sizeof(VDAgentMessage) + + sizeof(VDAgentAnnounceCapab= ilities) + + sizeof(uint32_t)); + + msg->type =3D VD_AGENT_ANNOUNCE_CAPABILITIES; + msg->size =3D sizeof(VDAgentAnnounceCapabilities) + sizeof(uint32_t); + + vdagent_send_msg(vd, msg); +} + +/* ------------------------------------------------------------------ */ +/* chardev backend */ + +static void vdagent_chr_open(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) +{ +#if defined(HOST_WORDS_BIGENDIAN) + /* + * TODO: vdagent protocol is defined to be LE, + * so we have to byteswap everything on BE hosts. + */ + error_setg(errp, "vdagent is not supported on bigendian hosts"); + return; +#endif + + *be_opened =3D true; +} + +static void vdagent_chr_recv_caps(VDAgentChardev *vd, VDAgentMessage *msg) +{ + VDAgentAnnounceCapabilities *caps =3D (void *)msg->data; + int i; + + if (msg->size < (sizeof(VDAgentAnnounceCapabilities) + + sizeof(uint32_t))) { + return; + } + + for (i =3D 0; i < ARRAY_SIZE(cap_name); i++) { + if (caps->caps[0] & (1 << i)) { + trace_vdagent_peer_cap(GET_NAME(cap_name, i)); + } + } + + vd->caps =3D caps->caps[0]; + if (caps->request) { + vdagent_send_caps(vd); + } +} + +static void vdagent_chr_recv_msg(VDAgentChardev *vd, VDAgentMessage *msg) +{ + trace_vdagent_recv_msg(GET_NAME(msg_name, msg->type), msg->size); + + switch (msg->type) { + case VD_AGENT_ANNOUNCE_CAPABILITIES: + vdagent_chr_recv_caps(vd, msg); + break; + default: + break; + } +} + +static void vdagent_reset_xbuf(VDAgentChardev *vd) +{ + g_clear_pointer(&vd->xbuf, g_free); + vd->xoff =3D 0; + vd->xsize =3D 0; +} + +static void vdagent_chr_recv_chunk(VDAgentChardev *vd) +{ + VDAgentMessage *msg =3D (void *)vd->msgbuf; + + if (!vd->xsize) { + if (vd->msgsize < sizeof(*msg)) { + error_report("%s: message too small: %d < %zd", __func__, + vd->msgsize, sizeof(*msg)); + return; + } + if (vd->msgsize =3D=3D msg->size + sizeof(*msg)) { + vdagent_chr_recv_msg(vd, msg); + return; + } + } + + if (!vd->xsize) { + vd->xsize =3D msg->size + sizeof(*msg); + vd->xbuf =3D g_malloc0(vd->xsize); + } + + if (vd->xoff + vd->msgsize > vd->xsize) { + error_report("%s: Oops: %d+%d > %d", __func__, + vd->xoff, vd->msgsize, vd->xsize); + vdagent_reset_xbuf(vd); + return; + } + + memcpy(vd->xbuf + vd->xoff, vd->msgbuf, vd->msgsize); + vd->xoff +=3D vd->msgsize; + if (vd->xoff < vd->xsize) { + return; + } + + msg =3D (void *)vd->xbuf; + vdagent_chr_recv_msg(vd, msg); + vdagent_reset_xbuf(vd); +} + +static void vdagent_reset_bufs(VDAgentChardev *vd) +{ + memset(&vd->chunk, 0, sizeof(vd->chunk)); + vd->chunksize =3D 0; + g_free(vd->msgbuf); + vd->msgbuf =3D NULL; + vd->msgsize =3D 0; +} + +static int vdagent_chr_write(Chardev *chr, const uint8_t *buf, int len) +{ + VDAgentChardev *vd =3D QEMU_VDAGENT_CHARDEV(chr); + uint32_t copy, ret =3D len; + + while (len) { + if (vd->chunksize < sizeof(vd->chunk)) { + copy =3D sizeof(vd->chunk) - vd->chunksize; + if (copy > len) { + copy =3D len; + } + memcpy((void *)(&vd->chunk) + vd->chunksize, buf, copy); + vd->chunksize +=3D copy; + buf +=3D copy; + len -=3D copy; + if (vd->chunksize < sizeof(vd->chunk)) { + break; + } + + assert(vd->msgbuf =3D=3D NULL); + vd->msgbuf =3D g_malloc0(vd->chunk.size); + } + + copy =3D vd->chunk.size - vd->msgsize; + if (copy > len) { + copy =3D len; + } + memcpy(vd->msgbuf + vd->msgsize, buf, copy); + vd->msgsize +=3D copy; + buf +=3D copy; + len -=3D copy; + + if (vd->msgsize =3D=3D vd->chunk.size) { + trace_vdagent_recv_chunk(vd->chunk.size); + vdagent_chr_recv_chunk(vd); + vdagent_reset_bufs(vd); + } + } + + return ret; +} + +static void vdagent_chr_accept_input(Chardev *chr) +{ + VDAgentChardev *vd =3D QEMU_VDAGENT_CHARDEV(chr); + + vdagent_send_buf(vd); +} + +static void vdagent_chr_set_fe_open(struct Chardev *chr, int fe_open) +{ + VDAgentChardev *vd =3D QEMU_VDAGENT_CHARDEV(chr); + + if (!fe_open) { + trace_vdagent_close(); + /* reset state */ + vdagent_reset_bufs(vd); + vd->caps =3D 0; + return; + } + + trace_vdagent_open(); +} + +/* ------------------------------------------------------------------ */ + +static void vdagent_chr_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc =3D CHARDEV_CLASS(oc); + + cc->open =3D vdagent_chr_open; + cc->chr_write =3D vdagent_chr_write; + cc->chr_set_fe_open =3D vdagent_chr_set_fe_open; + cc->chr_accept_input =3D vdagent_chr_accept_input; +} + +static void vdagent_chr_init(Object *obj) +{ + VDAgentChardev *vd =3D QEMU_VDAGENT_CHARDEV(obj); + + buffer_init(&vd->outbuf, "vdagent-outbuf"); +} + +static void vdagent_chr_fini(Object *obj) +{ + VDAgentChardev *vd =3D QEMU_VDAGENT_CHARDEV(obj); + + buffer_free(&vd->outbuf); +} + +static const TypeInfo vdagent_chr_type_info =3D { + .name =3D TYPE_CHARDEV_QEMU_VDAGENT, + .parent =3D TYPE_CHARDEV, + .instance_size =3D sizeof(VDAgentChardev), + .instance_init =3D vdagent_chr_init, + .instance_finalize =3D vdagent_chr_fini, + .class_init =3D vdagent_chr_class_init, +}; + +static void register_types(void) +{ + type_register_static(&vdagent_chr_type_info); +} + +type_init(register_types); diff --git a/qapi/char.json b/qapi/char.json index 6413970fa73b..990801e642bb 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -390,12 +390,25 @@ 'data': { '*size': 'int' }, 'base': 'ChardevCommon' } =20 +## +# @ChardevQemuVDAgent: +# +# Configuration info for qemu vdagent implementation. +# +# Since: 6.1 +# +## +{ 'struct': 'ChardevQemuVDAgent', + 'data': { }, + 'base': 'ChardevCommon', + 'if': 'defined(CONFIG_SPICE_PROTOCOL)' } + ## # @ChardevBackend: # # Configuration info for the new chardev backend. # -# Since: 1.4 (testdev since 2.2, wctablet since 2.9) +# Since: 1.4 (testdev since 2.2, wctablet since 2.9, vdagent since 6.1) ## { 'union': 'ChardevBackend', 'data': { 'file': 'ChardevFile', @@ -417,6 +430,8 @@ 'if': 'defined(CONFIG_SPICE)' }, 'spiceport': { 'type': 'ChardevSpicePort', 'if': 'defined(CONFIG_SPICE)' }, + 'qemu-vdagent': { 'type': 'ChardevQemuVDAgent', + 'if': 'defined(CONFIG_SPICE_PROTOCOL)' }, 'vc': 'ChardevVC', 'ringbuf': 'ChardevRingbuf', # next one is just for compatibility diff --git a/ui/meson.build b/ui/meson.build index fc4fb75c2869..bad49fb6de60 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -14,6 +14,7 @@ softmmu_ss.add(files( 'qemu-pixman.c', )) softmmu_ss.add([spice_headers, files('spice-module.c')]) +softmmu_ss.add(when: spice_protocol, if_true: files('vdagent.c')) =20 softmmu_ss.add(when: 'CONFIG_LINUX', if_true: files('input-linux.c')) softmmu_ss.add(when: cocoa, if_true: files('cocoa.m')) diff --git a/ui/trace-events b/ui/trace-events index 5d1da6f23668..c34cffb0452b 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -124,3 +124,11 @@ xkeymap_extension(const char *name) "extension '%s'" xkeymap_vendor(const char *name) "vendor '%s'" xkeymap_keycodes(const char *name) "keycodes '%s'" xkeymap_keymap(const char *name) "keymap '%s'" + +# vdagent.c +vdagent_open(void) "" +vdagent_close(void) "" +vdagent_send(const char *name) "msg %s" +vdagent_recv_chunk(uint32_t size) "size %d" +vdagent_recv_msg(const char *name, uint32_t size) "msg %s, size %d" +vdagent_peer_cap(const char *name) "cap %s" --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621602209; cv=none; d=zohomail.com; s=zohoarc; b=Y0DLtuG9NdNNQtkquRdNy9KAfVKRQ/xwJDY43ey9rsVLguUSYgI1g1xPid+34d4UlmBkI9ZwrQX46+pivNHmbGDXcwKgh38NLmPLtLkfVy2cbtrIMVcYSph0E7xEUK+Gxx9+TGS3OTvu71JexanJUKaZJk1/0w70eUMwQsCLtcU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621602209; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=BeDMvSwr47sUdHUuw5UsUFTELxGdO4wzJwtdhMN83Z4=; b=GhMSM+13s378VG0dG+kvLqyPHNAMbcYB0Ims+cUj4+dtJnfuG9DxuVVmOmAsev4a8X4ivQDydQcpognsioXoqEHfNRASQnKPSxG+GfEAACe45fxWl1g4v0i+jPZO+0JXbd9zFEiXsSDWB0wu7ESL4dJb4j4l6xxtpUHplTE/xoA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621602209065811.378493724292; Fri, 21 May 2021 06:03:29 -0700 (PDT) Received: from localhost ([::1]:35964 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4oH-000773-Oc for importer@patchew.org; Fri, 21 May 2021 09:03:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52820) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4ey-0007Ii-MP for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:48 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:50122) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4ew-0007z9-Kf for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:48 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-485-FPfnipXzNReUMUoXSS09fw-1; Fri, 21 May 2021 08:53:44 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BFC131926DA2 for ; Fri, 21 May 2021 12:53:43 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 892966267F; Fri, 21 May 2021 12:53:32 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id A128D180087E; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601626; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BeDMvSwr47sUdHUuw5UsUFTELxGdO4wzJwtdhMN83Z4=; b=PQHeXfA1mT0jSvFuVF6K06xdwfYj23NhSt0HxT/dbdfx/33sT2M5FPVVpfpeMgmGl57OUE A9XMO+c293yM/LXxnR0ll3p7Mx78kQHird9yRTJJMSWurR+yOJV4iJRogMlDkzvx9YrvoR E+lF+zAicQlTiqNQ9r2Y7VVd8oTrYOA= X-MC-Unique: FPfnipXzNReUMUoXSS09fw-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 07/11] ui/vdagent: add mouse support Date: Fri, 21 May 2021 14:51:15 +0200 Message-Id: <20210521125119.3173309-8-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) This patch adds support for mouse messages to the vdagent implementation. This can be enabled/disabled using the new 'mouse' parameter for the vdagent chardev. Default is on. Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-Andr=C3=A9 Lureau Acked-by: Markus Armbruster Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-6-kraxel@redhat.com> --- chardev/char.c | 3 + ui/vdagent.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ qapi/char.json | 4 +- 3 files changed, 155 insertions(+), 1 deletion(-) diff --git a/chardev/char.c b/chardev/char.c index a4ebfcc5ac20..52c567e8ff00 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -931,6 +931,9 @@ QemuOptsList qemu_chardev_opts =3D { },{ .name =3D "logappend", .type =3D QEMU_OPT_BOOL, + },{ + .name =3D "mouse", + .type =3D QEMU_OPT_BOOL, #ifdef CONFIG_LINUX },{ .name =3D "tight", diff --git a/ui/vdagent.c b/ui/vdagent.c index 21e55a41eaba..cf81ab6beb68 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -3,18 +3,27 @@ #include "include/qemu-common.h" #include "chardev/char.h" #include "qemu/buffer.h" +#include "qemu/option.h" #include "qemu/units.h" +#include "hw/qdev-core.h" +#include "ui/console.h" +#include "ui/input.h" #include "trace.h" =20 #include "qapi/qapi-types-char.h" +#include "qapi/qapi-types-ui.h" =20 #include "spice/vd_agent.h" =20 #define VDAGENT_BUFFER_LIMIT (1 * MiB) +#define VDAGENT_MOUSE_DEFAULT true =20 struct VDAgentChardev { Chardev parent; =20 + /* config */ + bool mouse; + /* guest vdagent */ uint32_t caps; VDIChunkHeader chunk; @@ -24,6 +33,14 @@ struct VDAgentChardev { uint8_t *xbuf; uint32_t xoff, xsize; Buffer outbuf; + + /* mouse */ + DeviceState mouse_dev; + uint32_t mouse_x; + uint32_t mouse_y; + uint32_t mouse_btn; + uint32_t mouse_display; + QemuInputHandlerState *mouse_hs; }; typedef struct VDAgentChardev VDAgentChardev; =20 @@ -137,13 +154,113 @@ static void vdagent_send_caps(VDAgentChardev *vd) g_autofree VDAgentMessage *msg =3D g_malloc0(sizeof(VDAgentMessage) + sizeof(VDAgentAnnounceCapab= ilities) + sizeof(uint32_t)); + VDAgentAnnounceCapabilities *caps =3D (void *)msg->data; =20 msg->type =3D VD_AGENT_ANNOUNCE_CAPABILITIES; msg->size =3D sizeof(VDAgentAnnounceCapabilities) + sizeof(uint32_t); + if (vd->mouse) { + caps->caps[0] |=3D (1 << VD_AGENT_CAP_MOUSE_STATE); + } =20 vdagent_send_msg(vd, msg); } =20 +/* ------------------------------------------------------------------ */ +/* mouse events */ + +static bool have_mouse(VDAgentChardev *vd) +{ + return vd->mouse && + (vd->caps & (1 << VD_AGENT_CAP_MOUSE_STATE)); +} + +static void vdagent_send_mouse(VDAgentChardev *vd) +{ + g_autofree VDAgentMessage *msg =3D g_malloc0(sizeof(VDAgentMessage) + + sizeof(VDAgentMouseState)); + VDAgentMouseState *mouse =3D (void *)msg->data; + + msg->type =3D VD_AGENT_MOUSE_STATE; + msg->size =3D sizeof(VDAgentMouseState); + + mouse->x =3D vd->mouse_x; + mouse->y =3D vd->mouse_y; + mouse->buttons =3D vd->mouse_btn; + mouse->display_id =3D vd->mouse_display; + + vdagent_send_msg(vd, msg); +} + +static void vdagent_pointer_event(DeviceState *dev, QemuConsole *src, + InputEvent *evt) +{ + static const int bmap[INPUT_BUTTON__MAX] =3D { + [INPUT_BUTTON_LEFT] =3D VD_AGENT_LBUTTON_MASK, + [INPUT_BUTTON_RIGHT] =3D VD_AGENT_RBUTTON_MASK, + [INPUT_BUTTON_MIDDLE] =3D VD_AGENT_MBUTTON_MASK, + [INPUT_BUTTON_WHEEL_UP] =3D VD_AGENT_UBUTTON_MASK, + [INPUT_BUTTON_WHEEL_DOWN] =3D VD_AGENT_DBUTTON_MASK, +#ifdef VD_AGENT_EBUTTON_MASK + [INPUT_BUTTON_SIDE] =3D VD_AGENT_SBUTTON_MASK, + [INPUT_BUTTON_EXTRA] =3D VD_AGENT_EBUTTON_MASK, +#endif + }; + + VDAgentChardev *vd =3D container_of(dev, struct VDAgentChardev, mouse_= dev); + InputMoveEvent *move; + InputBtnEvent *btn; + uint32_t xres, yres; + + switch (evt->type) { + case INPUT_EVENT_KIND_ABS: + move =3D evt->u.abs.data; + xres =3D qemu_console_get_width(src, 1024); + yres =3D qemu_console_get_height(src, 768); + if (move->axis =3D=3D INPUT_AXIS_X) { + vd->mouse_x =3D qemu_input_scale_axis(move->value, + INPUT_EVENT_ABS_MIN, + INPUT_EVENT_ABS_MAX, + 0, xres); + } else if (move->axis =3D=3D INPUT_AXIS_Y) { + vd->mouse_y =3D qemu_input_scale_axis(move->value, + INPUT_EVENT_ABS_MIN, + INPUT_EVENT_ABS_MAX, + 0, yres); + } + vd->mouse_display =3D qemu_console_get_index(src); + break; + + case INPUT_EVENT_KIND_BTN: + btn =3D evt->u.btn.data; + if (btn->down) { + vd->mouse_btn |=3D bmap[btn->button]; + } else { + vd->mouse_btn &=3D ~bmap[btn->button]; + } + break; + + default: + /* keep gcc happy */ + break; + } +} + +static void vdagent_pointer_sync(DeviceState *dev) +{ + VDAgentChardev *vd =3D container_of(dev, struct VDAgentChardev, mouse_= dev); + + if (vd->caps & (1 << VD_AGENT_CAP_MOUSE_STATE)) { + vdagent_send_mouse(vd); + } +} + +static QemuInputHandler vdagent_mouse_handler =3D { + .name =3D "vdagent mouse", + .mask =3D INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS, + .event =3D vdagent_pointer_event, + .sync =3D vdagent_pointer_sync, +}; + /* ------------------------------------------------------------------ */ /* chardev backend */ =20 @@ -152,6 +269,9 @@ static void vdagent_chr_open(Chardev *chr, bool *be_opened, Error **errp) { + VDAgentChardev *vd =3D QEMU_VDAGENT_CHARDEV(chr); + ChardevQemuVDAgent *cfg =3D backend->u.qemu_vdagent.data; + #if defined(HOST_WORDS_BIGENDIAN) /* * TODO: vdagent protocol is defined to be LE, @@ -161,6 +281,16 @@ static void vdagent_chr_open(Chardev *chr, return; #endif =20 + vd->mouse =3D VDAGENT_MOUSE_DEFAULT; + if (cfg->has_mouse) { + vd->mouse =3D cfg->mouse; + } + + if (vd->mouse) { + vd->mouse_hs =3D qemu_input_handler_register(&vd->mouse_dev, + &vdagent_mouse_handler); + } + *be_opened =3D true; } =20 @@ -184,6 +314,9 @@ static void vdagent_chr_recv_caps(VDAgentChardev *vd, V= DAgentMessage *msg) if (caps->request) { vdagent_send_caps(vd); } + if (have_mouse(vd) && vd->mouse_hs) { + qemu_input_handler_activate(vd->mouse_hs); + } } =20 static void vdagent_chr_recv_msg(VDAgentChardev *vd, VDAgentMessage *msg) @@ -312,18 +445,34 @@ static void vdagent_chr_set_fe_open(struct Chardev *c= hr, int fe_open) /* reset state */ vdagent_reset_bufs(vd); vd->caps =3D 0; + if (vd->mouse_hs) { + qemu_input_handler_deactivate(vd->mouse_hs); + } return; } =20 trace_vdagent_open(); } =20 +static void vdagent_chr_parse(QemuOpts *opts, ChardevBackend *backend, + Error **errp) +{ + ChardevQemuVDAgent *cfg; + + backend->type =3D CHARDEV_BACKEND_KIND_QEMU_VDAGENT; + cfg =3D backend->u.qemu_vdagent.data =3D g_new0(ChardevQemuVDAgent, 1); + qemu_chr_parse_common(opts, qapi_ChardevQemuVDAgent_base(cfg)); + cfg->has_mouse =3D true; + cfg->mouse =3D qemu_opt_get_bool(opts, "mouse", VDAGENT_MOUSE_DEFAULT); +} + /* ------------------------------------------------------------------ */ =20 static void vdagent_chr_class_init(ObjectClass *oc, void *data) { ChardevClass *cc =3D CHARDEV_CLASS(oc); =20 + cc->parse =3D vdagent_chr_parse; cc->open =3D vdagent_chr_open; cc->chr_write =3D vdagent_chr_write; cc->chr_set_fe_open =3D vdagent_chr_set_fe_open; diff --git a/qapi/char.json b/qapi/char.json index 990801e642bb..5711e8c60aeb 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -395,11 +395,13 @@ # # Configuration info for qemu vdagent implementation. # +# @mouse: enable/disable mouse, default is enabled. +# # Since: 6.1 # ## { 'struct': 'ChardevQemuVDAgent', - 'data': { }, + 'data': { '*mouse': 'bool' }, 'base': 'ChardevCommon', 'if': 'defined(CONFIG_SPICE_PROTOCOL)' } =20 --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621602126; cv=none; d=zohomail.com; s=zohoarc; b=lpCSSIUmkxmYAt6J1rLZsv9BM1pp4b0LIfEPtMR/tSIfD4C76tHGaT46/FyDvFmQcHdbWInIyt57WCg51zlFQfAhkwrPPf2cP3rLGEJB2OkAbWQqQO01B/6ZO2tuinw5hn8c+oyG2ZEY3dMXOUV93hIzZ/y6eSPj0Wm6FInX2hQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621602126; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=e/GobeqPWMnoSn9jVN4AltsxbfmBRCBosjxe6Js/HvA=; b=EtxnJK6l/twUqlFz+tbdtnptOI/lanAUEHkxurrfZG76KMnF3umgG/DlvgOAeSRYy7hKIqJNP3rdqYmZN4QpH4ogoeuXI0U1vo9u0HDeVIXM2JZ1yxVCWixKlTdL6OknH008OC+2sYlevY91ZVrNeq96geuUF+XOmwznyvt+vpQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621602126018263.4719385656489; Fri, 21 May 2021 06:02:06 -0700 (PDT) Received: from localhost ([::1]:33102 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4my-00058s-KI for importer@patchew.org; Fri, 21 May 2021 09:02:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52834) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4f1-0007Qy-VV for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:52 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:45951) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4ez-0007zG-0u for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:51 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-104-sWdxyxKfPyugqf_NmAjVCA-1; Fri, 21 May 2021 08:53:46 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A67EB8049D6 for ; Fri, 21 May 2021 12:53:45 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 346685D9D5; Fri, 21 May 2021 12:53:41 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id B421C180087F; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601628; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=e/GobeqPWMnoSn9jVN4AltsxbfmBRCBosjxe6Js/HvA=; b=bKTRqyO6XJmrviIWoo1aDj4gUVpPWocluLpX6yaIPeqjUbZk0iAMnGi1pbjfZgXDHg70/X fZjfRYc7/s4RdYvzEdvH38HAuomRdURLWSDTbBOJSwcXdcOr5vqVYrUQ9dU7doY+mTrm8D Ph7M8nDdBhqx79Jxoi1lKqi9xCp08wU= X-MC-Unique: sWdxyxKfPyugqf_NmAjVCA-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 08/11] ui/vdagent: add clipboard support Date: Fri, 21 May 2021 14:51:16 +0200 Message-Id: <20210521125119.3173309-9-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) This patch adds support for clipboard messages to the qemu vdagent implementation, which allows the guest exchange clipboard data with qemu. Clipboard support can be enabled/disabled using the new 'clipboard' parameter for the vdagent chardev. Default is off. Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-Andr=C3=A9 Lureau Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-7-kraxel@redhat.com> --- chardev/char.c | 3 + ui/vdagent.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++ qapi/char.json | 4 +- ui/trace-events | 2 + 4 files changed, 301 insertions(+), 1 deletion(-) diff --git a/chardev/char.c b/chardev/char.c index 52c567e8ff00..d959eec5229c 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -934,6 +934,9 @@ QemuOptsList qemu_chardev_opts =3D { },{ .name =3D "mouse", .type =3D QEMU_OPT_BOOL, + },{ + .name =3D "clipboard", + .type =3D QEMU_OPT_BOOL, #ifdef CONFIG_LINUX },{ .name =3D "tight", diff --git a/ui/vdagent.c b/ui/vdagent.c index cf81ab6beb68..a253a8fe63a6 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -6,6 +6,7 @@ #include "qemu/option.h" #include "qemu/units.h" #include "hw/qdev-core.h" +#include "ui/clipboard.h" #include "ui/console.h" #include "ui/input.h" #include "trace.h" @@ -17,12 +18,14 @@ =20 #define VDAGENT_BUFFER_LIMIT (1 * MiB) #define VDAGENT_MOUSE_DEFAULT true +#define VDAGENT_CLIPBOARD_DEFAULT false =20 struct VDAgentChardev { Chardev parent; =20 /* config */ bool mouse; + bool clipboard; =20 /* guest vdagent */ uint32_t caps; @@ -41,6 +44,11 @@ struct VDAgentChardev { uint32_t mouse_btn; uint32_t mouse_display; QemuInputHandlerState *mouse_hs; + + /* clipboard */ + QemuClipboardPeer cbpeer; + QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; + uint32_t cbpending[QEMU_CLIPBOARD_SELECTION__COUNT]; }; typedef struct VDAgentChardev VDAgentChardev; =20 @@ -96,6 +104,24 @@ static const char *msg_name[] =3D { #endif }; =20 +static const char *sel_name[] =3D { + [VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD] =3D "clipboard", + [VD_AGENT_CLIPBOARD_SELECTION_PRIMARY] =3D "primary", + [VD_AGENT_CLIPBOARD_SELECTION_SECONDARY] =3D "secondary", +}; + +static const char *type_name[] =3D { + [VD_AGENT_CLIPBOARD_NONE] =3D "none", + [VD_AGENT_CLIPBOARD_UTF8_TEXT] =3D "text", + [VD_AGENT_CLIPBOARD_IMAGE_PNG] =3D "png", + [VD_AGENT_CLIPBOARD_IMAGE_BMP] =3D "bmp", + [VD_AGENT_CLIPBOARD_IMAGE_TIFF] =3D "tiff", + [VD_AGENT_CLIPBOARD_IMAGE_JPG] =3D "jpg", +#if 0 + [VD_AGENT_CLIPBOARD_FILE_LIST] =3D "files", +#endif +}; + #define GET_NAME(_m, _v) \ (((_v) < ARRAY_SIZE(_m) && (_m[_v])) ? (_m[_v]) : "???") =20 @@ -161,6 +187,10 @@ static void vdagent_send_caps(VDAgentChardev *vd) if (vd->mouse) { caps->caps[0] |=3D (1 << VD_AGENT_CAP_MOUSE_STATE); } + if (vd->clipboard) { + caps->caps[0] |=3D (1 << VD_AGENT_CAP_CLIPBOARD_BY_DEMAND); + caps->caps[0] |=3D (1 << VD_AGENT_CAP_CLIPBOARD_SELECTION); + } =20 vdagent_send_msg(vd, msg); } @@ -261,6 +291,244 @@ static QemuInputHandler vdagent_mouse_handler =3D { .sync =3D vdagent_pointer_sync, }; =20 +/* ------------------------------------------------------------------ */ +/* clipboard */ + +static bool have_clipboard(VDAgentChardev *vd) +{ + return vd->clipboard && + (vd->caps & (1 << VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)); +} + +static bool have_selection(VDAgentChardev *vd) +{ + return vd->caps & (1 << VD_AGENT_CAP_CLIPBOARD_SELECTION); +} + +static uint32_t type_qemu_to_vdagent(enum QemuClipboardType type) +{ + switch (type) { + case QEMU_CLIPBOARD_TYPE_TEXT: + return VD_AGENT_CLIPBOARD_UTF8_TEXT; + default: + return VD_AGENT_CLIPBOARD_NONE; + } +} + +static void vdagent_send_clipboard_grab(VDAgentChardev *vd, + QemuClipboardInfo *info) +{ + g_autofree VDAgentMessage *msg =3D + g_malloc0(sizeof(VDAgentMessage) + + sizeof(uint32_t) * (QEMU_CLIPBOARD_TYPE__COUNT + 1)); + uint8_t *s =3D msg->data; + uint32_t *data =3D (uint32_t *)msg->data; + uint32_t q, type; + + if (have_selection(vd)) { + *s =3D info->selection; + data++; + msg->size +=3D sizeof(uint32_t); + } else if (info->selection !=3D QEMU_CLIPBOARD_SELECTION_CLIPBOARD) { + return; + } + + for (q =3D 0; q < QEMU_CLIPBOARD_TYPE__COUNT; q++) { + type =3D type_qemu_to_vdagent(q); + if (type !=3D VD_AGENT_CLIPBOARD_NONE && info->types[q].available)= { + *data =3D type; + data++; + msg->size +=3D sizeof(uint32_t); + } + } + + msg->type =3D VD_AGENT_CLIPBOARD_GRAB; + vdagent_send_msg(vd, msg); +} + +static void vdagent_send_clipboard_data(VDAgentChardev *vd, + QemuClipboardInfo *info, + QemuClipboardType type) +{ + g_autofree VDAgentMessage *msg =3D g_malloc0(sizeof(VDAgentMessage) + + sizeof(uint32_t) * 2 + + info->types[type].size); + + uint8_t *s =3D msg->data; + uint32_t *data =3D (uint32_t *)msg->data; + + if (have_selection(vd)) { + *s =3D info->selection; + data++; + msg->size +=3D sizeof(uint32_t); + } else if (info->selection !=3D QEMU_CLIPBOARD_SELECTION_CLIPBOARD) { + return; + } + + *data =3D type_qemu_to_vdagent(type); + data++; + msg->size +=3D sizeof(uint32_t); + + memcpy(data, info->types[type].data, info->types[type].size); + msg->size +=3D info->types[type].size; + + msg->type =3D VD_AGENT_CLIPBOARD; + vdagent_send_msg(vd, msg); +} + +static void vdagent_clipboard_notify(Notifier *notifier, void *data) +{ + VDAgentChardev *vd =3D container_of(notifier, VDAgentChardev, cbpeer.u= pdate); + QemuClipboardInfo *info =3D data; + QemuClipboardSelection s =3D info->selection; + QemuClipboardType type; + bool self_update =3D info->owner =3D=3D &vd->cbpeer; + + if (info !=3D vd->cbinfo[s]) { + qemu_clipboard_info_unref(vd->cbinfo[s]); + vd->cbinfo[s] =3D qemu_clipboard_info_ref(info); + vd->cbpending[s] =3D 0; + if (!self_update) { + vdagent_send_clipboard_grab(vd, info); + } + return; + } + + if (self_update) { + return; + } + + for (type =3D 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { + if (vd->cbpending[s] & (1 << type)) { + vd->cbpending[s] &=3D ~(1 << type); + vdagent_send_clipboard_data(vd, info, type); + } + } +} + +static void vdagent_clipboard_request(QemuClipboardInfo *info, + QemuClipboardType qtype) +{ + VDAgentChardev *vd =3D container_of(info->owner, VDAgentChardev, cbpee= r); + g_autofree VDAgentMessage *msg =3D g_malloc0(sizeof(VDAgentMessage) + + sizeof(uint32_t) * 2); + uint32_t type =3D type_qemu_to_vdagent(qtype); + uint8_t *s =3D msg->data; + uint32_t *data =3D (uint32_t *)msg->data; + + if (type =3D=3D VD_AGENT_CLIPBOARD_NONE) { + return; + } + + if (have_selection(vd)) { + *s =3D info->selection; + data++; + msg->size +=3D sizeof(uint32_t); + } + + *data =3D type; + msg->size +=3D sizeof(uint32_t); + + msg->type =3D VD_AGENT_CLIPBOARD_REQUEST; + vdagent_send_msg(vd, msg); +} + +static void vdagent_chr_recv_clipboard(VDAgentChardev *vd, VDAgentMessage = *msg) +{ + uint8_t s =3D VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; + uint32_t size =3D msg->size; + void *data =3D msg->data; + QemuClipboardInfo *info; + QemuClipboardType type; + + if (have_selection(vd)) { + if (size < 4) { + return; + } + s =3D *(uint8_t *)data; + if (s >=3D QEMU_CLIPBOARD_SELECTION__COUNT) { + return; + } + data +=3D 4; + size -=3D 4; + } + + switch (msg->type) { + case VD_AGENT_CLIPBOARD_GRAB: + trace_vdagent_cb_grab_selection(GET_NAME(sel_name, s)); + info =3D qemu_clipboard_info_new(&vd->cbpeer, s); + if (size > sizeof(uint32_t) * 10) { + /* + * spice has 6 types as of 2021. Limiting to 10 entries + * so we we have some wiggle room. + */ + return; + } + while (size >=3D sizeof(uint32_t)) { + trace_vdagent_cb_grab_type(GET_NAME(type_name, *(uint32_t *)da= ta)); + switch (*(uint32_t *)data) { + case VD_AGENT_CLIPBOARD_UTF8_TEXT: + info->types[QEMU_CLIPBOARD_TYPE_TEXT].available =3D true; + break; + default: + break; + } + data +=3D sizeof(uint32_t); + size -=3D sizeof(uint32_t); + } + qemu_clipboard_update(info); + qemu_clipboard_info_unref(info); + break; + case VD_AGENT_CLIPBOARD_REQUEST: + if (size < sizeof(uint32_t)) { + return; + } + switch (*(uint32_t *)data) { + case VD_AGENT_CLIPBOARD_UTF8_TEXT: + type =3D QEMU_CLIPBOARD_TYPE_TEXT; + break; + default: + return; + } + if (vd->cbinfo[s] && + vd->cbinfo[s]->types[type].available && + vd->cbinfo[s]->owner !=3D &vd->cbpeer) { + if (vd->cbinfo[s]->types[type].data) { + vdagent_send_clipboard_data(vd, vd->cbinfo[s], type); + } else { + vd->cbpending[s] |=3D (1 << type); + qemu_clipboard_request(vd->cbinfo[s], type); + } + } + break; + case VD_AGENT_CLIPBOARD: /* data */ + if (size < sizeof(uint32_t)) { + return; + } + switch (*(uint32_t *)data) { + case VD_AGENT_CLIPBOARD_UTF8_TEXT: + type =3D QEMU_CLIPBOARD_TYPE_TEXT; + break; + default: + return; + } + data +=3D 4; + size -=3D 4; + qemu_clipboard_set_data(&vd->cbpeer, vd->cbinfo[s], type, + size, data, true); + break; + case VD_AGENT_CLIPBOARD_RELEASE: /* data */ + if (vd->cbinfo[s] && + vd->cbinfo[s]->owner =3D=3D &vd->cbpeer) { + /* set empty clipboard info */ + info =3D qemu_clipboard_info_new(NULL, s); + qemu_clipboard_update(info); + qemu_clipboard_info_unref(info); + } + break; + } +} + /* ------------------------------------------------------------------ */ /* chardev backend */ =20 @@ -286,6 +554,11 @@ static void vdagent_chr_open(Chardev *chr, vd->mouse =3D cfg->mouse; } =20 + vd->clipboard =3D VDAGENT_CLIPBOARD_DEFAULT; + if (cfg->has_clipboard) { + vd->clipboard =3D cfg->clipboard; + } + if (vd->mouse) { vd->mouse_hs =3D qemu_input_handler_register(&vd->mouse_dev, &vdagent_mouse_handler); @@ -317,6 +590,12 @@ static void vdagent_chr_recv_caps(VDAgentChardev *vd, = VDAgentMessage *msg) if (have_mouse(vd) && vd->mouse_hs) { qemu_input_handler_activate(vd->mouse_hs); } + if (have_clipboard(vd) && vd->cbpeer.update.notify =3D=3D NULL) { + vd->cbpeer.name =3D "vdagent"; + vd->cbpeer.update.notify =3D vdagent_clipboard_notify; + vd->cbpeer.request =3D vdagent_clipboard_request; + qemu_clipboard_peer_register(&vd->cbpeer); + } } =20 static void vdagent_chr_recv_msg(VDAgentChardev *vd, VDAgentMessage *msg) @@ -327,6 +606,14 @@ static void vdagent_chr_recv_msg(VDAgentChardev *vd, V= DAgentMessage *msg) case VD_AGENT_ANNOUNCE_CAPABILITIES: vdagent_chr_recv_caps(vd, msg); break; + case VD_AGENT_CLIPBOARD: + case VD_AGENT_CLIPBOARD_GRAB: + case VD_AGENT_CLIPBOARD_REQUEST: + case VD_AGENT_CLIPBOARD_RELEASE: + if (have_clipboard(vd)) { + vdagent_chr_recv_clipboard(vd, msg); + } + break; default: break; } @@ -448,6 +735,10 @@ static void vdagent_chr_set_fe_open(struct Chardev *ch= r, int fe_open) if (vd->mouse_hs) { qemu_input_handler_deactivate(vd->mouse_hs); } + if (vd->cbpeer.update.notify) { + qemu_clipboard_peer_unregister(&vd->cbpeer); + memset(&vd->cbpeer, 0, sizeof(vd->cbpeer)); + } return; } =20 @@ -464,6 +755,8 @@ static void vdagent_chr_parse(QemuOpts *opts, ChardevBa= ckend *backend, qemu_chr_parse_common(opts, qapi_ChardevQemuVDAgent_base(cfg)); cfg->has_mouse =3D true; cfg->mouse =3D qemu_opt_get_bool(opts, "mouse", VDAGENT_MOUSE_DEFAULT); + cfg->has_clipboard =3D true; + cfg->clipboard =3D qemu_opt_get_bool(opts, "clipboard", VDAGENT_CLIPBO= ARD_DEFAULT); } =20 /* ------------------------------------------------------------------ */ diff --git a/qapi/char.json b/qapi/char.json index 5711e8c60aeb..adf2685f6889 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -396,12 +396,14 @@ # Configuration info for qemu vdagent implementation. # # @mouse: enable/disable mouse, default is enabled. +# @clipboard: enable/disable clipboard, default is disabled. # # Since: 6.1 # ## { 'struct': 'ChardevQemuVDAgent', - 'data': { '*mouse': 'bool' }, + 'data': { '*mouse': 'bool', + '*clipboard': 'bool' }, 'base': 'ChardevCommon', 'if': 'defined(CONFIG_SPICE_PROTOCOL)' } =20 diff --git a/ui/trace-events b/ui/trace-events index c34cffb0452b..c86542e2b69b 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -132,3 +132,5 @@ vdagent_send(const char *name) "msg %s" vdagent_recv_chunk(uint32_t size) "size %d" vdagent_recv_msg(const char *name, uint32_t size) "msg %s, size %d" vdagent_peer_cap(const char *name) "cap %s" +vdagent_cb_grab_selection(const char *name) "selection %s" +vdagent_cb_grab_type(const char *name) "type %s" --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621602342; cv=none; d=zohomail.com; s=zohoarc; b=SteHCiVQaw6Vb3amy7hi2nKHSiCn355d07fTLmgml+XHYKaGJi2p1BpVSHItHfTRMJdD+czrwaSpAEDA3YQBZyDJx2hpgi2ymY+/BEVO1HEkWV29Nb7bFZHYNBkg/nUhcrCyyRY+ucja0AtXliBKdxy+r2ws35s0GB8yjWfMVPY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621602342; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=B2xOnfY/NCdu1BW4/bkn49Oqjw43+kRD8fua/2mDCM8=; b=CI1NWM9+D7OzfTDk3vpCfnh91S9v7g3lQNHNluTvBgY8kq46laXMtfcgIStr59ETPoJb1YDHHFN1kbnSD5pu6ZdF/V71tsgONQ8LyreVZa0nlNaOk7jQ/uytoEfCEfwOwjYFT0RyrDOV9rzUiEVTBkQfKfk0olppzjKejVMw5Rg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621602342064106.38269008026532; Fri, 21 May 2021 06:05:42 -0700 (PDT) Received: from localhost ([::1]:41736 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4qT-0002Za-1a for importer@patchew.org; Fri, 21 May 2021 09:05:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52928) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4fF-0007xx-Lo for qemu-devel@nongnu.org; Fri, 21 May 2021 08:54:05 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:54066) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4fC-00080a-OP for qemu-devel@nongnu.org; Fri, 21 May 2021 08:54:05 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-488-e0ZcAeOWN9-JKc1yl_ntkA-1; Fri, 21 May 2021 08:54:00 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A08E880B731 for ; Fri, 21 May 2021 12:53:59 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 32ECA1009962; Fri, 21 May 2021 12:53:48 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id C70CB1800900; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601642; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=B2xOnfY/NCdu1BW4/bkn49Oqjw43+kRD8fua/2mDCM8=; b=MU18WT8WxK5K4T3XEr7FmXLm3/EUScrKaFUEw7a/feBzhlF0BBAq6h3i9Ml4XD88SPWgbu zDKVFb0SQ7/ddvE9nvXByYtXxblfe8f6YIJIPfKqYwR/Jbw3d/OCAWHjVUi92jwc1thxSv HjTJb8x7pmDoXwRS9CBVl42+VZC8xI8= X-MC-Unique: e0ZcAeOWN9-JKc1yl_ntkA-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 09/11] ui/vnc: clipboard support Date: Fri, 21 May 2021 14:51:17 +0200 Message-Id: <20210521125119.3173309-10-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) This patch adds support for cut+paste to the qemu vnc server, which allows the vnc client exchange clipbaord data with qemu and other peers like the qemu vdagent implementation. Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-Andr=C3=A9 Lureau Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-8-kraxel@redhat.com> --- ui/vnc.h | 24 ++++ ui/vnc-clipboard.c | 323 +++++++++++++++++++++++++++++++++++++++++++++ ui/vnc.c | 21 ++- ui/meson.build | 1 + 4 files changed, 363 insertions(+), 6 deletions(-) create mode 100644 ui/vnc-clipboard.c diff --git a/ui/vnc.h b/ui/vnc.h index d4f3e1555809..a7149831f906 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -29,6 +29,7 @@ =20 #include "qemu/queue.h" #include "qemu/thread.h" +#include "ui/clipboard.h" #include "ui/console.h" #include "audio/audio.h" #include "qemu/bitmap.h" @@ -348,6 +349,10 @@ struct VncState =20 Notifier mouse_mode_notifier; =20 + QemuClipboardPeer cbpeer; + QemuClipboardInfo *cbinfo; + uint32_t cbpending; + QTAILQ_ENTRY(VncState) next; }; =20 @@ -417,6 +422,7 @@ enum { #define VNC_ENCODING_XVP 0XFFFFFECB /* -309 */ #define VNC_ENCODING_ALPHA_CURSOR 0XFFFFFEC6 /* -314 */ #define VNC_ENCODING_WMVi 0x574D5669 +#define VNC_ENCODING_CLIPBOARD_EXT 0xc0a1e5ce =20 /*************************************************************************= **** * @@ -458,6 +464,7 @@ enum VncFeatures { VNC_FEATURE_ZYWRLE, VNC_FEATURE_LED_STATE, VNC_FEATURE_XVP, + VNC_FEATURE_CLIPBOARD_EXT, }; =20 #define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE) @@ -474,6 +481,7 @@ enum VncFeatures { #define VNC_FEATURE_ZYWRLE_MASK (1 << VNC_FEATURE_ZYWRLE) #define VNC_FEATURE_LED_STATE_MASK (1 << VNC_FEATURE_LED_STATE) #define VNC_FEATURE_XVP_MASK (1 << VNC_FEATURE_XVP) +#define VNC_FEATURE_CLIPBOARD_EXT_MASK (1 << VNC_FEATURE_CLIPBOARD_= EXT) =20 =20 /* Client -> Server message IDs */ @@ -535,6 +543,17 @@ enum VncFeatures { #define VNC_XVP_ACTION_REBOOT 3 #define VNC_XVP_ACTION_RESET 4 =20 +/* extended clipboard flags */ +#define VNC_CLIPBOARD_TEXT (1 << 0) +#define VNC_CLIPBOARD_RTF (1 << 1) +#define VNC_CLIPBOARD_HTML (1 << 2) +#define VNC_CLIPBOARD_DIB (1 << 3) +#define VNC_CLIPBOARD_FILES (1 << 4) +#define VNC_CLIPBOARD_CAPS (1 << 24) +#define VNC_CLIPBOARD_REQUEST (1 << 25) +#define VNC_CLIPBOARD_PEEK (1 << 26) +#define VNC_CLIPBOARD_NOTIFY (1 << 27) +#define VNC_CLIPBOARD_PROVIDE (1 << 28) =20 /*************************************************************************= **** * @@ -618,4 +637,9 @@ int vnc_zrle_send_framebuffer_update(VncState *vs, int = x, int y, int w, int h); int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, = int h); void vnc_zrle_clear(VncState *vs); =20 +/* vnc-clipboard.c */ +void vnc_server_cut_text_caps(VncState *vs); +void vnc_client_cut_text(VncState *vs, size_t len, uint8_t *text); +void vnc_client_cut_text_ext(VncState *vs, int32_t len, uint32_t flags, ui= nt8_t *data); + #endif /* QEMU_VNC_H */ diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c new file mode 100644 index 000000000000..9f077965d056 --- /dev/null +++ b/ui/vnc-clipboard.c @@ -0,0 +1,323 @@ +/* + * QEMU VNC display driver -- clipboard support + * + * Copyright (C) 2021 Gerd Hoffmann + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "vnc.h" +#include "vnc-jobs.h" + +static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *siz= e) +{ + z_stream stream =3D { + .next_in =3D in, + .avail_in =3D in_len, + .zalloc =3D Z_NULL, + .zfree =3D Z_NULL, + }; + uint32_t out_len =3D 8; + uint8_t *out =3D g_malloc(out_len); + int ret; + + stream.next_out =3D out + stream.total_out; + stream.avail_out =3D out_len - stream.total_out; + + ret =3D inflateInit(&stream); + if (ret !=3D Z_OK) { + goto err; + } + + while (stream.avail_in) { + ret =3D inflate(&stream, Z_FINISH); + switch (ret) { + case Z_OK: + case Z_STREAM_END: + break; + case Z_BUF_ERROR: + out_len <<=3D 1; + if (out_len > (1 << 20)) { + goto err_end; + } + out =3D g_realloc(out, out_len); + stream.next_out =3D out + stream.total_out; + stream.avail_out =3D out_len - stream.total_out; + break; + default: + goto err_end; + } + } + + *size =3D stream.total_out; + inflateEnd(&stream); + + return out; + +err_end: + inflateEnd(&stream); +err: + g_free(out); + return NULL; +} + +static uint8_t *deflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *siz= e) +{ + z_stream stream =3D { + .next_in =3D in, + .avail_in =3D in_len, + .zalloc =3D Z_NULL, + .zfree =3D Z_NULL, + }; + uint32_t out_len =3D 8; + uint8_t *out =3D g_malloc(out_len); + int ret; + + stream.next_out =3D out + stream.total_out; + stream.avail_out =3D out_len - stream.total_out; + + ret =3D deflateInit(&stream, Z_DEFAULT_COMPRESSION); + if (ret !=3D Z_OK) { + goto err; + } + + while (ret !=3D Z_STREAM_END) { + ret =3D deflate(&stream, Z_FINISH); + switch (ret) { + case Z_OK: + case Z_STREAM_END: + break; + case Z_BUF_ERROR: + out_len <<=3D 1; + if (out_len > (1 << 20)) { + goto err_end; + } + out =3D g_realloc(out, out_len); + stream.next_out =3D out + stream.total_out; + stream.avail_out =3D out_len - stream.total_out; + break; + default: + goto err_end; + } + } + + *size =3D stream.total_out; + deflateEnd(&stream); + + return out; + +err_end: + deflateEnd(&stream); +err: + g_free(out); + return NULL; +} + +static void vnc_clipboard_send(VncState *vs, uint32_t count, uint32_t *dwo= rds) +{ + int i; + + vnc_lock_output(vs); + vnc_write_u8(vs, VNC_MSG_SERVER_CUT_TEXT); + vnc_write_u8(vs, 0); + vnc_write_u8(vs, 0); + vnc_write_u8(vs, 0); + vnc_write_s32(vs, -(count * sizeof(uint32_t))); /* -(message length) = */ + for (i =3D 0; i < count; i++) { + vnc_write_u32(vs, dwords[i]); + } + vnc_unlock_output(vs); + vnc_flush(vs); +} + +static void vnc_clipboard_provide(VncState *vs, + QemuClipboardInfo *info, + QemuClipboardType type) +{ + uint32_t flags =3D 0; + g_autofree uint8_t *buf =3D NULL; + g_autofree void *zbuf =3D NULL; + uint32_t zsize; + + switch (type) { + case QEMU_CLIPBOARD_TYPE_TEXT: + flags |=3D VNC_CLIPBOARD_TEXT; + break; + default: + return; + } + flags |=3D VNC_CLIPBOARD_PROVIDE; + + buf =3D g_malloc(info->types[type].size + 4); + buf[0] =3D (info->types[type].size >> 24) & 0xff; + buf[1] =3D (info->types[type].size >> 16) & 0xff; + buf[2] =3D (info->types[type].size >> 8) & 0xff; + buf[3] =3D (info->types[type].size >> 0) & 0xff; + memcpy(buf + 4, info->types[type].data, info->types[type].size); + zbuf =3D deflate_buffer(buf, info->types[type].size + 4, &zsize); + if (!zbuf) { + return; + } + + vnc_lock_output(vs); + vnc_write_u8(vs, VNC_MSG_SERVER_CUT_TEXT); + vnc_write_u8(vs, 0); + vnc_write_u8(vs, 0); + vnc_write_u8(vs, 0); + vnc_write_s32(vs, -(sizeof(uint32_t) + zsize)); /* -(message length) = */ + vnc_write_u32(vs, flags); + vnc_write(vs, zbuf, zsize); + vnc_unlock_output(vs); + vnc_flush(vs); +} + +static void vnc_clipboard_notify(Notifier *notifier, void *data) +{ + VncState *vs =3D container_of(notifier, VncState, cbpeer.update); + QemuClipboardInfo *info =3D data; + QemuClipboardType type; + bool self_update =3D info->owner =3D=3D &vs->cbpeer; + uint32_t flags =3D 0; + + if (info !=3D vs->cbinfo) { + qemu_clipboard_info_unref(vs->cbinfo); + vs->cbinfo =3D qemu_clipboard_info_ref(info); + vs->cbpending =3D 0; + if (!self_update) { + if (info->types[QEMU_CLIPBOARD_TYPE_TEXT].available) { + flags |=3D VNC_CLIPBOARD_TEXT; + } + flags |=3D VNC_CLIPBOARD_NOTIFY; + vnc_clipboard_send(vs, 1, &flags); + } + return; + } + + if (self_update) { + return; + } + + for (type =3D 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { + if (vs->cbpending & (1 << type)) { + vs->cbpending &=3D ~(1 << type); + vnc_clipboard_provide(vs, info, type); + } + } +} + +static void vnc_clipboard_request(QemuClipboardInfo *info, + QemuClipboardType type) +{ + VncState *vs =3D container_of(info->owner, VncState, cbpeer); + uint32_t flags =3D 0; + + if (type =3D=3D QEMU_CLIPBOARD_TYPE_TEXT) { + flags |=3D VNC_CLIPBOARD_TEXT; + } + if (!flags) { + return; + } + flags |=3D VNC_CLIPBOARD_REQUEST; + + vnc_clipboard_send(vs, 1, &flags); +} + +void vnc_client_cut_text_ext(VncState *vs, int32_t len, uint32_t flags, ui= nt8_t *data) +{ + if (flags & VNC_CLIPBOARD_CAPS) { + /* need store caps somewhere ? */ + return; + } + + if (flags & VNC_CLIPBOARD_NOTIFY) { + QemuClipboardInfo *info =3D + qemu_clipboard_info_new(&vs->cbpeer, QEMU_CLIPBOARD_SELECTION_= CLIPBOARD); + if (flags & VNC_CLIPBOARD_TEXT) { + info->types[QEMU_CLIPBOARD_TYPE_TEXT].available =3D true; + } + qemu_clipboard_update(info); + qemu_clipboard_info_unref(info); + return; + } + + if (flags & VNC_CLIPBOARD_PROVIDE && + vs->cbinfo && + vs->cbinfo->owner =3D=3D &vs->cbpeer) { + uint32_t size =3D 0; + g_autofree uint8_t *buf =3D inflate_buffer(data, len - 4, &size); + if ((flags & VNC_CLIPBOARD_TEXT) && + buf && size >=3D 4) { + uint32_t tsize =3D read_u32(buf, 0); + uint8_t *tbuf =3D buf + 4; + if (tsize < size) { + qemu_clipboard_set_data(&vs->cbpeer, vs->cbinfo, + QEMU_CLIPBOARD_TYPE_TEXT, + tsize, tbuf, true); + } + } + } + + if (flags & VNC_CLIPBOARD_REQUEST && + vs->cbinfo && + vs->cbinfo->owner !=3D &vs->cbpeer) { + if ((flags & VNC_CLIPBOARD_TEXT) && + vs->cbinfo->types[QEMU_CLIPBOARD_TYPE_TEXT].available) { + if (vs->cbinfo->types[QEMU_CLIPBOARD_TYPE_TEXT].data) { + vnc_clipboard_provide(vs, vs->cbinfo, QEMU_CLIPBOARD_TYPE_= TEXT); + } else { + vs->cbpending |=3D (1 << QEMU_CLIPBOARD_TYPE_TEXT); + qemu_clipboard_request(vs->cbinfo, QEMU_CLIPBOARD_TYPE_TEX= T); + } + } + } +} + +void vnc_client_cut_text(VncState *vs, size_t len, uint8_t *text) +{ + QemuClipboardInfo *info =3D + qemu_clipboard_info_new(&vs->cbpeer, QEMU_CLIPBOARD_SELECTION_CLIP= BOARD); + + qemu_clipboard_set_data(&vs->cbpeer, info, QEMU_CLIPBOARD_TYPE_TEXT, + len, text, true); + qemu_clipboard_info_unref(info); +} + +void vnc_server_cut_text_caps(VncState *vs) +{ + uint32_t caps[2]; + + if (!vnc_has_feature(vs, VNC_FEATURE_CLIPBOARD_EXT)) { + return; + } + + caps[0] =3D (VNC_CLIPBOARD_PROVIDE | + VNC_CLIPBOARD_NOTIFY | + VNC_CLIPBOARD_REQUEST | + VNC_CLIPBOARD_CAPS | + VNC_CLIPBOARD_TEXT); + caps[1] =3D 0; + vnc_clipboard_send(vs, 2, caps); + + vs->cbpeer.name =3D "vnc"; + vs->cbpeer.update.notify =3D vnc_clipboard_notify; + vs->cbpeer.request =3D vnc_clipboard_request; + qemu_clipboard_peer_register(&vs->cbpeer); +} diff --git a/ui/vnc.c b/ui/vnc.c index 2bea46b2b3f8..b3d4d7b9a5f5 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -25,6 +25,7 @@ */ =20 #include "qemu/osdep.h" +#include "qemu-common.h" #include "vnc.h" #include "vnc-jobs.h" #include "trace.h" @@ -1352,6 +1353,9 @@ void vnc_disconnect_finish(VncState *vs) /* last client gone */ vnc_update_server_surface(vs->vd); } + if (vs->cbpeer.update.notify) { + qemu_clipboard_peer_unregister(&vs->cbpeer); + } =20 vnc_unlock_output(vs); =20 @@ -1777,10 +1781,6 @@ uint32_t read_u32(uint8_t *data, size_t offset) (data[offset + 2] << 8) | data[offset + 3]); } =20 -static void client_cut_text(VncState *vs, size_t len, uint8_t *text) -{ -} - static void check_pointer_type_change(Notifier *notifier, void *data) { VncState *vs =3D container_of(notifier, VncState, mouse_mode_notifier); @@ -2222,6 +2222,10 @@ static void set_encodings(VncState *vs, int32_t *enc= odings, size_t n_encodings) send_xvp_message(vs, VNC_XVP_CODE_INIT); } break; + case VNC_ENCODING_CLIPBOARD_EXT: + vs->features |=3D VNC_FEATURE_CLIPBOARD_EXT_MASK; + vnc_server_cut_text_caps(vs); + break; case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 += 9: vs->tight->compression =3D (enc & 0x0F); break; @@ -2438,7 +2442,7 @@ static int protocol_client_msg(VncState *vs, uint8_t = *data, size_t len) return 8; } if (len =3D=3D 8) { - uint32_t dlen =3D read_u32(data, 4); + uint32_t dlen =3D abs(read_s32(data, 4)); if (dlen > (1 << 20)) { error_report("vnc: client_cut_text msg payload has %u byte= s" " which exceeds our limit of 1MB.", dlen); @@ -2450,7 +2454,12 @@ static int protocol_client_msg(VncState *vs, uint8_t= *data, size_t len) } } =20 - client_cut_text(vs, read_u32(data, 4), data + 8); + if (read_s32(data, 4) < 0) { + vnc_client_cut_text_ext(vs, abs(read_s32(data, 4)), + read_u32(data, 8), data + 12); + break; + } + vnc_client_cut_text(vs, read_u32(data, 4), data + 8); break; case VNC_MSG_CLIENT_XVP: if (!(vs->features & VNC_FEATURE_XVP)) { diff --git a/ui/meson.build b/ui/meson.build index bad49fb6de60..f37ef882e0e3 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -30,6 +30,7 @@ vnc_ss.add(files( 'vnc-auth-vencrypt.c', 'vnc-ws.c', 'vnc-jobs.c', + 'vnc-clipboard.c', )) vnc_ss.add(zlib, png, jpeg, gnutls) vnc_ss.add(when: sasl, if_true: files('vnc-auth-sasl.c')) --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621601999; cv=none; d=zohomail.com; s=zohoarc; b=d2+lEOB7Hr62P6YaBTUInVctTVMz81aBVOGIAzlu3ncbafv5Rj/NC5IN+GIa6wh3JTTkwI0yd3oPj/5dAJzt+qvFW4wU0sdqsJ9keyO+rq3CZeYR/C++xrLiD3pjjk9pDuu9aExdg245or+ID77nys7uE3RaYL7dwu9gqg4MMCg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621601999; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=YXQOl/oMe/wAK0KJZsJf1micrlz8Bals/VcqC1ADUU4=; b=iBS9aHDknlRARqD2UCVv5H9Fu0D8o2t4PlJyKfMbN81gBmJ7OSxrQ6T9h/jW+fU2Tn90x6BQY+7rL4qE3xIbpoypNmSSo70zT6cjMz6L3n+yLn0QvHQ824JmgZdogTovLNBRUArbCAGmnlQSnacLPldNlw/ffD5C2SG5aj2S8YE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621601999218436.33058732098425; Fri, 21 May 2021 05:59:59 -0700 (PDT) Received: from localhost ([::1]:57422 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4kw-0002Ns-2A for importer@patchew.org; Fri, 21 May 2021 08:59:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52856) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4f7-0007Uo-QM for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:57 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:25824) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4f1-0007zU-Ji for qemu-devel@nongnu.org; Fri, 21 May 2021 08:53:57 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-214-6kIEVviYMV2NYWbspgLWxQ-1; Fri, 21 May 2021 08:53:49 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6F8EE1009464 for ; Fri, 21 May 2021 12:53:48 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 3397A62467; Fri, 21 May 2021 12:53:48 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id D441F1800902; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601630; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YXQOl/oMe/wAK0KJZsJf1micrlz8Bals/VcqC1ADUU4=; b=Ag5SSPRRXxBP0AV29eUxLqsXA6rpbp4pE4KKwe/T/0MkZhz3dwrGMgjClo+r+MrCsLfXUH SFRZNst7EALsojEESXN6uaY0oNW+iwfvVRqYUYQ6KKtV5HLKDFDJ/QzsKJUy2mK6+VjNPH liIW3jXH5hk2vCae4D9DaCdiVyYXKVc= X-MC-Unique: 6kIEVviYMV2NYWbspgLWxQ-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 10/11] ui/gtk: move struct GtkDisplayState to ui/gtk.h Date: Fri, 21 May 2021 14:51:18 +0200 Message-Id: <20210521125119.3173309-11-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Want place gtk clipboard code in a separate C file, which in turn requires GtkDisplayState being in a header file. So move it. No functional change. Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-Andr=C3=A9 Lureau Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-9-kraxel@redhat.com> --- include/ui/gtk.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ ui/gtk.c | 55 ---------------------------------------------- 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 5ae0ad60a600..6e751794043f 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -18,12 +18,15 @@ #include #endif =20 +#include "ui/console.h" #include "ui/kbd-state.h" #if defined(CONFIG_OPENGL) #include "ui/egl-helpers.h" #include "ui/egl-context.h" #endif =20 +#define MAX_VCS 10 + typedef struct GtkDisplayState GtkDisplayState; =20 typedef struct VirtualGfxConsole { @@ -83,6 +86,60 @@ typedef struct VirtualConsole { }; } VirtualConsole; =20 +struct GtkDisplayState { + GtkWidget *window; + + GtkWidget *menu_bar; + + GtkAccelGroup *accel_group; + + GtkWidget *machine_menu_item; + GtkWidget *machine_menu; + GtkWidget *pause_item; + GtkWidget *reset_item; + GtkWidget *powerdown_item; + GtkWidget *quit_item; + + GtkWidget *view_menu_item; + GtkWidget *view_menu; + GtkWidget *full_screen_item; + GtkWidget *copy_item; + GtkWidget *zoom_in_item; + GtkWidget *zoom_out_item; + GtkWidget *zoom_fixed_item; + GtkWidget *zoom_fit_item; + GtkWidget *grab_item; + GtkWidget *grab_on_hover_item; + + int nb_vcs; + VirtualConsole vc[MAX_VCS]; + + GtkWidget *show_tabs_item; + GtkWidget *untabify_item; + GtkWidget *show_menubar_item; + + GtkWidget *vbox; + GtkWidget *notebook; + int button_mask; + gboolean last_set; + int last_x; + int last_y; + int grab_x_root; + int grab_y_root; + VirtualConsole *kbd_owner; + VirtualConsole *ptr_owner; + + gboolean full_screen; + + GdkCursor *null_cursor; + Notifier mouse_mode_notifier; + gboolean free_scale; + + bool external_pause_update; + + DisplayOptions *opts; +}; + extern bool gtk_use_gl_area; =20 /* ui/gtk.c */ diff --git a/ui/gtk.c b/ui/gtk.c index 1ea12535284a..7da288a25156 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -60,7 +60,6 @@ #include "chardev/char.h" #include "qom/object.h" =20 -#define MAX_VCS 10 #define VC_WINDOW_X_MIN 320 #define VC_WINDOW_Y_MIN 240 #define VC_TERM_X_MIN 80 @@ -119,60 +118,6 @@ static const guint16 *keycode_map; static size_t keycode_maplen; =20 -struct GtkDisplayState { - GtkWidget *window; - - GtkWidget *menu_bar; - - GtkAccelGroup *accel_group; - - GtkWidget *machine_menu_item; - GtkWidget *machine_menu; - GtkWidget *pause_item; - GtkWidget *reset_item; - GtkWidget *powerdown_item; - GtkWidget *quit_item; - - GtkWidget *view_menu_item; - GtkWidget *view_menu; - GtkWidget *full_screen_item; - GtkWidget *copy_item; - GtkWidget *zoom_in_item; - GtkWidget *zoom_out_item; - GtkWidget *zoom_fixed_item; - GtkWidget *zoom_fit_item; - GtkWidget *grab_item; - GtkWidget *grab_on_hover_item; - - int nb_vcs; - VirtualConsole vc[MAX_VCS]; - - GtkWidget *show_tabs_item; - GtkWidget *untabify_item; - GtkWidget *show_menubar_item; - - GtkWidget *vbox; - GtkWidget *notebook; - int button_mask; - gboolean last_set; - int last_x; - int last_y; - int grab_x_root; - int grab_y_root; - VirtualConsole *kbd_owner; - VirtualConsole *ptr_owner; - - gboolean full_screen; - - GdkCursor *null_cursor; - Notifier mouse_mode_notifier; - gboolean free_scale; - - bool external_pause_update; - - DisplayOptions *opts; -}; - struct VCChardev { Chardev parent; VirtualConsole *console; --=20 2.31.1 From nobody Fri Apr 19 17:53:57 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1621602201; cv=none; d=zohomail.com; s=zohoarc; b=UzCIadtQGnmsba6oVcDrDSRbNe7krWoul0YhmdCMXA9vIXLuFu/pYxsCY6Sm5000nbAWzyhqnZc/EaRbP8FKJw70mIAkTcgYaQas1e7cvJ/TTCG+qPF6RHmKcBSivWJ/PLZh2m+0WxbnzcRVWIj683Zhjuq63IHjz2s4neWLzl0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621602201; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=6Y4ytJuH80Or3DbAQbf2oSzUq7hUCXYqfH5uGxcQFrU=; b=IZTolyBelOu8fKCo5RT6jMwWOBSYdqQTkj8YyXBMAa9Stlx9VeeIgPaPTx5+U+nAS9CoFl9p07lA8ndet2SiRpYmIMZOfzuxsRP290KNyf0VWs0hEtQRY0Fuj6oWVS1+0qYMNc6hQWtsgSV318jALOLmLCZnKTXEVrFVuIwQpjM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1621602201151733.6935878963169; Fri, 21 May 2021 06:03:21 -0700 (PDT) Received: from localhost ([::1]:35688 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lk4oC-0006v6-2O for importer@patchew.org; Fri, 21 May 2021 09:03:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52896) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4fC-0007ko-K4 for qemu-devel@nongnu.org; Fri, 21 May 2021 08:54:02 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:38173) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lk4fA-00080N-Dp for qemu-devel@nongnu.org; Fri, 21 May 2021 08:54:02 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-26-CW8AuaNePtWYpB-2LYJZ7Q-1; Fri, 21 May 2021 08:53:58 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 465388A9F45 for ; Fri, 21 May 2021 12:53:57 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-84.ams2.redhat.com [10.36.112.84]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 06B9860D4B; Fri, 21 May 2021 12:53:50 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id E5EFC1800903; Fri, 21 May 2021 14:51:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1621601639; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6Y4ytJuH80Or3DbAQbf2oSzUq7hUCXYqfH5uGxcQFrU=; b=BpzyK6feBeKwkz2ZXYXvelaOIuTU4OwRCOtVQQXzdTmTEEaFQ/uJ+PVLTxhZf4aeKW0Lhc XFkL1PirviE45+5z5D6OkaQyQQr1Wozr3K91/are0GFYHdXHt7PRt8Ym6x2fVzTcBKsPK6 ArcP3medb3f3Fa//LZdg16ZfgHYZUYA= X-MC-Unique: CW8AuaNePtWYpB-2LYJZ7Q-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 11/11] ui/gtk: add clipboard support Date: Fri, 21 May 2021 14:51:19 +0200 Message-Id: <20210521125119.3173309-12-kraxel@redhat.com> In-Reply-To: <20210521125119.3173309-1-kraxel@redhat.com> References: <20210521125119.3173309-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -31 X-Spam_score: -3.2 X-Spam_bar: --- X-Spam_report: (-3.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.374, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Markus Armbruster , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) This patch adds clipboard support to the qemu gtk ui. Signed-off-by: Gerd Hoffmann Reviewed-by: Marc-Andr=C3=A9 Lureau Message-id: 20210519053940.1888907-1-kraxel@redhat.com Message-Id: <20210519053940.1888907-10-kraxel@redhat.com> --- include/ui/gtk.h | 10 +++ ui/gtk-clipboard.c | 192 +++++++++++++++++++++++++++++++++++++++++++++ ui/gtk.c | 1 + ui/meson.build | 2 +- 4 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 ui/gtk-clipboard.c diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 6e751794043f..9516670ebc87 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -18,6 +18,7 @@ #include #endif =20 +#include "ui/clipboard.h" #include "ui/console.h" #include "ui/kbd-state.h" #if defined(CONFIG_OPENGL) @@ -137,6 +138,12 @@ struct GtkDisplayState { =20 bool external_pause_update; =20 + QemuClipboardPeer cbpeer; + QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; + uint32_t cbpending[QEMU_CLIPBOARD_SELECTION__COUNT]; + GtkClipboard *gtkcb[QEMU_CLIPBOARD_SELECTION__COUNT]; + bool cbowner[QEMU_CLIPBOARD_SELECTION__COUNT]; + DisplayOptions *opts; }; =20 @@ -207,4 +214,7 @@ void gtk_gl_area_init(void); int gd_gl_area_make_current(DisplayChangeListener *dcl, QEMUGLContext ctx); =20 +/* gtk-clipboard.c */ +void gd_clipboard_init(GtkDisplayState *gd); + #endif /* UI_GTK_H */ diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c new file mode 100644 index 000000000000..bff28d203014 --- /dev/null +++ b/ui/gtk-clipboard.c @@ -0,0 +1,192 @@ +/* + * GTK UI -- clipboard support + * + * Copyright (C) 2021 Gerd Hoffmann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/main-loop.h" + +#include "ui/gtk.h" + +static QemuClipboardSelection gd_find_selection(GtkDisplayState *gd, + GtkClipboard *clipboard) +{ + QemuClipboardSelection s; + + for (s =3D 0; s < QEMU_CLIPBOARD_SELECTION__COUNT; s++) { + if (gd->gtkcb[s] =3D=3D clipboard) { + return s; + } + } + return QEMU_CLIPBOARD_SELECTION_CLIPBOARD; +} + +static void gd_clipboard_get_data(GtkClipboard *clipboard, + GtkSelectionData *selection_data, + guint selection_info, + gpointer data) +{ + GtkDisplayState *gd =3D data; + QemuClipboardSelection s =3D gd_find_selection(gd, clipboard); + QemuClipboardType type =3D QEMU_CLIPBOARD_TYPE_TEXT; + QemuClipboardInfo *info =3D qemu_clipboard_info_ref(gd->cbinfo[s]); + + qemu_clipboard_request(info, type); + while (info =3D=3D gd->cbinfo[s] && + info->types[type].available && + info->types[type].data =3D=3D NULL) { + main_loop_wait(false); + } + + if (info =3D=3D gd->cbinfo[s] && gd->cbowner[s]) { + gtk_selection_data_set_text(selection_data, + info->types[type].data, + info->types[type].size); + } else { + /* clipboard owner changed while waiting for the data */ + } + + qemu_clipboard_info_unref(info); +} + +static void gd_clipboard_clear(GtkClipboard *clipboard, + gpointer data) +{ + GtkDisplayState *gd =3D data; + QemuClipboardSelection s =3D gd_find_selection(gd, clipboard); + + gd->cbowner[s] =3D false; +} + +static void gd_clipboard_notify(Notifier *notifier, void *data) +{ + GtkDisplayState *gd =3D container_of(notifier, GtkDisplayState, cbpeer= .update); + QemuClipboardInfo *info =3D data; + QemuClipboardSelection s =3D info->selection; + bool self_update =3D info->owner =3D=3D &gd->cbpeer; + + if (info !=3D gd->cbinfo[s]) { + qemu_clipboard_info_unref(gd->cbinfo[s]); + gd->cbinfo[s] =3D qemu_clipboard_info_ref(info); + gd->cbpending[s] =3D 0; + if (!self_update) { + GtkTargetList *list; + GtkTargetEntry *targets; + gint n_targets; + + list =3D gtk_target_list_new(NULL, 0); + if (info->types[QEMU_CLIPBOARD_TYPE_TEXT].available) { + gtk_target_list_add_text_targets(list, 0); + } + targets =3D gtk_target_table_new_from_list(list, &n_targets); + + gtk_clipboard_clear(gd->gtkcb[s]); + gd->cbowner[s] =3D true; + gtk_clipboard_set_with_data(gd->gtkcb[s], + targets, n_targets, + gd_clipboard_get_data, + gd_clipboard_clear, + gd); + + gtk_target_table_free(targets, n_targets); + gtk_target_list_unref(list); + } + return; + } + + if (self_update) { + return; + } + + /* + * Clipboard got updated, with data probably. No action here, we + * are waiting for updates in gd_clipboard_get_data(). + */ +} + +static void gd_clipboard_request(QemuClipboardInfo *info, + QemuClipboardType type) +{ + GtkDisplayState *gd =3D container_of(info->owner, GtkDisplayState, cbp= eer); + char *text; + + switch (type) { + case QEMU_CLIPBOARD_TYPE_TEXT: + text =3D gtk_clipboard_wait_for_text(gd->gtkcb[info->selection]); + if (text) { + qemu_clipboard_set_data(&gd->cbpeer, info, type, + strlen(text), text, true); + g_free(text); + } + break; + default: + break; + } +} + +static void gd_owner_change(GtkClipboard *clipboard, + GdkEvent *event, + gpointer data) +{ + GtkDisplayState *gd =3D data; + QemuClipboardSelection s =3D gd_find_selection(gd, clipboard); + QemuClipboardInfo *info; + + if (gd->cbowner[s]) { + /* ignore notifications about our own grabs */ + return; + } + + + switch (event->owner_change.reason) { + case GDK_SETTING_ACTION_NEW: + info =3D qemu_clipboard_info_new(&gd->cbpeer, s); + if (gtk_clipboard_wait_is_text_available(clipboard)) { + info->types[QEMU_CLIPBOARD_TYPE_TEXT].available =3D true; + } + + qemu_clipboard_update(info); + qemu_clipboard_info_unref(info); + break; + default: + break; + } +} + +void gd_clipboard_init(GtkDisplayState *gd) +{ + gd->cbpeer.name =3D "gtk"; + gd->cbpeer.update.notify =3D gd_clipboard_notify; + gd->cbpeer.request =3D gd_clipboard_request; + qemu_clipboard_peer_register(&gd->cbpeer); + + gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD] =3D + gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", FALSE)); + gd->gtkcb[QEMU_CLIPBOARD_SELECTION_PRIMARY] =3D + gtk_clipboard_get(gdk_atom_intern("PRIMARY", FALSE)); + gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY] =3D + gtk_clipboard_get(gdk_atom_intern("SECONDARY", FALSE)); + + g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD], + "owner-change", G_CALLBACK(gd_owner_change), gd); + g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_PRIMARY], + "owner-change", G_CALLBACK(gd_owner_change), gd); + g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY], + "owner-change", G_CALLBACK(gd_owner_change), gd); +} diff --git a/ui/gtk.c b/ui/gtk.c index 7da288a25156..98046f577b9d 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -2267,6 +2267,7 @@ static void gtk_display_init(DisplayState *ds, Displa= yOptions *opts) opts->u.gtk.grab_on_hover) { gtk_menu_item_activate(GTK_MENU_ITEM(s->grab_on_hover_item)); } + gd_clipboard_init(s); } =20 static void early_gtk_display_init(DisplayOptions *opts) diff --git a/ui/meson.build b/ui/meson.build index f37ef882e0e3..b5aed14886cf 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -65,7 +65,7 @@ if gtk.found() softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('win32-kbd-hook.c')) =20 gtk_ss =3D ss.source_set() - gtk_ss.add(gtk, vte, pixman, files('gtk.c')) + gtk_ss.add(gtk, vte, pixman, files('gtk.c', 'gtk-clipboard.c')) gtk_ss.add(when: x11, if_true: files('x_keymap.c')) gtk_ss.add(when: [opengl, 'CONFIG_OPENGL'], if_true: files('gtk-gl-area.= c')) gtk_ss.add(when: [x11, opengl, 'CONFIG_OPENGL'], if_true: files('gtk-egl= .c')) --=20 2.31.1