From patchwork Sat Sep 17 00:07:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kasireddy, Vivek" X-Patchwork-Id: 12978918 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6C546C54EE9 for ; Sat, 17 Sep 2022 00:28:48 +0000 (UTC) Received: from localhost ([::1]:52370 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oZLhP-00076m-EQ for qemu-devel@archiver.kernel.org; Fri, 16 Sep 2022 20:28:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52436) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oZLgC-0005l6-NM for qemu-devel@nongnu.org; Fri, 16 Sep 2022 20:27:33 -0400 Received: from mga17.intel.com ([192.55.52.151]:23527) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oZLgB-0000iY-4u for qemu-devel@nongnu.org; Fri, 16 Sep 2022 20:27:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1663374451; x=1694910451; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tyQ9swSZYvERopPc45XEuZ3lVkPVWxE8P613hgl7eIA=; b=fhnf/GlNWkTk9nPem6ehWLlrS53S9a4rHeAw7VH9MrJedUzfTVXXTDNU 644H9w/sTTD0qSHb6NoQ3ABW/gwvbSsWYuUptywS0BI6qv1+UJWOMamoA dSo0JCXGAwwfvfL/BTGF6OEO5tkAV6sj3dZesWYPB+ZqWJ+lV7V9r9s74 gTWzmDIt9R5XMka5BoHEtZeGzQsqdLlEBmMRqz9FDFJZPQ/hxF0fMSBUu jbWpF/touPSnqRBBrM8+DoQy8neOLECEpKy+3H0XWvbcGpnd3dG6kQ1Z9 oOeN9TARzvW3wVIHltIZiHSdvWDqij6OFCTi3tuuj1+fSe3JhJoxzLUa+ w==; X-IronPort-AV: E=McAfee;i="6500,9779,10472"; a="279489394" X-IronPort-AV: E=Sophos;i="5.93,321,1654585200"; d="scan'208";a="279489394" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Sep 2022 17:27:20 -0700 X-IronPort-AV: E=Sophos;i="5.93,321,1654585200"; d="scan'208";a="760235121" Received: from vkasired-desk2.fm.intel.com ([10.105.128.127]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Sep 2022 17:27:20 -0700 From: Vivek Kasireddy To: qemu-devel@nongnu.org Cc: Vivek Kasireddy , Gerd Hoffmann , Dongwon Kim Subject: [PATCH v1 1/3] ui/gtk: Disable the scanout when a detached tab is closed Date: Fri, 16 Sep 2022 17:07:29 -0700 Message-Id: <20220917000731.465003-2-vivek.kasireddy@intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220917000731.465003-1-vivek.kasireddy@intel.com> References: <20220917000731.465003-1-vivek.kasireddy@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.151; envelope-from=vivek.kasireddy@intel.com; helo=mga17.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" When a detached tab window is closed, the underlying (EGL) context is destroyed; therefore, disable the scanout which also destroys the underlying framebuffer (id) and other objects. Also add calls to make the context current in disable scanout and other missing places. Cc: Gerd Hoffmann Cc: Dongwon Kim Signed-off-by: Vivek Kasireddy --- ui/gtk-egl.c | 2 ++ ui/gtk-gl-area.c | 2 ++ ui/gtk.c | 1 + 3 files changed, 5 insertions(+) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index b5bffbab25..0f9ef11f4c 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -211,6 +211,8 @@ void gd_egl_scanout_disable(DisplayChangeListener *dcl) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, + vc->gfx.esurface, vc->gfx.ectx); vc->gfx.w = 0; vc->gfx.h = 0; gtk_egl_set_scanout_mode(vc, false); diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 682638a197..0b9fd4713a 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -270,6 +270,7 @@ void gd_gl_area_scanout_disable(DisplayChangeListener *dcl) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); gtk_gl_area_set_scanout_mode(vc, false); } @@ -278,6 +279,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); if (vc->gfx.guest_fb.dmabuf) { graphic_hw_gl_block(vc->gfx.dcl.con, true); vc->gfx.guest_fb.dmabuf->draw_submitted = true; diff --git a/ui/gtk.c b/ui/gtk.c index 1467b8c7d7..0ff31cb852 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1302,6 +1302,7 @@ static gboolean gd_tab_window_close(GtkWidget *widget, GdkEvent *event, VirtualConsole *vc = opaque; GtkDisplayState *s = vc->s; + dpy_gl_scanout_disable(vc->gfx.dcl.con); gtk_widget_set_sensitive(vc->menu_item, true); gd_widget_reparent(vc->window, s->notebook, vc->tab_item); gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(s->notebook), From patchwork Sat Sep 17 00:07:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kasireddy, Vivek" X-Patchwork-Id: 12978919 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 50672ECAAA1 for ; Sat, 17 Sep 2022 00:28:48 +0000 (UTC) Received: from localhost ([::1]:52368 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oZLhP-000765-2i for qemu-devel@archiver.kernel.org; Fri, 16 Sep 2022 20:28:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52434) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oZLgB-0005ky-0T for qemu-devel@nongnu.org; Fri, 16 Sep 2022 20:27:31 -0400 Received: from mga17.intel.com ([192.55.52.151]:23527) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oZLg8-0000iY-Ag for qemu-devel@nongnu.org; Fri, 16 Sep 2022 20:27:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1663374448; x=1694910448; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9JsnKgMaT+NWlAlZc/hCPg1J/P2cW1jC9qrb4G6jxbU=; b=eOVQT4gFx5oODrhyzYgvO4Sh5Lpg6DZbneJjpQgOlU7GfIFJu/gwwLy2 udBb2jdJRulzAC043nYg2zarTR8BlMy3Qp7va8decROXJJtA6D9QWPSdj xOTVd7U/K/rEQAEjkoaJvy77kizFFDLOomP5CYe1NoMD+GkpvKrMkSp8l /2M5AwtED87XDgzmjGa2i8Cr3DnIwfgi2dKQQ0LzIY2kwU6UwaamhyEMD ZD6L8g/7FYiQ36Hko74KBQVg1NsCFPQWtDTeN6/qcosT1iF/4KhXDFf06 cmnPQ5Zc/kJbYFqansVeRSVyLAGJiWH+Og3/Knp+WhZgs75vnn11TF08j g==; X-IronPort-AV: E=McAfee;i="6500,9779,10472"; a="279489395" X-IronPort-AV: E=Sophos;i="5.93,321,1654585200"; d="scan'208";a="279489395" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Sep 2022 17:27:20 -0700 X-IronPort-AV: E=Sophos;i="5.93,321,1654585200"; d="scan'208";a="760235124" Received: from vkasired-desk2.fm.intel.com ([10.105.128.127]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Sep 2022 17:27:20 -0700 From: Vivek Kasireddy To: qemu-devel@nongnu.org Cc: Vivek Kasireddy , Gerd Hoffmann , Dongwon Kim Subject: [PATCH v1 2/3] ui/gtk: Factor out tab window creation into a separate function Date: Fri, 16 Sep 2022 17:07:30 -0700 Message-Id: <20220917000731.465003-3-vivek.kasireddy@intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220917000731.465003-1-vivek.kasireddy@intel.com> References: <20220917000731.465003-1-vivek.kasireddy@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.151; envelope-from=vivek.kasireddy@intel.com; helo=mga17.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Pull the code that creates a new window associated with a notebook tab into a separate function. This new function can be useful not just when user wants to detach a tab but also in the future when a new window creation is needed in other scenarios. Cc: Gerd Hoffmann Cc: Dongwon Kim Signed-off-by: Vivek Kasireddy --- ui/gtk.c | 65 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 0ff31cb852..945c550909 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1335,6 +1335,41 @@ static gboolean gd_win_grab(void *opaque) return TRUE; } +static void gd_tab_window_create(VirtualConsole *vc) +{ + GtkDisplayState *s = vc->s; + + gtk_widget_set_sensitive(vc->menu_item, false); + vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); +#if defined(CONFIG_OPENGL) + if (vc->gfx.esurface) { + eglDestroySurface(qemu_egl_display, vc->gfx.esurface); + vc->gfx.esurface = NULL; + } + if (vc->gfx.esurface) { + eglDestroyContext(qemu_egl_display, vc->gfx.ectx); + vc->gfx.ectx = NULL; + } +#endif + gd_widget_reparent(s->notebook, vc->window, vc->tab_item); + + g_signal_connect(vc->window, "delete-event", + G_CALLBACK(gd_tab_window_close), vc); + gtk_widget_show_all(vc->window); + + if (qemu_console_is_graphic(vc->gfx.dcl.con)) { + GtkAccelGroup *ag = gtk_accel_group_new(); + gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag); + + GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), + vc, NULL); + gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb); + } + + gd_update_geometry_hints(vc); + gd_update_caption(s); +} + static void gd_menu_untabify(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; @@ -1346,35 +1381,7 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) FALSE); } if (!vc->window) { - gtk_widget_set_sensitive(vc->menu_item, false); - vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); -#if defined(CONFIG_OPENGL) - if (vc->gfx.esurface) { - eglDestroySurface(qemu_egl_display, vc->gfx.esurface); - vc->gfx.esurface = NULL; - } - if (vc->gfx.esurface) { - eglDestroyContext(qemu_egl_display, vc->gfx.ectx); - vc->gfx.ectx = NULL; - } -#endif - gd_widget_reparent(s->notebook, vc->window, vc->tab_item); - - g_signal_connect(vc->window, "delete-event", - G_CALLBACK(gd_tab_window_close), vc); - gtk_widget_show_all(vc->window); - - if (qemu_console_is_graphic(vc->gfx.dcl.con)) { - GtkAccelGroup *ag = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag); - - GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), - vc, NULL); - gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb); - } - - gd_update_geometry_hints(vc); - gd_update_caption(s); + gd_tab_window_create(vc); } } From patchwork Sat Sep 17 00:07:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Kasireddy, Vivek" X-Patchwork-Id: 12978921 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9A884ECAAD8 for ; Sat, 17 Sep 2022 00:33:17 +0000 (UTC) Received: from localhost ([::1]:51850 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oZLlk-0002Pw-Mn for qemu-devel@archiver.kernel.org; Fri, 16 Sep 2022 20:33:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58526) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oZLgG-0005qQ-OR for qemu-devel@nongnu.org; Fri, 16 Sep 2022 20:27:37 -0400 Received: from mga17.intel.com ([192.55.52.151]:23527) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oZLgD-0000iY-IL for qemu-devel@nongnu.org; Fri, 16 Sep 2022 20:27:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1663374453; x=1694910453; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OVXOpEVHfZJ/ouyAPRX1Ee0x/0NohO6TmCyWheTQUMo=; b=JHXgGeNFg6IHkIIbtxPiyLqlCp0HKg8SvZO0hdKerasLwtu1Kr7EgIvw XHhkVmtBITT4YKnrZCj7m1iDBqg3rMdCb9E8gIetPk8U95gh+PjEz558v 6xvlTLqU8QNlHgquk/IY6k1+9BgwyjU7SoOeEIt/vj643TniKdwsc5WVa KgvjTICMK/lOsDOT7rBZUNm9hr4uNi7wURvDccGTpDIdi+DITl+bIAts7 ue2WvZj3BIiICLv+1t5o6NBC69aWJpLSOVE5V5SZvGwwgKWH+/aT/0u/R DLD/Ce1W9BIfbF0MuKDLmL6+NPMpMSZR0moC6XxJm7Ei1lBjcv/kquF2J g==; X-IronPort-AV: E=McAfee;i="6500,9779,10472"; a="279489396" X-IronPort-AV: E=Sophos;i="5.93,321,1654585200"; d="scan'208";a="279489396" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Sep 2022 17:27:20 -0700 X-IronPort-AV: E=Sophos;i="5.93,321,1654585200"; d="scan'208";a="760235127" Received: from vkasired-desk2.fm.intel.com ([10.105.128.127]) by fmsmga001-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Sep 2022 17:27:20 -0700 From: Vivek Kasireddy To: qemu-devel@nongnu.org Cc: Vivek Kasireddy , Dongwon Kim , Gerd Hoffmann , =?utf-8?q?Daniel_P_=2E_Berrang=C3=A9?= , Markus Armbruster , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , Thomas Huth Subject: [PATCH v1 3/3] ui/gtk: Add a new parameter to assign connectors/monitors to GFX VCs Date: Fri, 16 Sep 2022 17:07:31 -0700 Message-Id: <20220917000731.465003-4-vivek.kasireddy@intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220917000731.465003-1-vivek.kasireddy@intel.com> References: <20220917000731.465003-1-vivek.kasireddy@intel.com> MIME-Version: 1.0 Received-SPF: pass client-ip=192.55.52.151; envelope-from=vivek.kasireddy@intel.com; helo=mga17.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, 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.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" The new parameter named "connector" can be used to assign physical monitors/connectors to individual GFX VCs such that when the monitor is connected or hotplugged, the associated GTK window would be fullscreened on it. If the monitor is disconnected or unplugged, the associated GTK window would be destroyed and a relevant disconnect event would be sent to the Guest. Usage: -device virtio-gpu-pci,max_outputs=2,blob=true,xres=1920,yres=1080... -display gtk,gl=on,connector.0=eDP-1,connector.1=DP-1..... Cc: Dongwon Kim Cc: Gerd Hoffmann Cc: Daniel P. Berrangé Cc: Markus Armbruster Cc: Philippe Mathieu-Daudé Cc: Marc-André Lureau Cc: Thomas Huth Signed-off-by: Vivek Kasireddy Acked-by: Markus Armbruster --- qapi/ui.json | 9 ++- qemu-options.hx | 1 + ui/gtk.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 1 deletion(-) diff --git a/qapi/ui.json b/qapi/ui.json index 286c5731d1..86787a4c95 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1199,13 +1199,20 @@ # interfaces (e.g. VGA and virtual console character devices) # by default. # Since 7.1 +# @connector: List of physical monitor/connector names where the GTK windows +# containing the respective graphics virtual consoles (VCs) are +# to be placed. If a mapping exists for a VC, it will be +# fullscreened on that specific monitor or else it would not be +# displayed anywhere and would appear disconnected to the guest. +# Since 7.2 # # Since: 2.12 ## { 'struct' : 'DisplayGTK', 'data' : { '*grab-on-hover' : 'bool', '*zoom-to-fit' : 'bool', - '*show-tabs' : 'bool' } } + '*show-tabs' : 'bool', + '*connector' : ['str'] } } ## # @DisplayEGLHeadless: diff --git a/qemu-options.hx b/qemu-options.hx index 31c04f7eea..576b65ef9f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1945,6 +1945,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, #if defined(CONFIG_GTK) "-display gtk[,full-screen=on|off][,gl=on|off][,grab-on-hover=on|off]\n" " [,show-tabs=on|off][,show-cursor=on|off][,window-close=on|off]\n" + " [,connector.=]\n" #endif #if defined(CONFIG_VNC) "-display vnc=[,]\n" diff --git a/ui/gtk.c b/ui/gtk.c index 945c550909..651aaaf174 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -37,6 +37,7 @@ #include "qapi/qapi-commands-misc.h" #include "qemu/cutils.h" #include "qemu/main-loop.h" +#include "qemu/option.h" #include "ui/console.h" #include "ui/gtk.h" @@ -115,6 +116,7 @@ #endif #define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK) +#define MAX_NUM_ATTEMPTS 5 static const guint16 *keycode_map; static size_t keycode_maplen; @@ -126,6 +128,15 @@ struct VCChardev { }; typedef struct VCChardev VCChardev; +struct gd_monitor_data { + GtkDisplayState *s; + GdkDisplay *dpy; + GdkMonitor *monitor; + QEMUTimer *hp_timer; + int attempt; +}; +typedef struct gd_monitor_data gd_monitor_data; + #define TYPE_CHARDEV_VC "chardev-vc" DECLARE_INSTANCE_CHECKER(VCChardev, VC_CHARDEV, TYPE_CHARDEV_VC) @@ -1385,6 +1396,147 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) } } +static void gd_monitor_fullscreen(GdkDisplay *dpy, VirtualConsole *vc, + gint monitor_num) +{ + GtkDisplayState *s = vc->s; + + if (!vc->window) { + gd_tab_window_create(vc); + } + gtk_window_fullscreen_on_monitor(GTK_WINDOW(vc->window), + gdk_display_get_default_screen(dpy), + monitor_num); + s->full_screen = TRUE; + gd_update_cursor(vc); +} + +static int gd_monitor_lookup(GdkDisplay *dpy, char *label) +{ + GdkMonitor *monitor; + const char *monitor_name; + int i, total_monitors; + + total_monitors = gdk_display_get_n_monitors(dpy); + for (i = 0; i < total_monitors; i++) { + monitor = gdk_display_get_monitor(dpy, i); + if (monitor) { + monitor_name = gdk_monitor_get_model(monitor); + if (monitor_name && !strcmp(monitor_name, label)) { + return i; + } + } + } + return -1; +} + +static void gd_monitor_check_vcs(GdkDisplay *dpy, GdkMonitor *monitor, + GtkDisplayState *s) +{ + VirtualConsole *vc; + const char *monitor_name = gdk_monitor_get_model(monitor); + int i; + + for (i = 0; i < s->nb_vcs; i++) { + vc = &s->vc[i]; + if (!strcmp(vc->label, monitor_name)) { + gd_monitor_fullscreen(dpy, vc, gd_monitor_lookup(dpy, vc->label)); + gd_set_ui_size(vc, surface_width(vc->gfx.ds), + surface_height(vc->gfx.ds)); + break; + } + } +} + +static void gd_monitor_hotplug_timer(void *opaque) +{ + gd_monitor_data *data = opaque; + const char *monitor_name = gdk_monitor_get_model(data->monitor); + + if (monitor_name) { + gd_monitor_check_vcs(data->dpy, data->monitor, data->s); + } + if (monitor_name || data->attempt == MAX_NUM_ATTEMPTS) { + timer_del(data->hp_timer); + g_free(data); + } else { + data->attempt++; + timer_mod(data->hp_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 50); + } +} + +static void gd_monitor_add(GdkDisplay *dpy, GdkMonitor *monitor, + void *opaque) +{ + GtkDisplayState *s = opaque; + gd_monitor_data *data; + const char *monitor_name = gdk_monitor_get_model(monitor); + + if (!monitor_name) { + data = g_malloc0(sizeof(*data)); + data->s = s; + data->dpy = dpy; + data->monitor = monitor; + data->hp_timer = timer_new_ms(QEMU_CLOCK_REALTIME, + gd_monitor_hotplug_timer, data); + timer_mod(data->hp_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 50); + } else { + gd_monitor_check_vcs(dpy, monitor, s); + } +} + +static void gd_monitor_remove(GdkDisplay *dpy, GdkMonitor *monitor, + void *opaque) +{ + GtkDisplayState *s = opaque; + VirtualConsole *vc; + const char *monitor_name = gdk_monitor_get_model(monitor); + int i; + + if (!monitor_name) { + return; + } + for (i = 0; i < s->nb_vcs; i++) { + vc = &s->vc[i]; + if (!strcmp(vc->label, monitor_name)) { + gd_tab_window_close(NULL, NULL, vc); + gd_set_ui_size(vc, 0, 0); + break; + } + } +} + +static void gd_connectors_init(GdkDisplay *dpy, GtkDisplayState *s) +{ + VirtualConsole *vc; + strList *connector = s->opts->u.gtk.connector; + gint page_num = 0, monitor_num; + + gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE); + gtk_widget_hide(s->menu_bar); + for (; connector; connector = connector->next) { + vc = gd_vc_find_by_page(s, page_num); + if (!vc) { + break; + } + if (page_num == 0) { + vc->window = s->window; + } + + g_free(vc->label); + vc->label = g_strdup(connector->value); + monitor_num = gd_monitor_lookup(dpy, vc->label); + if (monitor_num >= 0) { + gd_monitor_fullscreen(dpy, vc, monitor_num); + gd_set_ui_size(vc, surface_width(vc->gfx.ds), + surface_height(vc->gfx.ds)); + } else { + gd_set_ui_size(vc, 0, 0); + } + page_num++; + } +} + static void gd_menu_show_menubar(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; @@ -1705,7 +1857,14 @@ static gboolean gd_configure(GtkWidget *widget, GdkEventConfigure *cfg, gpointer opaque) { VirtualConsole *vc = opaque; + GtkDisplayState *s = vc->s; + GtkWidget *parent = gtk_widget_get_parent(widget); + if (s->opts->u.gtk.has_connector) { + if (!parent || !GTK_IS_WINDOW(parent)) { + return FALSE; + } + } gd_set_ui_size(vc, cfg->width, cfg->height); return FALSE; } @@ -2038,6 +2197,12 @@ static void gd_connect_signals(GtkDisplayState *s) G_CALLBACK(gd_menu_grab_input), s); g_signal_connect(s->notebook, "switch-page", G_CALLBACK(gd_change_page), s); + if (s->opts->u.gtk.has_connector) { + g_signal_connect(gtk_widget_get_display(s->window), "monitor-added", + G_CALLBACK(gd_monitor_add), s); + g_signal_connect(gtk_widget_get_display(s->window), "monitor-removed", + G_CALLBACK(gd_monitor_remove), s); + } } static GtkWidget *gd_create_menu_machine(GtkDisplayState *s) @@ -2402,6 +2567,9 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) opts->u.gtk.show_tabs) { gtk_menu_item_activate(GTK_MENU_ITEM(s->show_tabs_item)); } + if (s->opts->u.gtk.has_connector) { + gd_connectors_init(window_display, s); + } gd_clipboard_init(s); }