1use std::path::PathBuf;
2
3use crate::common::{OnOff, YesNo};
4use crate::to_command::{ToArg, ToCommand};
5
6#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
7pub enum OnCoreEsOff {
8 On,
9 Core,
10 Es,
11 Off,
12}
13
14impl ToArg for OnCoreEsOff {
15 fn to_arg(&self) -> &str {
16 match self {
17 OnCoreEsOff::On => "on",
18 OnCoreEsOff::Core => "core",
19 OnCoreEsOff::Es => "es",
20 OnCoreEsOff::Off => "off",
21 }
22 }
23}
24
25#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
26pub enum QemuDisplay {
27 Spice {
28 gl: Option<OnOff>,
29 },
30 Sdl {
31 gl: Option<OnCoreEsOff>,
32 grab_mod: Option<String>,
33 show_cursor: Option<OnOff>,
34 window_close: Option<OnOff>,
35 },
36 Gtk {
37 fullscreen: Option<OnOff>,
38 gl: Option<OnOff>,
39 grab_on_hover: Option<OnOff>,
40 show_tabs: Option<OnOff>,
41 show_cursor: Option<OnOff>,
42 window_close: Option<OnOff>,
43 show_menubar: Option<OnOff>,
44 zoom_to_fit: Option<OnOff>,
45 },
46 Vnc {
47 vnc: String,
48 optargs: Option<String>,
49 },
50 Curses {
51 charset: Option<String>,
52 },
53 Cocoa {
54 full_grab: Option<OnOff>,
55 swap_opt_cmd: Option<OnOff>,
56 show_cursor: Option<OnOff>,
57 left_command_key: Option<OnOff>,
58 full_screen: Option<OnOff>,
59 zoom_to_fit: Option<OnOff>,
60 },
61 EglHeadless {
62 rendernode: Option<PathBuf>,
63 },
64 Dbus {
65 addr: Option<String>,
66 p2p: Option<YesNo>,
67 gl: Option<OnCoreEsOff>,
68 rendernode: Option<PathBuf>,
69 },
70 None,
71}
72
73impl ToCommand for QemuDisplay {
74 fn to_command(&self) -> Vec<String> {
75 let mut cmd = vec![];
76
77 cmd.push("-display".to_string());
78
79 let mut args = vec![];
80 match self {
81 QemuDisplay::Spice { gl } => {
82 args.push("spice-app".to_string());
83 if let Some(gl) = gl {
84 args.push(format!("gl={}", gl.to_arg()));
85 }
86 }
87 QemuDisplay::Sdl {
88 gl,
89 grab_mod,
90 show_cursor,
91 window_close,
92 } => {
93 args.push("sdl".to_string());
94 if let Some(gl) = gl {
95 args.push(format!("gl={}", gl.to_arg()));
96 }
97 if let Some(grab_mod) = grab_mod {
98 args.push(format!("grab-mod={}", grab_mod));
99 }
100 if let Some(show_cursor) = show_cursor {
101 args.push(format!("show-cursor={}", show_cursor.to_arg()));
102 }
103 if let Some(window_close) = window_close {
104 args.push(format!("window-close={}", window_close.to_arg()));
105 }
106 }
107 QemuDisplay::Gtk {
108 fullscreen,
109 gl,
110 grab_on_hover,
111 show_tabs,
112 show_cursor,
113 window_close,
114 show_menubar,
115 zoom_to_fit,
116 } => {
117 args.push("gtk".to_string());
118 if let Some(fullscreen) = fullscreen {
119 args.push(format!("full-screen={}", fullscreen.to_arg()));
120 }
121 if let Some(gl) = gl {
122 args.push(format!("gl={}", gl.to_arg()));
123 }
124 if let Some(grab_on_hover) = grab_on_hover {
125 args.push(format!("grab-on-hover={}", grab_on_hover.to_arg()));
126 }
127 if let Some(show_tabs) = show_tabs {
128 args.push(format!("show-tabs={}", show_tabs.to_arg()));
129 }
130 if let Some(show_cursor) = show_cursor {
131 args.push(format!("show-cursor={}", show_cursor.to_arg()));
132 }
133 if let Some(window_close) = window_close {
134 args.push(format!("window-close={}", window_close.to_arg()));
135 }
136 if let Some(show_menubar) = show_menubar {
137 args.push(format!("show-menubar={}", show_menubar.to_arg()));
138 }
139 if let Some(zoom_to_fit) = zoom_to_fit {
140 args.push(format!("zoom-to-fit={}", zoom_to_fit.to_arg()));
141 }
142 }
143 QemuDisplay::Vnc { vnc, optargs } => {
144 args.push(format!("vnc={}", vnc.clone()));
145 if let Some(optargs) = optargs {
146 args.push(optargs.clone());
147 }
148 }
149 QemuDisplay::Curses { charset } => {
150 args.push("curses".to_string());
151 if let Some(charset) = charset {
152 args.push(format!("charset={}", charset));
153 }
154 }
155 QemuDisplay::Cocoa {
156 full_grab,
157 swap_opt_cmd,
158 show_cursor,
159 left_command_key,
160 full_screen,
161 zoom_to_fit,
162 } => {
163 args.push("cocoa".to_string());
164 if let Some(full_grab) = full_grab {
165 args.push(format!("full-grab={}", full_grab.to_arg()));
166 }
167 if let Some(swap_opt_cmd) = swap_opt_cmd {
168 args.push(format!("swap-opt-cmd={}", swap_opt_cmd.to_arg()));
169 }
170 if let Some(show_cursor) = show_cursor {
171 args.push(format!("show-cursor={}", show_cursor.to_arg()));
172 }
173 if let Some(left_command_key) = left_command_key {
174 args.push(format!("left-command-key={}", left_command_key.to_arg()));
175 }
176 if let Some(full_screen) = full_screen {
177 args.push(format!("full-screen={}", full_screen.to_arg()));
178 }
179 if let Some(zoom_to_fit) = zoom_to_fit {
180 args.push(format!("zoom-to-fit={}", zoom_to_fit.to_arg()));
181 }
182 }
183 QemuDisplay::EglHeadless { rendernode } => {
184 args.push("egl-headless".to_string());
185 if let Some(rendernode) = rendernode {
186 args.push(format!("rendernode={}", rendernode.display()));
187 }
188 }
189 QemuDisplay::Dbus {
190 addr,
191 p2p,
192 gl,
193 rendernode,
194 } => {
195 args.push("dbus".to_string());
196 if let Some(addr) = addr {
197 args.push(format!("addr={}", addr));
198 }
199 if let Some(p2p) = p2p {
200 args.push(format!("p2p={}", p2p.to_arg()));
201 }
202 if let Some(gl) = gl {
203 args.push(format!("gl={}", gl.to_arg()));
204 }
205 if let Some(rendernode) = rendernode {
206 args.push(format!("rendernode={}", rendernode.display()));
207 }
208 }
209 QemuDisplay::None => {
210 args.push("none".to_string());
211 }
212 }
213 cmd.push(args.join(","));
214 cmd
215 }
216}