root / ui / gtk.c @ 5cc11c46
History | View | Annotate | Download (41.4 kB)
1 | a4ccabcf | Anthony Liguori | /*
|
---|---|---|---|
2 | a4ccabcf | Anthony Liguori | * GTK UI
|
3 | a4ccabcf | Anthony Liguori | *
|
4 | a4ccabcf | Anthony Liguori | * Copyright IBM, Corp. 2012
|
5 | a4ccabcf | Anthony Liguori | *
|
6 | a4ccabcf | Anthony Liguori | * Authors:
|
7 | a4ccabcf | Anthony Liguori | * Anthony Liguori <aliguori@us.ibm.com>
|
8 | a4ccabcf | Anthony Liguori | *
|
9 | a4ccabcf | Anthony Liguori | * This work is licensed under the terms of the GNU GPL, version 2 or later.
|
10 | a4ccabcf | Anthony Liguori | * See the COPYING file in the top-level directory.
|
11 | a4ccabcf | Anthony Liguori | *
|
12 | a4ccabcf | Anthony Liguori | * Portions from gtk-vnc:
|
13 | a4ccabcf | Anthony Liguori | *
|
14 | a4ccabcf | Anthony Liguori | * GTK VNC Widget
|
15 | a4ccabcf | Anthony Liguori | *
|
16 | a4ccabcf | Anthony Liguori | * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
|
17 | a4ccabcf | Anthony Liguori | * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com>
|
18 | a4ccabcf | Anthony Liguori | *
|
19 | a4ccabcf | Anthony Liguori | * This library is free software; you can redistribute it and/or
|
20 | a4ccabcf | Anthony Liguori | * modify it under the terms of the GNU Lesser General Public
|
21 | a4ccabcf | Anthony Liguori | * License as published by the Free Software Foundation; either
|
22 | a4ccabcf | Anthony Liguori | * version 2.0 of the License, or (at your option) any later version.
|
23 | a4ccabcf | Anthony Liguori | *
|
24 | a4ccabcf | Anthony Liguori | * This library is distributed in the hope that it will be useful,
|
25 | a4ccabcf | Anthony Liguori | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
26 | a4ccabcf | Anthony Liguori | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
27 | a4ccabcf | Anthony Liguori | * Lesser General Public License for more details.
|
28 | a4ccabcf | Anthony Liguori | *
|
29 | a4ccabcf | Anthony Liguori | * You should have received a copy of the GNU Lesser General Public
|
30 | a4ccabcf | Anthony Liguori | * License along with this library; if not, write to the Free Software
|
31 | a4ccabcf | Anthony Liguori | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
32 | a4ccabcf | Anthony Liguori | */
|
33 | a4ccabcf | Anthony Liguori | |
34 | 834574ea | Anthony Liguori | #define GETTEXT_PACKAGE "qemu" |
35 | 834574ea | Anthony Liguori | #define LOCALEDIR "po" |
36 | 834574ea | Anthony Liguori | |
37 | c95e3080 | Kevin Wolf | #include "qemu-common.h" |
38 | c95e3080 | Kevin Wolf | |
39 | c95e3080 | Kevin Wolf | #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
|
40 | c95e3080 | Kevin Wolf | /* Work around an -Wstrict-prototypes warning in GTK headers */
|
41 | c95e3080 | Kevin Wolf | #pragma GCC diagnostic ignored "-Wstrict-prototypes" |
42 | c95e3080 | Kevin Wolf | #endif
|
43 | a4ccabcf | Anthony Liguori | #include <gtk/gtk.h> |
44 | c95e3080 | Kevin Wolf | #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
|
45 | c95e3080 | Kevin Wolf | #pragma GCC diagnostic error "-Wstrict-prototypes" |
46 | c95e3080 | Kevin Wolf | #endif
|
47 | c95e3080 | Kevin Wolf | |
48 | c95e3080 | Kevin Wolf | |
49 | a4ccabcf | Anthony Liguori | #include <gdk/gdkkeysyms.h> |
50 | 834574ea | Anthony Liguori | #include <glib/gi18n.h> |
51 | 3f58eade | Stefan Weil | #include <locale.h> |
52 | a4ccabcf | Anthony Liguori | #include <vte/vte.h> |
53 | a4ccabcf | Anthony Liguori | #include <sys/types.h> |
54 | a4ccabcf | Anthony Liguori | #include <sys/socket.h> |
55 | a4ccabcf | Anthony Liguori | #include <sys/un.h> |
56 | a4ccabcf | Anthony Liguori | #include <sys/wait.h> |
57 | a4ccabcf | Anthony Liguori | #include <pty.h> |
58 | a4ccabcf | Anthony Liguori | #include <math.h> |
59 | a4ccabcf | Anthony Liguori | |
60 | a4ccabcf | Anthony Liguori | #include "ui/console.h" |
61 | a4ccabcf | Anthony Liguori | #include "sysemu/sysemu.h" |
62 | a4ccabcf | Anthony Liguori | #include "qmp-commands.h" |
63 | a4ccabcf | Anthony Liguori | #include "x_keymap.h" |
64 | a4ccabcf | Anthony Liguori | #include "keymaps.h" |
65 | d861def3 | Anthony Liguori | #include "char/char.h" |
66 | a4ccabcf | Anthony Liguori | |
67 | a4ccabcf | Anthony Liguori | //#define DEBUG_GTK
|
68 | a4ccabcf | Anthony Liguori | |
69 | a4ccabcf | Anthony Liguori | #ifdef DEBUG_GTK
|
70 | a4ccabcf | Anthony Liguori | #define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) |
71 | a4ccabcf | Anthony Liguori | #else
|
72 | a4ccabcf | Anthony Liguori | #define DPRINTF(fmt, ...) do { } while (0) |
73 | a4ccabcf | Anthony Liguori | #endif
|
74 | a4ccabcf | Anthony Liguori | |
75 | d861def3 | Anthony Liguori | #define MAX_VCS 10 |
76 | d861def3 | Anthony Liguori | |
77 | cba68834 | Daniel P. Berrange | |
78 | cba68834 | Daniel P. Berrange | /* Compatibility define to let us build on both Gtk2 and Gtk3 */
|
79 | cba68834 | Daniel P. Berrange | #if GTK_CHECK_VERSION(3, 0, 0) |
80 | cba68834 | Daniel P. Berrange | static inline void gdk_drawable_get_size(GdkWindow *w, gint *ww, gint *wh) |
81 | cba68834 | Daniel P. Berrange | { |
82 | cba68834 | Daniel P. Berrange | *ww = gdk_window_get_width(w); |
83 | cba68834 | Daniel P. Berrange | *wh = gdk_window_get_height(w); |
84 | cba68834 | Daniel P. Berrange | } |
85 | cba68834 | Daniel P. Berrange | #endif
|
86 | cba68834 | Daniel P. Berrange | |
87 | ef6413a2 | Daniel P. Berrange | #if !GTK_CHECK_VERSION(2, 20, 0) |
88 | ef6413a2 | Daniel P. Berrange | #define gtk_widget_get_realized(widget) GTK_WIDGET_REALIZED(widget)
|
89 | ef6413a2 | Daniel P. Berrange | #endif
|
90 | ef6413a2 | Daniel P. Berrange | |
91 | bc0477c7 | Daniel P. Berrange | #ifndef GDK_KEY_0
|
92 | bc0477c7 | Daniel P. Berrange | #define GDK_KEY_0 GDK_0
|
93 | bc0477c7 | Daniel P. Berrange | #define GDK_KEY_1 GDK_1
|
94 | bc0477c7 | Daniel P. Berrange | #define GDK_KEY_2 GDK_2
|
95 | bc0477c7 | Daniel P. Berrange | #define GDK_KEY_f GDK_f
|
96 | bc0477c7 | Daniel P. Berrange | #define GDK_KEY_g GDK_g
|
97 | bc0477c7 | Daniel P. Berrange | #define GDK_KEY_plus GDK_plus
|
98 | bc0477c7 | Daniel P. Berrange | #define GDK_KEY_minus GDK_minus
|
99 | bc0477c7 | Daniel P. Berrange | #endif
|
100 | ef6413a2 | Daniel P. Berrange | |
101 | 6db253ca | Jan Kiszka | static const int modifier_keycode[] = { |
102 | 6db253ca | Jan Kiszka | /* shift, control, alt keys, meta keys, both left & right */
|
103 | 6db253ca | Jan Kiszka | 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, 0xdb, 0xdd, |
104 | 6db253ca | Jan Kiszka | }; |
105 | 6db253ca | Jan Kiszka | |
106 | a4ccabcf | Anthony Liguori | typedef struct VirtualConsole |
107 | a4ccabcf | Anthony Liguori | { |
108 | a4ccabcf | Anthony Liguori | GtkWidget *menu_item; |
109 | a4ccabcf | Anthony Liguori | GtkWidget *terminal; |
110 | a4ccabcf | Anthony Liguori | GtkWidget *scrolled_window; |
111 | a4ccabcf | Anthony Liguori | CharDriverState *chr; |
112 | a4ccabcf | Anthony Liguori | int fd;
|
113 | a4ccabcf | Anthony Liguori | } VirtualConsole; |
114 | a4ccabcf | Anthony Liguori | |
115 | a4ccabcf | Anthony Liguori | typedef struct GtkDisplayState |
116 | a4ccabcf | Anthony Liguori | { |
117 | a4ccabcf | Anthony Liguori | GtkWidget *window; |
118 | a4ccabcf | Anthony Liguori | |
119 | a4ccabcf | Anthony Liguori | GtkWidget *menu_bar; |
120 | a4ccabcf | Anthony Liguori | |
121 | 73d4dc71 | Anthony Liguori | GtkAccelGroup *accel_group; |
122 | 73d4dc71 | Anthony Liguori | |
123 | 30e8f22b | Jan Kiszka | GtkWidget *machine_menu_item; |
124 | 30e8f22b | Jan Kiszka | GtkWidget *machine_menu; |
125 | 30e8f22b | Jan Kiszka | GtkWidget *pause_item; |
126 | 30e8f22b | Jan Kiszka | GtkWidget *reset_item; |
127 | 30e8f22b | Jan Kiszka | GtkWidget *powerdown_item; |
128 | a4ccabcf | Anthony Liguori | GtkWidget *quit_item; |
129 | a4ccabcf | Anthony Liguori | |
130 | a4ccabcf | Anthony Liguori | GtkWidget *view_menu_item; |
131 | a4ccabcf | Anthony Liguori | GtkWidget *view_menu; |
132 | c6158483 | Anthony Liguori | GtkWidget *full_screen_item; |
133 | c6158483 | Anthony Liguori | GtkWidget *zoom_in_item; |
134 | c6158483 | Anthony Liguori | GtkWidget *zoom_out_item; |
135 | c6158483 | Anthony Liguori | GtkWidget *zoom_fixed_item; |
136 | c6158483 | Anthony Liguori | GtkWidget *zoom_fit_item; |
137 | 5104a1f6 | Anthony Liguori | GtkWidget *grab_item; |
138 | 5104a1f6 | Anthony Liguori | GtkWidget *grab_on_hover_item; |
139 | a4ccabcf | Anthony Liguori | GtkWidget *vga_item; |
140 | a4ccabcf | Anthony Liguori | |
141 | d861def3 | Anthony Liguori | int nb_vcs;
|
142 | d861def3 | Anthony Liguori | VirtualConsole vc[MAX_VCS]; |
143 | d861def3 | Anthony Liguori | |
144 | a4ccabcf | Anthony Liguori | GtkWidget *show_tabs_item; |
145 | a4ccabcf | Anthony Liguori | |
146 | a4ccabcf | Anthony Liguori | GtkWidget *vbox; |
147 | a4ccabcf | Anthony Liguori | GtkWidget *notebook; |
148 | a4ccabcf | Anthony Liguori | GtkWidget *drawing_area; |
149 | a4ccabcf | Anthony Liguori | cairo_surface_t *surface; |
150 | a4ccabcf | Anthony Liguori | DisplayChangeListener dcl; |
151 | 9d9801cf | Gerd Hoffmann | DisplaySurface *ds; |
152 | a4ccabcf | Anthony Liguori | int button_mask;
|
153 | a4ccabcf | Anthony Liguori | int last_x;
|
154 | a4ccabcf | Anthony Liguori | int last_y;
|
155 | a4ccabcf | Anthony Liguori | |
156 | a4ccabcf | Anthony Liguori | double scale_x;
|
157 | a4ccabcf | Anthony Liguori | double scale_y;
|
158 | c6158483 | Anthony Liguori | gboolean full_screen; |
159 | a4ccabcf | Anthony Liguori | |
160 | a4ccabcf | Anthony Liguori | GdkCursor *null_cursor; |
161 | a4ccabcf | Anthony Liguori | Notifier mouse_mode_notifier; |
162 | c6158483 | Anthony Liguori | gboolean free_scale; |
163 | 30e8f22b | Jan Kiszka | |
164 | 30e8f22b | Jan Kiszka | bool external_pause_update;
|
165 | 6db253ca | Jan Kiszka | |
166 | 6db253ca | Jan Kiszka | bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
|
167 | a4ccabcf | Anthony Liguori | } GtkDisplayState; |
168 | a4ccabcf | Anthony Liguori | |
169 | a4ccabcf | Anthony Liguori | static GtkDisplayState *global_state;
|
170 | a4ccabcf | Anthony Liguori | |
171 | a4ccabcf | Anthony Liguori | /** Utility Functions **/
|
172 | a4ccabcf | Anthony Liguori | |
173 | 5104a1f6 | Anthony Liguori | static bool gd_is_grab_active(GtkDisplayState *s) |
174 | 5104a1f6 | Anthony Liguori | { |
175 | 5104a1f6 | Anthony Liguori | return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->grab_item));
|
176 | 5104a1f6 | Anthony Liguori | } |
177 | 5104a1f6 | Anthony Liguori | |
178 | 5104a1f6 | Anthony Liguori | static bool gd_grab_on_hover(GtkDisplayState *s) |
179 | 5104a1f6 | Anthony Liguori | { |
180 | 5104a1f6 | Anthony Liguori | return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->grab_on_hover_item));
|
181 | 5104a1f6 | Anthony Liguori | } |
182 | 5104a1f6 | Anthony Liguori | |
183 | 5104a1f6 | Anthony Liguori | static bool gd_on_vga(GtkDisplayState *s) |
184 | 5104a1f6 | Anthony Liguori | { |
185 | 5104a1f6 | Anthony Liguori | return gtk_notebook_get_current_page(GTK_NOTEBOOK(s->notebook)) == 0; |
186 | 5104a1f6 | Anthony Liguori | } |
187 | 5104a1f6 | Anthony Liguori | |
188 | a4ccabcf | Anthony Liguori | static void gd_update_cursor(GtkDisplayState *s, gboolean override) |
189 | a4ccabcf | Anthony Liguori | { |
190 | a4ccabcf | Anthony Liguori | GdkWindow *window; |
191 | a4ccabcf | Anthony Liguori | bool on_vga;
|
192 | a4ccabcf | Anthony Liguori | |
193 | a4ccabcf | Anthony Liguori | window = gtk_widget_get_window(GTK_WIDGET(s->drawing_area)); |
194 | a4ccabcf | Anthony Liguori | |
195 | 5104a1f6 | Anthony Liguori | on_vga = gd_on_vga(s); |
196 | a4ccabcf | Anthony Liguori | |
197 | 5104a1f6 | Anthony Liguori | if ((override || on_vga) &&
|
198 | c6158483 | Anthony Liguori | (s->full_screen || kbd_mouse_is_absolute() || gd_is_grab_active(s))) { |
199 | a4ccabcf | Anthony Liguori | gdk_window_set_cursor(window, s->null_cursor); |
200 | a4ccabcf | Anthony Liguori | } else {
|
201 | a4ccabcf | Anthony Liguori | gdk_window_set_cursor(window, NULL);
|
202 | a4ccabcf | Anthony Liguori | } |
203 | a4ccabcf | Anthony Liguori | } |
204 | a4ccabcf | Anthony Liguori | |
205 | a4ccabcf | Anthony Liguori | static void gd_update_caption(GtkDisplayState *s) |
206 | a4ccabcf | Anthony Liguori | { |
207 | a4ccabcf | Anthony Liguori | const char *status = ""; |
208 | a4ccabcf | Anthony Liguori | gchar *title; |
209 | 5104a1f6 | Anthony Liguori | const char *grab = ""; |
210 | 30e8f22b | Jan Kiszka | bool is_paused = !runstate_is_running();
|
211 | 5104a1f6 | Anthony Liguori | |
212 | 5104a1f6 | Anthony Liguori | if (gd_is_grab_active(s)) {
|
213 | 5104a1f6 | Anthony Liguori | grab = " - Press Ctrl+Alt+G to release grab";
|
214 | 5104a1f6 | Anthony Liguori | } |
215 | a4ccabcf | Anthony Liguori | |
216 | 30e8f22b | Jan Kiszka | if (is_paused) {
|
217 | 30e8f22b | Jan Kiszka | status = " [Paused]";
|
218 | a4ccabcf | Anthony Liguori | } |
219 | 30e8f22b | Jan Kiszka | s->external_pause_update = true;
|
220 | 30e8f22b | Jan Kiszka | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->pause_item), |
221 | 30e8f22b | Jan Kiszka | is_paused); |
222 | 30e8f22b | Jan Kiszka | s->external_pause_update = false;
|
223 | a4ccabcf | Anthony Liguori | |
224 | a4ccabcf | Anthony Liguori | if (qemu_name) {
|
225 | 5104a1f6 | Anthony Liguori | title = g_strdup_printf("QEMU (%s)%s%s", qemu_name, status, grab);
|
226 | a4ccabcf | Anthony Liguori | } else {
|
227 | 5104a1f6 | Anthony Liguori | title = g_strdup_printf("QEMU%s%s", status, grab);
|
228 | a4ccabcf | Anthony Liguori | } |
229 | a4ccabcf | Anthony Liguori | |
230 | a4ccabcf | Anthony Liguori | gtk_window_set_title(GTK_WINDOW(s->window), title); |
231 | a4ccabcf | Anthony Liguori | |
232 | a4ccabcf | Anthony Liguori | g_free(title); |
233 | a4ccabcf | Anthony Liguori | } |
234 | a4ccabcf | Anthony Liguori | |
235 | 9d9801cf | Gerd Hoffmann | static void gd_update_windowsize(GtkDisplayState *s) |
236 | 9d9801cf | Gerd Hoffmann | { |
237 | 9d9801cf | Gerd Hoffmann | if (!s->full_screen) {
|
238 | 9d9801cf | Gerd Hoffmann | GtkRequisition req; |
239 | 9d9801cf | Gerd Hoffmann | double sx, sy;
|
240 | 9d9801cf | Gerd Hoffmann | |
241 | 9d9801cf | Gerd Hoffmann | if (s->free_scale) {
|
242 | 9d9801cf | Gerd Hoffmann | sx = s->scale_x; |
243 | 9d9801cf | Gerd Hoffmann | sy = s->scale_y; |
244 | 9d9801cf | Gerd Hoffmann | |
245 | 9d9801cf | Gerd Hoffmann | s->scale_y = 1.0; |
246 | 9d9801cf | Gerd Hoffmann | s->scale_x = 1.0; |
247 | 9d9801cf | Gerd Hoffmann | } else {
|
248 | 9d9801cf | Gerd Hoffmann | sx = 1.0; |
249 | 9d9801cf | Gerd Hoffmann | sy = 1.0; |
250 | 9d9801cf | Gerd Hoffmann | } |
251 | 9d9801cf | Gerd Hoffmann | |
252 | 9d9801cf | Gerd Hoffmann | gtk_widget_set_size_request(s->drawing_area, |
253 | 9d9801cf | Gerd Hoffmann | surface_width(s->ds) * s->scale_x, |
254 | 9d9801cf | Gerd Hoffmann | surface_height(s->ds) * s->scale_y); |
255 | 9d9801cf | Gerd Hoffmann | #if GTK_CHECK_VERSION(3, 0, 0) |
256 | 9d9801cf | Gerd Hoffmann | gtk_widget_get_preferred_size(s->vbox, NULL, &req);
|
257 | 9d9801cf | Gerd Hoffmann | #else
|
258 | 9d9801cf | Gerd Hoffmann | gtk_widget_size_request(s->vbox, &req); |
259 | 9d9801cf | Gerd Hoffmann | #endif
|
260 | 9d9801cf | Gerd Hoffmann | |
261 | 9d9801cf | Gerd Hoffmann | gtk_window_resize(GTK_WINDOW(s->window), |
262 | 9d9801cf | Gerd Hoffmann | req.width * sx, req.height * sy); |
263 | 9d9801cf | Gerd Hoffmann | } |
264 | 9d9801cf | Gerd Hoffmann | } |
265 | 9d9801cf | Gerd Hoffmann | |
266 | 9d9801cf | Gerd Hoffmann | static void gd_update_full_redraw(GtkDisplayState *s) |
267 | 9d9801cf | Gerd Hoffmann | { |
268 | 9d9801cf | Gerd Hoffmann | int ww, wh;
|
269 | 9d9801cf | Gerd Hoffmann | gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); |
270 | 9d9801cf | Gerd Hoffmann | gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh); |
271 | 9d9801cf | Gerd Hoffmann | } |
272 | 9d9801cf | Gerd Hoffmann | |
273 | 6db253ca | Jan Kiszka | static void gtk_release_modifiers(GtkDisplayState *s) |
274 | 6db253ca | Jan Kiszka | { |
275 | 6db253ca | Jan Kiszka | int i, keycode;
|
276 | 6db253ca | Jan Kiszka | |
277 | 6db253ca | Jan Kiszka | if (!gd_on_vga(s)) {
|
278 | 6db253ca | Jan Kiszka | return;
|
279 | 6db253ca | Jan Kiszka | } |
280 | 6db253ca | Jan Kiszka | for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) { |
281 | 6db253ca | Jan Kiszka | keycode = modifier_keycode[i]; |
282 | 6db253ca | Jan Kiszka | if (!s->modifier_pressed[i]) {
|
283 | 6db253ca | Jan Kiszka | continue;
|
284 | 6db253ca | Jan Kiszka | } |
285 | 6db253ca | Jan Kiszka | if (keycode & SCANCODE_GREY) {
|
286 | 6db253ca | Jan Kiszka | kbd_put_keycode(SCANCODE_EMUL0); |
287 | 6db253ca | Jan Kiszka | } |
288 | 6db253ca | Jan Kiszka | kbd_put_keycode(keycode | SCANCODE_UP); |
289 | 6db253ca | Jan Kiszka | s->modifier_pressed[i] = false;
|
290 | 6db253ca | Jan Kiszka | } |
291 | 6db253ca | Jan Kiszka | } |
292 | 6db253ca | Jan Kiszka | |
293 | a4ccabcf | Anthony Liguori | /** DisplayState Callbacks **/
|
294 | a4ccabcf | Anthony Liguori | |
295 | 7c20b4a3 | Gerd Hoffmann | static void gd_update(DisplayChangeListener *dcl, |
296 | bc2ed970 | Gerd Hoffmann | int x, int y, int w, int h) |
297 | a4ccabcf | Anthony Liguori | { |
298 | 21ef45d7 | Gerd Hoffmann | GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); |
299 | a4ccabcf | Anthony Liguori | int x1, x2, y1, y2;
|
300 | c6158483 | Anthony Liguori | int mx, my;
|
301 | c6158483 | Anthony Liguori | int fbw, fbh;
|
302 | c6158483 | Anthony Liguori | int ww, wh;
|
303 | a4ccabcf | Anthony Liguori | |
304 | a4ccabcf | Anthony Liguori | DPRINTF("update(x=%d, y=%d, w=%d, h=%d)\n", x, y, w, h);
|
305 | a4ccabcf | Anthony Liguori | |
306 | a4ccabcf | Anthony Liguori | x1 = floor(x * s->scale_x); |
307 | a4ccabcf | Anthony Liguori | y1 = floor(y * s->scale_y); |
308 | a4ccabcf | Anthony Liguori | |
309 | a4ccabcf | Anthony Liguori | x2 = ceil(x * s->scale_x + w * s->scale_x); |
310 | a4ccabcf | Anthony Liguori | y2 = ceil(y * s->scale_y + h * s->scale_y); |
311 | a4ccabcf | Anthony Liguori | |
312 | 9d9801cf | Gerd Hoffmann | fbw = surface_width(s->ds) * s->scale_x; |
313 | 9d9801cf | Gerd Hoffmann | fbh = surface_height(s->ds) * s->scale_y; |
314 | c6158483 | Anthony Liguori | |
315 | c6158483 | Anthony Liguori | gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); |
316 | c6158483 | Anthony Liguori | |
317 | c6158483 | Anthony Liguori | mx = my = 0;
|
318 | c6158483 | Anthony Liguori | if (ww > fbw) {
|
319 | c6158483 | Anthony Liguori | mx = (ww - fbw) / 2;
|
320 | c6158483 | Anthony Liguori | } |
321 | c6158483 | Anthony Liguori | if (wh > fbh) {
|
322 | c6158483 | Anthony Liguori | my = (wh - fbh) / 2;
|
323 | c6158483 | Anthony Liguori | } |
324 | c6158483 | Anthony Liguori | |
325 | c6158483 | Anthony Liguori | gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1)); |
326 | a4ccabcf | Anthony Liguori | } |
327 | a4ccabcf | Anthony Liguori | |
328 | bc2ed970 | Gerd Hoffmann | static void gd_refresh(DisplayChangeListener *dcl) |
329 | a4ccabcf | Anthony Liguori | { |
330 | a4ccabcf | Anthony Liguori | vga_hw_update(); |
331 | a4ccabcf | Anthony Liguori | } |
332 | a4ccabcf | Anthony Liguori | |
333 | c12aeb86 | Gerd Hoffmann | static void gd_switch(DisplayChangeListener *dcl, |
334 | c12aeb86 | Gerd Hoffmann | DisplaySurface *surface) |
335 | a4ccabcf | Anthony Liguori | { |
336 | 21ef45d7 | Gerd Hoffmann | GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); |
337 | a4ccabcf | Anthony Liguori | cairo_format_t kind; |
338 | 9d9801cf | Gerd Hoffmann | bool resized = true; |
339 | a4ccabcf | Anthony Liguori | int stride;
|
340 | a4ccabcf | Anthony Liguori | |
341 | a4ccabcf | Anthony Liguori | DPRINTF("resize(width=%d, height=%d)\n",
|
342 | 9d9801cf | Gerd Hoffmann | surface_width(surface), surface_height(surface)); |
343 | a4ccabcf | Anthony Liguori | |
344 | a4ccabcf | Anthony Liguori | if (s->surface) {
|
345 | a4ccabcf | Anthony Liguori | cairo_surface_destroy(s->surface); |
346 | a4ccabcf | Anthony Liguori | } |
347 | a4ccabcf | Anthony Liguori | |
348 | 9d9801cf | Gerd Hoffmann | if (s->ds &&
|
349 | 9d9801cf | Gerd Hoffmann | surface_width(s->ds) == surface_width(surface) && |
350 | 9d9801cf | Gerd Hoffmann | surface_height(s->ds) == surface_height(surface)) { |
351 | 9d9801cf | Gerd Hoffmann | resized = false;
|
352 | 9d9801cf | Gerd Hoffmann | } |
353 | 9d9801cf | Gerd Hoffmann | s->ds = surface; |
354 | 9d9801cf | Gerd Hoffmann | switch (surface_bits_per_pixel(surface)) {
|
355 | a4ccabcf | Anthony Liguori | case 8: |
356 | a4ccabcf | Anthony Liguori | kind = CAIRO_FORMAT_A8; |
357 | a4ccabcf | Anthony Liguori | break;
|
358 | a4ccabcf | Anthony Liguori | case 16: |
359 | a4ccabcf | Anthony Liguori | kind = CAIRO_FORMAT_RGB16_565; |
360 | a4ccabcf | Anthony Liguori | break;
|
361 | a4ccabcf | Anthony Liguori | case 32: |
362 | a4ccabcf | Anthony Liguori | kind = CAIRO_FORMAT_RGB24; |
363 | a4ccabcf | Anthony Liguori | break;
|
364 | a4ccabcf | Anthony Liguori | default:
|
365 | a4ccabcf | Anthony Liguori | g_assert_not_reached(); |
366 | a4ccabcf | Anthony Liguori | break;
|
367 | a4ccabcf | Anthony Liguori | } |
368 | a4ccabcf | Anthony Liguori | |
369 | 9d9801cf | Gerd Hoffmann | stride = cairo_format_stride_for_width(kind, surface_width(surface)); |
370 | 9d9801cf | Gerd Hoffmann | g_assert(surface_stride(surface) == stride); |
371 | a4ccabcf | Anthony Liguori | |
372 | 9d9801cf | Gerd Hoffmann | s->surface = cairo_image_surface_create_for_data(surface_data(surface), |
373 | a4ccabcf | Anthony Liguori | kind, |
374 | 9d9801cf | Gerd Hoffmann | surface_width(surface), |
375 | 9d9801cf | Gerd Hoffmann | surface_height(surface), |
376 | 9d9801cf | Gerd Hoffmann | surface_stride(surface)); |
377 | c6158483 | Anthony Liguori | |
378 | 9d9801cf | Gerd Hoffmann | if (resized) {
|
379 | 9d9801cf | Gerd Hoffmann | gd_update_windowsize(s); |
380 | 9d9801cf | Gerd Hoffmann | } else {
|
381 | 9d9801cf | Gerd Hoffmann | gd_update_full_redraw(s); |
382 | c6158483 | Anthony Liguori | } |
383 | a4ccabcf | Anthony Liguori | } |
384 | a4ccabcf | Anthony Liguori | |
385 | a4ccabcf | Anthony Liguori | /** QEMU Events **/
|
386 | a4ccabcf | Anthony Liguori | |
387 | a4ccabcf | Anthony Liguori | static void gd_change_runstate(void *opaque, int running, RunState state) |
388 | a4ccabcf | Anthony Liguori | { |
389 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = opaque; |
390 | a4ccabcf | Anthony Liguori | |
391 | a4ccabcf | Anthony Liguori | gd_update_caption(s); |
392 | a4ccabcf | Anthony Liguori | } |
393 | a4ccabcf | Anthony Liguori | |
394 | a4ccabcf | Anthony Liguori | static void gd_mouse_mode_change(Notifier *notify, void *data) |
395 | a4ccabcf | Anthony Liguori | { |
396 | a4ccabcf | Anthony Liguori | gd_update_cursor(container_of(notify, GtkDisplayState, mouse_mode_notifier), |
397 | a4ccabcf | Anthony Liguori | FALSE); |
398 | a4ccabcf | Anthony Liguori | } |
399 | a4ccabcf | Anthony Liguori | |
400 | a4ccabcf | Anthony Liguori | /** GTK Events **/
|
401 | a4ccabcf | Anthony Liguori | |
402 | 73d4dc71 | Anthony Liguori | static gboolean gd_window_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) |
403 | 73d4dc71 | Anthony Liguori | { |
404 | 73d4dc71 | Anthony Liguori | GtkDisplayState *s = opaque; |
405 | 73d4dc71 | Anthony Liguori | GtkAccelGroupEntry *entries; |
406 | 73d4dc71 | Anthony Liguori | guint n_entries = 0;
|
407 | 73d4dc71 | Anthony Liguori | gboolean propagate_accel = TRUE; |
408 | 73d4dc71 | Anthony Liguori | gboolean handled = FALSE; |
409 | 73d4dc71 | Anthony Liguori | |
410 | 73d4dc71 | Anthony Liguori | entries = gtk_accel_group_query(s->accel_group, key->keyval, |
411 | 73d4dc71 | Anthony Liguori | key->state, &n_entries); |
412 | 73d4dc71 | Anthony Liguori | if (n_entries) {
|
413 | 73d4dc71 | Anthony Liguori | const char *quark = g_quark_to_string(entries[0].accel_path_quark); |
414 | 73d4dc71 | Anthony Liguori | |
415 | 73d4dc71 | Anthony Liguori | if (gd_is_grab_active(s) && strstart(quark, "<QEMU>/File/", NULL)) { |
416 | 73d4dc71 | Anthony Liguori | propagate_accel = FALSE; |
417 | 73d4dc71 | Anthony Liguori | } |
418 | 73d4dc71 | Anthony Liguori | } |
419 | 73d4dc71 | Anthony Liguori | |
420 | 73d4dc71 | Anthony Liguori | if (!handled && propagate_accel) {
|
421 | 73d4dc71 | Anthony Liguori | handled = gtk_window_activate_key(GTK_WINDOW(widget), key); |
422 | 73d4dc71 | Anthony Liguori | } |
423 | 6db253ca | Jan Kiszka | if (handled) {
|
424 | 6db253ca | Jan Kiszka | gtk_release_modifiers(s); |
425 | 6db253ca | Jan Kiszka | } else {
|
426 | 73d4dc71 | Anthony Liguori | handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), key); |
427 | 73d4dc71 | Anthony Liguori | } |
428 | 73d4dc71 | Anthony Liguori | |
429 | 73d4dc71 | Anthony Liguori | return handled;
|
430 | 73d4dc71 | Anthony Liguori | } |
431 | 73d4dc71 | Anthony Liguori | |
432 | a4ccabcf | Anthony Liguori | static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event,
|
433 | a4ccabcf | Anthony Liguori | void *opaque)
|
434 | a4ccabcf | Anthony Liguori | { |
435 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = opaque; |
436 | a4ccabcf | Anthony Liguori | |
437 | a4ccabcf | Anthony Liguori | if (!no_quit) {
|
438 | 7c20b4a3 | Gerd Hoffmann | unregister_displaychangelistener(&s->dcl); |
439 | a4ccabcf | Anthony Liguori | qmp_quit(NULL);
|
440 | a4ccabcf | Anthony Liguori | return FALSE;
|
441 | a4ccabcf | Anthony Liguori | } |
442 | a4ccabcf | Anthony Liguori | |
443 | a4ccabcf | Anthony Liguori | return TRUE;
|
444 | a4ccabcf | Anthony Liguori | } |
445 | a4ccabcf | Anthony Liguori | |
446 | a4ccabcf | Anthony Liguori | static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque) |
447 | a4ccabcf | Anthony Liguori | { |
448 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = opaque; |
449 | c6158483 | Anthony Liguori | int mx, my;
|
450 | a4ccabcf | Anthony Liguori | int ww, wh;
|
451 | a4ccabcf | Anthony Liguori | int fbw, fbh;
|
452 | a4ccabcf | Anthony Liguori | |
453 | c6158483 | Anthony Liguori | if (!gtk_widget_get_realized(widget)) {
|
454 | c6158483 | Anthony Liguori | return FALSE;
|
455 | c6158483 | Anthony Liguori | } |
456 | c6158483 | Anthony Liguori | |
457 | 9d9801cf | Gerd Hoffmann | fbw = surface_width(s->ds); |
458 | 9d9801cf | Gerd Hoffmann | fbh = surface_height(s->ds); |
459 | a4ccabcf | Anthony Liguori | |
460 | a4ccabcf | Anthony Liguori | gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh); |
461 | a4ccabcf | Anthony Liguori | |
462 | c6158483 | Anthony Liguori | if (s->full_screen) {
|
463 | a4ccabcf | Anthony Liguori | s->scale_x = (double)ww / fbw;
|
464 | a4ccabcf | Anthony Liguori | s->scale_y = (double)wh / fbh;
|
465 | c6158483 | Anthony Liguori | } else if (s->free_scale) { |
466 | c6158483 | Anthony Liguori | double sx, sy;
|
467 | c6158483 | Anthony Liguori | |
468 | c6158483 | Anthony Liguori | sx = (double)ww / fbw;
|
469 | c6158483 | Anthony Liguori | sy = (double)wh / fbh;
|
470 | c6158483 | Anthony Liguori | |
471 | c6158483 | Anthony Liguori | s->scale_x = s->scale_y = MIN(sx, sy); |
472 | a4ccabcf | Anthony Liguori | } |
473 | a4ccabcf | Anthony Liguori | |
474 | 5104a1f6 | Anthony Liguori | fbw *= s->scale_x; |
475 | 5104a1f6 | Anthony Liguori | fbh *= s->scale_y; |
476 | 5104a1f6 | Anthony Liguori | |
477 | c6158483 | Anthony Liguori | mx = my = 0;
|
478 | c6158483 | Anthony Liguori | if (ww > fbw) {
|
479 | c6158483 | Anthony Liguori | mx = (ww - fbw) / 2;
|
480 | c6158483 | Anthony Liguori | } |
481 | c6158483 | Anthony Liguori | if (wh > fbh) {
|
482 | c6158483 | Anthony Liguori | my = (wh - fbh) / 2;
|
483 | c6158483 | Anthony Liguori | } |
484 | c6158483 | Anthony Liguori | |
485 | c6158483 | Anthony Liguori | cairo_rectangle(cr, 0, 0, ww, wh); |
486 | c6158483 | Anthony Liguori | |
487 | c6158483 | Anthony Liguori | /* Optionally cut out the inner area where the pixmap
|
488 | c6158483 | Anthony Liguori | will be drawn. This avoids 'flashing' since we're
|
489 | c6158483 | Anthony Liguori | not double-buffering. Note we're using the undocumented
|
490 | c6158483 | Anthony Liguori | behaviour of drawing the rectangle from right to left
|
491 | c6158483 | Anthony Liguori | to cut out the whole */
|
492 | c6158483 | Anthony Liguori | cairo_rectangle(cr, mx + fbw, my, |
493 | c6158483 | Anthony Liguori | -1 * fbw, fbh);
|
494 | c6158483 | Anthony Liguori | cairo_fill(cr); |
495 | c6158483 | Anthony Liguori | |
496 | c6158483 | Anthony Liguori | cairo_scale(cr, s->scale_x, s->scale_y); |
497 | c6158483 | Anthony Liguori | cairo_set_source_surface(cr, s->surface, mx / s->scale_x, my / s->scale_y); |
498 | a4ccabcf | Anthony Liguori | cairo_paint(cr); |
499 | a4ccabcf | Anthony Liguori | |
500 | a4ccabcf | Anthony Liguori | return TRUE;
|
501 | a4ccabcf | Anthony Liguori | } |
502 | a4ccabcf | Anthony Liguori | |
503 | fe43bca8 | Daniel P. Berrange | #if !GTK_CHECK_VERSION(3, 0, 0) |
504 | a4ccabcf | Anthony Liguori | static gboolean gd_expose_event(GtkWidget *widget, GdkEventExpose *expose,
|
505 | a4ccabcf | Anthony Liguori | void *opaque)
|
506 | a4ccabcf | Anthony Liguori | { |
507 | a4ccabcf | Anthony Liguori | cairo_t *cr; |
508 | a4ccabcf | Anthony Liguori | gboolean ret; |
509 | a4ccabcf | Anthony Liguori | |
510 | a4ccabcf | Anthony Liguori | cr = gdk_cairo_create(gtk_widget_get_window(widget)); |
511 | a4ccabcf | Anthony Liguori | cairo_rectangle(cr, |
512 | a4ccabcf | Anthony Liguori | expose->area.x, |
513 | a4ccabcf | Anthony Liguori | expose->area.y, |
514 | a4ccabcf | Anthony Liguori | expose->area.width, |
515 | a4ccabcf | Anthony Liguori | expose->area.height); |
516 | a4ccabcf | Anthony Liguori | cairo_clip(cr); |
517 | a4ccabcf | Anthony Liguori | |
518 | a4ccabcf | Anthony Liguori | ret = gd_draw_event(widget, cr, opaque); |
519 | a4ccabcf | Anthony Liguori | |
520 | a4ccabcf | Anthony Liguori | cairo_destroy(cr); |
521 | a4ccabcf | Anthony Liguori | |
522 | a4ccabcf | Anthony Liguori | return ret;
|
523 | a4ccabcf | Anthony Liguori | } |
524 | fe43bca8 | Daniel P. Berrange | #endif
|
525 | a4ccabcf | Anthony Liguori | |
526 | a4ccabcf | Anthony Liguori | static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
|
527 | a4ccabcf | Anthony Liguori | void *opaque)
|
528 | a4ccabcf | Anthony Liguori | { |
529 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = opaque; |
530 | a4ccabcf | Anthony Liguori | int dx, dy;
|
531 | a4ccabcf | Anthony Liguori | int x, y;
|
532 | c6158483 | Anthony Liguori | int mx, my;
|
533 | c6158483 | Anthony Liguori | int fbh, fbw;
|
534 | c6158483 | Anthony Liguori | int ww, wh;
|
535 | c6158483 | Anthony Liguori | |
536 | 9d9801cf | Gerd Hoffmann | fbw = surface_width(s->ds) * s->scale_x; |
537 | 9d9801cf | Gerd Hoffmann | fbh = surface_height(s->ds) * s->scale_y; |
538 | a4ccabcf | Anthony Liguori | |
539 | c6158483 | Anthony Liguori | gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh); |
540 | c6158483 | Anthony Liguori | |
541 | c6158483 | Anthony Liguori | mx = my = 0;
|
542 | c6158483 | Anthony Liguori | if (ww > fbw) {
|
543 | c6158483 | Anthony Liguori | mx = (ww - fbw) / 2;
|
544 | c6158483 | Anthony Liguori | } |
545 | c6158483 | Anthony Liguori | if (wh > fbh) {
|
546 | c6158483 | Anthony Liguori | my = (wh - fbh) / 2;
|
547 | c6158483 | Anthony Liguori | } |
548 | c6158483 | Anthony Liguori | |
549 | c6158483 | Anthony Liguori | x = (motion->x - mx) / s->scale_x; |
550 | c6158483 | Anthony Liguori | y = (motion->y - my) / s->scale_y; |
551 | c6158483 | Anthony Liguori | |
552 | c6158483 | Anthony Liguori | if (x < 0 || y < 0 || |
553 | 9d9801cf | Gerd Hoffmann | x >= surface_width(s->ds) || |
554 | 9d9801cf | Gerd Hoffmann | y >= surface_height(s->ds)) { |
555 | c6158483 | Anthony Liguori | return TRUE;
|
556 | c6158483 | Anthony Liguori | } |
557 | a4ccabcf | Anthony Liguori | |
558 | a4ccabcf | Anthony Liguori | if (kbd_mouse_is_absolute()) {
|
559 | 9d9801cf | Gerd Hoffmann | dx = x * 0x7FFF / (surface_width(s->ds) - 1); |
560 | 9d9801cf | Gerd Hoffmann | dy = y * 0x7FFF / (surface_height(s->ds) - 1); |
561 | a4ccabcf | Anthony Liguori | } else if (s->last_x == -1 || s->last_y == -1) { |
562 | a4ccabcf | Anthony Liguori | dx = 0;
|
563 | a4ccabcf | Anthony Liguori | dy = 0;
|
564 | a4ccabcf | Anthony Liguori | } else {
|
565 | a4ccabcf | Anthony Liguori | dx = x - s->last_x; |
566 | a4ccabcf | Anthony Liguori | dy = y - s->last_y; |
567 | a4ccabcf | Anthony Liguori | } |
568 | a4ccabcf | Anthony Liguori | |
569 | a4ccabcf | Anthony Liguori | s->last_x = x; |
570 | a4ccabcf | Anthony Liguori | s->last_y = y; |
571 | a4ccabcf | Anthony Liguori | |
572 | 5104a1f6 | Anthony Liguori | if (kbd_mouse_is_absolute() || gd_is_grab_active(s)) {
|
573 | a4ccabcf | Anthony Liguori | kbd_mouse_event(dx, dy, 0, s->button_mask);
|
574 | a4ccabcf | Anthony Liguori | } |
575 | a4ccabcf | Anthony Liguori | |
576 | 5104a1f6 | Anthony Liguori | if (!kbd_mouse_is_absolute() && gd_is_grab_active(s)) {
|
577 | 66962f14 | Daniel P. Berrange | GdkScreen *screen = gtk_widget_get_screen(s->drawing_area); |
578 | 5104a1f6 | Anthony Liguori | int x = (int)motion->x_root; |
579 | 5104a1f6 | Anthony Liguori | int y = (int)motion->y_root; |
580 | 5104a1f6 | Anthony Liguori | |
581 | 5104a1f6 | Anthony Liguori | /* In relative mode check to see if client pointer hit
|
582 | 5104a1f6 | Anthony Liguori | * one of the screen edges, and if so move it back by
|
583 | 5104a1f6 | Anthony Liguori | * 200 pixels. This is important because the pointer
|
584 | 5104a1f6 | Anthony Liguori | * in the server doesn't correspond 1-for-1, and so
|
585 | 5104a1f6 | Anthony Liguori | * may still be only half way across the screen. Without
|
586 | 5104a1f6 | Anthony Liguori | * this warp, the server pointer would thus appear to hit
|
587 | 5104a1f6 | Anthony Liguori | * an invisible wall */
|
588 | 5104a1f6 | Anthony Liguori | if (x == 0) { |
589 | 5104a1f6 | Anthony Liguori | x += 200;
|
590 | 5104a1f6 | Anthony Liguori | } |
591 | 5104a1f6 | Anthony Liguori | if (y == 0) { |
592 | 5104a1f6 | Anthony Liguori | y += 200;
|
593 | 5104a1f6 | Anthony Liguori | } |
594 | 5104a1f6 | Anthony Liguori | if (x == (gdk_screen_get_width(screen) - 1)) { |
595 | 5104a1f6 | Anthony Liguori | x -= 200;
|
596 | 5104a1f6 | Anthony Liguori | } |
597 | 5104a1f6 | Anthony Liguori | if (y == (gdk_screen_get_height(screen) - 1)) { |
598 | 5104a1f6 | Anthony Liguori | y -= 200;
|
599 | 5104a1f6 | Anthony Liguori | } |
600 | 5104a1f6 | Anthony Liguori | |
601 | 5104a1f6 | Anthony Liguori | if (x != (int)motion->x_root || y != (int)motion->y_root) { |
602 | 8906de76 | Daniel P. Berrange | #if GTK_CHECK_VERSION(3, 0, 0) |
603 | 8906de76 | Daniel P. Berrange | GdkDevice *dev = gdk_event_get_device((GdkEvent *)motion); |
604 | 8906de76 | Daniel P. Berrange | gdk_device_warp(dev, screen, x, y); |
605 | 8906de76 | Daniel P. Berrange | #else
|
606 | 8906de76 | Daniel P. Berrange | GdkDisplay *display = gtk_widget_get_display(widget); |
607 | 5104a1f6 | Anthony Liguori | gdk_display_warp_pointer(display, screen, x, y); |
608 | 8906de76 | Daniel P. Berrange | #endif
|
609 | 5104a1f6 | Anthony Liguori | s->last_x = -1;
|
610 | 5104a1f6 | Anthony Liguori | s->last_y = -1;
|
611 | 5104a1f6 | Anthony Liguori | return FALSE;
|
612 | 5104a1f6 | Anthony Liguori | } |
613 | 5104a1f6 | Anthony Liguori | } |
614 | a4ccabcf | Anthony Liguori | return TRUE;
|
615 | a4ccabcf | Anthony Liguori | } |
616 | a4ccabcf | Anthony Liguori | |
617 | a4ccabcf | Anthony Liguori | static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
|
618 | a4ccabcf | Anthony Liguori | void *opaque)
|
619 | a4ccabcf | Anthony Liguori | { |
620 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = opaque; |
621 | a4ccabcf | Anthony Liguori | int dx, dy;
|
622 | a4ccabcf | Anthony Liguori | int n;
|
623 | a4ccabcf | Anthony Liguori | |
624 | a4ccabcf | Anthony Liguori | if (button->button == 1) { |
625 | a4ccabcf | Anthony Liguori | n = 0x01;
|
626 | a4ccabcf | Anthony Liguori | } else if (button->button == 2) { |
627 | a4ccabcf | Anthony Liguori | n = 0x04;
|
628 | a4ccabcf | Anthony Liguori | } else if (button->button == 3) { |
629 | a4ccabcf | Anthony Liguori | n = 0x02;
|
630 | a4ccabcf | Anthony Liguori | } else {
|
631 | a4ccabcf | Anthony Liguori | n = 0x00;
|
632 | a4ccabcf | Anthony Liguori | } |
633 | a4ccabcf | Anthony Liguori | |
634 | a4ccabcf | Anthony Liguori | if (button->type == GDK_BUTTON_PRESS) {
|
635 | a4ccabcf | Anthony Liguori | s->button_mask |= n; |
636 | a4ccabcf | Anthony Liguori | } else if (button->type == GDK_BUTTON_RELEASE) { |
637 | a4ccabcf | Anthony Liguori | s->button_mask &= ~n; |
638 | a4ccabcf | Anthony Liguori | } |
639 | a4ccabcf | Anthony Liguori | |
640 | a4ccabcf | Anthony Liguori | if (kbd_mouse_is_absolute()) {
|
641 | 9d9801cf | Gerd Hoffmann | dx = s->last_x * 0x7FFF / (surface_width(s->ds) - 1); |
642 | 9d9801cf | Gerd Hoffmann | dy = s->last_y * 0x7FFF / (surface_height(s->ds) - 1); |
643 | a4ccabcf | Anthony Liguori | } else {
|
644 | a4ccabcf | Anthony Liguori | dx = 0;
|
645 | a4ccabcf | Anthony Liguori | dy = 0;
|
646 | a4ccabcf | Anthony Liguori | } |
647 | a4ccabcf | Anthony Liguori | |
648 | a4ccabcf | Anthony Liguori | kbd_mouse_event(dx, dy, 0, s->button_mask);
|
649 | a4ccabcf | Anthony Liguori | |
650 | a4ccabcf | Anthony Liguori | return TRUE;
|
651 | a4ccabcf | Anthony Liguori | } |
652 | a4ccabcf | Anthony Liguori | |
653 | a4ccabcf | Anthony Liguori | static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque) |
654 | a4ccabcf | Anthony Liguori | { |
655 | 6db253ca | Jan Kiszka | GtkDisplayState *s = opaque; |
656 | a4ccabcf | Anthony Liguori | int gdk_keycode;
|
657 | a4ccabcf | Anthony Liguori | int qemu_keycode;
|
658 | 6db253ca | Jan Kiszka | int i;
|
659 | a4ccabcf | Anthony Liguori | |
660 | a4ccabcf | Anthony Liguori | gdk_keycode = key->hardware_keycode; |
661 | a4ccabcf | Anthony Liguori | |
662 | a4ccabcf | Anthony Liguori | if (gdk_keycode < 9) { |
663 | a4ccabcf | Anthony Liguori | qemu_keycode = 0;
|
664 | a4ccabcf | Anthony Liguori | } else if (gdk_keycode < 97) { |
665 | a4ccabcf | Anthony Liguori | qemu_keycode = gdk_keycode - 8;
|
666 | a4ccabcf | Anthony Liguori | } else if (gdk_keycode < 158) { |
667 | a4ccabcf | Anthony Liguori | qemu_keycode = translate_evdev_keycode(gdk_keycode - 97);
|
668 | a4ccabcf | Anthony Liguori | } else if (gdk_keycode == 208) { /* Hiragana_Katakana */ |
669 | a4ccabcf | Anthony Liguori | qemu_keycode = 0x70;
|
670 | a4ccabcf | Anthony Liguori | } else if (gdk_keycode == 211) { /* backslash */ |
671 | a4ccabcf | Anthony Liguori | qemu_keycode = 0x73;
|
672 | a4ccabcf | Anthony Liguori | } else {
|
673 | a4ccabcf | Anthony Liguori | qemu_keycode = 0;
|
674 | a4ccabcf | Anthony Liguori | } |
675 | a4ccabcf | Anthony Liguori | |
676 | a4ccabcf | Anthony Liguori | DPRINTF("translated GDK keycode %d to QEMU keycode %d (%s)\n",
|
677 | a4ccabcf | Anthony Liguori | gdk_keycode, qemu_keycode, |
678 | a4ccabcf | Anthony Liguori | (key->type == GDK_KEY_PRESS) ? "down" : "up"); |
679 | a4ccabcf | Anthony Liguori | |
680 | 6db253ca | Jan Kiszka | for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) { |
681 | 6db253ca | Jan Kiszka | if (qemu_keycode == modifier_keycode[i]) {
|
682 | 6db253ca | Jan Kiszka | s->modifier_pressed[i] = (key->type == GDK_KEY_PRESS); |
683 | 6db253ca | Jan Kiszka | } |
684 | 6db253ca | Jan Kiszka | } |
685 | 6db253ca | Jan Kiszka | |
686 | a4ccabcf | Anthony Liguori | if (qemu_keycode & SCANCODE_GREY) {
|
687 | a4ccabcf | Anthony Liguori | kbd_put_keycode(SCANCODE_EMUL0); |
688 | a4ccabcf | Anthony Liguori | } |
689 | a4ccabcf | Anthony Liguori | |
690 | a4ccabcf | Anthony Liguori | if (key->type == GDK_KEY_PRESS) {
|
691 | a4ccabcf | Anthony Liguori | kbd_put_keycode(qemu_keycode & SCANCODE_KEYCODEMASK); |
692 | a4ccabcf | Anthony Liguori | } else if (key->type == GDK_KEY_RELEASE) { |
693 | a4ccabcf | Anthony Liguori | kbd_put_keycode(qemu_keycode | SCANCODE_UP); |
694 | a4ccabcf | Anthony Liguori | } else {
|
695 | a4ccabcf | Anthony Liguori | g_assert_not_reached(); |
696 | a4ccabcf | Anthony Liguori | } |
697 | a4ccabcf | Anthony Liguori | |
698 | a4ccabcf | Anthony Liguori | return TRUE;
|
699 | a4ccabcf | Anthony Liguori | } |
700 | a4ccabcf | Anthony Liguori | |
701 | a4ccabcf | Anthony Liguori | /** Window Menu Actions **/
|
702 | a4ccabcf | Anthony Liguori | |
703 | 30e8f22b | Jan Kiszka | static void gd_menu_pause(GtkMenuItem *item, void *opaque) |
704 | 30e8f22b | Jan Kiszka | { |
705 | 30e8f22b | Jan Kiszka | GtkDisplayState *s = opaque; |
706 | 30e8f22b | Jan Kiszka | |
707 | 30e8f22b | Jan Kiszka | if (s->external_pause_update) {
|
708 | 30e8f22b | Jan Kiszka | return;
|
709 | 30e8f22b | Jan Kiszka | } |
710 | 30e8f22b | Jan Kiszka | if (runstate_is_running()) {
|
711 | 30e8f22b | Jan Kiszka | qmp_stop(NULL);
|
712 | 30e8f22b | Jan Kiszka | } else {
|
713 | 30e8f22b | Jan Kiszka | qmp_cont(NULL);
|
714 | 30e8f22b | Jan Kiszka | } |
715 | 30e8f22b | Jan Kiszka | } |
716 | 30e8f22b | Jan Kiszka | |
717 | 30e8f22b | Jan Kiszka | static void gd_menu_reset(GtkMenuItem *item, void *opaque) |
718 | 30e8f22b | Jan Kiszka | { |
719 | 30e8f22b | Jan Kiszka | qmp_system_reset(NULL);
|
720 | 30e8f22b | Jan Kiszka | } |
721 | 30e8f22b | Jan Kiszka | |
722 | 30e8f22b | Jan Kiszka | static void gd_menu_powerdown(GtkMenuItem *item, void *opaque) |
723 | 30e8f22b | Jan Kiszka | { |
724 | 30e8f22b | Jan Kiszka | qmp_system_powerdown(NULL);
|
725 | 30e8f22b | Jan Kiszka | } |
726 | 30e8f22b | Jan Kiszka | |
727 | a4ccabcf | Anthony Liguori | static void gd_menu_quit(GtkMenuItem *item, void *opaque) |
728 | a4ccabcf | Anthony Liguori | { |
729 | a4ccabcf | Anthony Liguori | qmp_quit(NULL);
|
730 | a4ccabcf | Anthony Liguori | } |
731 | a4ccabcf | Anthony Liguori | |
732 | a4ccabcf | Anthony Liguori | static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque) |
733 | a4ccabcf | Anthony Liguori | { |
734 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = opaque; |
735 | a4ccabcf | Anthony Liguori | |
736 | a4ccabcf | Anthony Liguori | if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vga_item))) {
|
737 | a4ccabcf | Anthony Liguori | gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), 0);
|
738 | d861def3 | Anthony Liguori | } else {
|
739 | d861def3 | Anthony Liguori | int i;
|
740 | d861def3 | Anthony Liguori | |
741 | 6db253ca | Jan Kiszka | gtk_release_modifiers(s); |
742 | d861def3 | Anthony Liguori | for (i = 0; i < s->nb_vcs; i++) { |
743 | d861def3 | Anthony Liguori | if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vc[i].menu_item))) {
|
744 | d861def3 | Anthony Liguori | gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), i + 1);
|
745 | d861def3 | Anthony Liguori | break;
|
746 | d861def3 | Anthony Liguori | } |
747 | d861def3 | Anthony Liguori | } |
748 | a4ccabcf | Anthony Liguori | } |
749 | a4ccabcf | Anthony Liguori | } |
750 | a4ccabcf | Anthony Liguori | |
751 | a4ccabcf | Anthony Liguori | static void gd_menu_show_tabs(GtkMenuItem *item, void *opaque) |
752 | a4ccabcf | Anthony Liguori | { |
753 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = opaque; |
754 | a4ccabcf | Anthony Liguori | |
755 | a4ccabcf | Anthony Liguori | if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->show_tabs_item))) {
|
756 | a4ccabcf | Anthony Liguori | gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), TRUE); |
757 | a4ccabcf | Anthony Liguori | } else {
|
758 | a4ccabcf | Anthony Liguori | gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE); |
759 | a4ccabcf | Anthony Liguori | } |
760 | a4ccabcf | Anthony Liguori | } |
761 | a4ccabcf | Anthony Liguori | |
762 | c6158483 | Anthony Liguori | static void gd_menu_full_screen(GtkMenuItem *item, void *opaque) |
763 | c6158483 | Anthony Liguori | { |
764 | c6158483 | Anthony Liguori | GtkDisplayState *s = opaque; |
765 | c6158483 | Anthony Liguori | |
766 | 10409282 | Stefan Weil | if (!s->full_screen) {
|
767 | c6158483 | Anthony Liguori | gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE); |
768 | c6158483 | Anthony Liguori | gtk_widget_set_size_request(s->menu_bar, 0, 0); |
769 | c6158483 | Anthony Liguori | gtk_widget_set_size_request(s->drawing_area, -1, -1); |
770 | c6158483 | Anthony Liguori | gtk_window_fullscreen(GTK_WINDOW(s->window)); |
771 | c6158483 | Anthony Liguori | if (gd_on_vga(s)) {
|
772 | c6158483 | Anthony Liguori | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), TRUE); |
773 | c6158483 | Anthony Liguori | } |
774 | c6158483 | Anthony Liguori | s->full_screen = TRUE; |
775 | c6158483 | Anthony Liguori | } else {
|
776 | c6158483 | Anthony Liguori | gtk_window_unfullscreen(GTK_WINDOW(s->window)); |
777 | c6158483 | Anthony Liguori | gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s); |
778 | c6158483 | Anthony Liguori | gtk_widget_set_size_request(s->menu_bar, -1, -1); |
779 | c6158483 | Anthony Liguori | gtk_widget_set_size_request(s->drawing_area, |
780 | 9d9801cf | Gerd Hoffmann | surface_width(s->ds), |
781 | 9d9801cf | Gerd Hoffmann | surface_height(s->ds)); |
782 | c6158483 | Anthony Liguori | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), FALSE); |
783 | c6158483 | Anthony Liguori | s->full_screen = FALSE; |
784 | c6158483 | Anthony Liguori | s->scale_x = 1.0; |
785 | c6158483 | Anthony Liguori | s->scale_y = 1.0; |
786 | c6158483 | Anthony Liguori | } |
787 | c6158483 | Anthony Liguori | |
788 | c6158483 | Anthony Liguori | gd_update_cursor(s, FALSE); |
789 | c6158483 | Anthony Liguori | } |
790 | c6158483 | Anthony Liguori | |
791 | c6158483 | Anthony Liguori | static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque) |
792 | c6158483 | Anthony Liguori | { |
793 | c6158483 | Anthony Liguori | GtkDisplayState *s = opaque; |
794 | c6158483 | Anthony Liguori | |
795 | c6158483 | Anthony Liguori | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item), |
796 | c6158483 | Anthony Liguori | FALSE); |
797 | c6158483 | Anthony Liguori | |
798 | c6158483 | Anthony Liguori | s->scale_x += .25;
|
799 | c6158483 | Anthony Liguori | s->scale_y += .25;
|
800 | c6158483 | Anthony Liguori | |
801 | 9d9801cf | Gerd Hoffmann | gd_update_windowsize(s); |
802 | c6158483 | Anthony Liguori | } |
803 | c6158483 | Anthony Liguori | |
804 | c6158483 | Anthony Liguori | static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) |
805 | c6158483 | Anthony Liguori | { |
806 | c6158483 | Anthony Liguori | GtkDisplayState *s = opaque; |
807 | c6158483 | Anthony Liguori | |
808 | c6158483 | Anthony Liguori | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item), |
809 | c6158483 | Anthony Liguori | FALSE); |
810 | c6158483 | Anthony Liguori | |
811 | c6158483 | Anthony Liguori | s->scale_x -= .25;
|
812 | c6158483 | Anthony Liguori | s->scale_y -= .25;
|
813 | c6158483 | Anthony Liguori | |
814 | c6158483 | Anthony Liguori | s->scale_x = MAX(s->scale_x, .25);
|
815 | c6158483 | Anthony Liguori | s->scale_y = MAX(s->scale_y, .25);
|
816 | c6158483 | Anthony Liguori | |
817 | 9d9801cf | Gerd Hoffmann | gd_update_windowsize(s); |
818 | c6158483 | Anthony Liguori | } |
819 | c6158483 | Anthony Liguori | |
820 | c6158483 | Anthony Liguori | static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque) |
821 | c6158483 | Anthony Liguori | { |
822 | c6158483 | Anthony Liguori | GtkDisplayState *s = opaque; |
823 | c6158483 | Anthony Liguori | |
824 | c6158483 | Anthony Liguori | s->scale_x = 1.0; |
825 | c6158483 | Anthony Liguori | s->scale_y = 1.0; |
826 | c6158483 | Anthony Liguori | |
827 | 9d9801cf | Gerd Hoffmann | gd_update_windowsize(s); |
828 | c6158483 | Anthony Liguori | } |
829 | c6158483 | Anthony Liguori | |
830 | c6158483 | Anthony Liguori | static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) |
831 | c6158483 | Anthony Liguori | { |
832 | c6158483 | Anthony Liguori | GtkDisplayState *s = opaque; |
833 | c6158483 | Anthony Liguori | |
834 | c6158483 | Anthony Liguori | if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item))) {
|
835 | c6158483 | Anthony Liguori | s->free_scale = TRUE; |
836 | c6158483 | Anthony Liguori | } else {
|
837 | c6158483 | Anthony Liguori | s->free_scale = FALSE; |
838 | c6158483 | Anthony Liguori | } |
839 | c6158483 | Anthony Liguori | |
840 | 9d9801cf | Gerd Hoffmann | gd_update_windowsize(s); |
841 | 9d9801cf | Gerd Hoffmann | gd_update_full_redraw(s); |
842 | c6158483 | Anthony Liguori | } |
843 | c6158483 | Anthony Liguori | |
844 | 5104a1f6 | Anthony Liguori | static void gd_grab_keyboard(GtkDisplayState *s) |
845 | 5104a1f6 | Anthony Liguori | { |
846 | 655199da | Daniel P. Berrange | #if GTK_CHECK_VERSION(3, 0, 0) |
847 | 655199da | Daniel P. Berrange | GdkDisplay *display = gtk_widget_get_display(s->drawing_area); |
848 | 655199da | Daniel P. Berrange | GdkDeviceManager *mgr = gdk_display_get_device_manager(display); |
849 | 655199da | Daniel P. Berrange | GList *devices = gdk_device_manager_list_devices(mgr, |
850 | 655199da | Daniel P. Berrange | GDK_DEVICE_TYPE_MASTER); |
851 | 655199da | Daniel P. Berrange | GList *tmp = devices; |
852 | 655199da | Daniel P. Berrange | while (tmp) {
|
853 | 655199da | Daniel P. Berrange | GdkDevice *dev = tmp->data; |
854 | 655199da | Daniel P. Berrange | if (gdk_device_get_source(dev) == GDK_SOURCE_KEYBOARD) {
|
855 | 655199da | Daniel P. Berrange | gdk_device_grab(dev, |
856 | 655199da | Daniel P. Berrange | gtk_widget_get_window(s->drawing_area), |
857 | 655199da | Daniel P. Berrange | GDK_OWNERSHIP_NONE, |
858 | 655199da | Daniel P. Berrange | FALSE, |
859 | 655199da | Daniel P. Berrange | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, |
860 | 655199da | Daniel P. Berrange | NULL,
|
861 | 655199da | Daniel P. Berrange | GDK_CURRENT_TIME); |
862 | 655199da | Daniel P. Berrange | } |
863 | 655199da | Daniel P. Berrange | tmp = tmp->next; |
864 | 655199da | Daniel P. Berrange | } |
865 | 655199da | Daniel P. Berrange | g_list_free(devices); |
866 | 655199da | Daniel P. Berrange | #else
|
867 | 655199da | Daniel P. Berrange | gdk_keyboard_grab(gtk_widget_get_window(s->drawing_area), |
868 | 5104a1f6 | Anthony Liguori | FALSE, |
869 | 5104a1f6 | Anthony Liguori | GDK_CURRENT_TIME); |
870 | 655199da | Daniel P. Berrange | #endif
|
871 | 5104a1f6 | Anthony Liguori | } |
872 | 5104a1f6 | Anthony Liguori | |
873 | 5104a1f6 | Anthony Liguori | static void gd_ungrab_keyboard(GtkDisplayState *s) |
874 | 5104a1f6 | Anthony Liguori | { |
875 | 655199da | Daniel P. Berrange | #if GTK_CHECK_VERSION(3, 0, 0) |
876 | 655199da | Daniel P. Berrange | GdkDisplay *display = gtk_widget_get_display(s->drawing_area); |
877 | 655199da | Daniel P. Berrange | GdkDeviceManager *mgr = gdk_display_get_device_manager(display); |
878 | 655199da | Daniel P. Berrange | GList *devices = gdk_device_manager_list_devices(mgr, |
879 | 655199da | Daniel P. Berrange | GDK_DEVICE_TYPE_MASTER); |
880 | 655199da | Daniel P. Berrange | GList *tmp = devices; |
881 | 655199da | Daniel P. Berrange | while (tmp) {
|
882 | 655199da | Daniel P. Berrange | GdkDevice *dev = tmp->data; |
883 | 655199da | Daniel P. Berrange | if (gdk_device_get_source(dev) == GDK_SOURCE_KEYBOARD) {
|
884 | 655199da | Daniel P. Berrange | gdk_device_ungrab(dev, |
885 | 655199da | Daniel P. Berrange | GDK_CURRENT_TIME); |
886 | 655199da | Daniel P. Berrange | } |
887 | 655199da | Daniel P. Berrange | tmp = tmp->next; |
888 | 655199da | Daniel P. Berrange | } |
889 | 655199da | Daniel P. Berrange | g_list_free(devices); |
890 | 655199da | Daniel P. Berrange | #else
|
891 | 5104a1f6 | Anthony Liguori | gdk_keyboard_ungrab(GDK_CURRENT_TIME); |
892 | 655199da | Daniel P. Berrange | #endif
|
893 | 5104a1f6 | Anthony Liguori | } |
894 | 5104a1f6 | Anthony Liguori | |
895 | 2a05485d | Daniel P. Berrange | static void gd_grab_pointer(GtkDisplayState *s) |
896 | 2a05485d | Daniel P. Berrange | { |
897 | 2a05485d | Daniel P. Berrange | #if GTK_CHECK_VERSION(3, 0, 0) |
898 | 2a05485d | Daniel P. Berrange | GdkDisplay *display = gtk_widget_get_display(s->drawing_area); |
899 | 2a05485d | Daniel P. Berrange | GdkDeviceManager *mgr = gdk_display_get_device_manager(display); |
900 | 2a05485d | Daniel P. Berrange | GList *devices = gdk_device_manager_list_devices(mgr, |
901 | 2a05485d | Daniel P. Berrange | GDK_DEVICE_TYPE_MASTER); |
902 | 2a05485d | Daniel P. Berrange | GList *tmp = devices; |
903 | 2a05485d | Daniel P. Berrange | while (tmp) {
|
904 | 2a05485d | Daniel P. Berrange | GdkDevice *dev = tmp->data; |
905 | 2a05485d | Daniel P. Berrange | if (gdk_device_get_source(dev) == GDK_SOURCE_MOUSE) {
|
906 | 2a05485d | Daniel P. Berrange | gdk_device_grab(dev, |
907 | 2a05485d | Daniel P. Berrange | gtk_widget_get_window(s->drawing_area), |
908 | 2a05485d | Daniel P. Berrange | GDK_OWNERSHIP_NONE, |
909 | 2a05485d | Daniel P. Berrange | FALSE, /* All events to come to our
|
910 | 2a05485d | Daniel P. Berrange | window directly */
|
911 | 2a05485d | Daniel P. Berrange | GDK_POINTER_MOTION_MASK | |
912 | 2a05485d | Daniel P. Berrange | GDK_BUTTON_PRESS_MASK | |
913 | 2a05485d | Daniel P. Berrange | GDK_BUTTON_RELEASE_MASK | |
914 | 2a05485d | Daniel P. Berrange | GDK_BUTTON_MOTION_MASK | |
915 | 2a05485d | Daniel P. Berrange | GDK_SCROLL_MASK, |
916 | 2a05485d | Daniel P. Berrange | s->null_cursor, |
917 | 2a05485d | Daniel P. Berrange | GDK_CURRENT_TIME); |
918 | 2a05485d | Daniel P. Berrange | } |
919 | 2a05485d | Daniel P. Berrange | tmp = tmp->next; |
920 | 2a05485d | Daniel P. Berrange | } |
921 | 2a05485d | Daniel P. Berrange | g_list_free(devices); |
922 | 2a05485d | Daniel P. Berrange | #else
|
923 | 2a05485d | Daniel P. Berrange | gdk_pointer_grab(gtk_widget_get_window(s->drawing_area), |
924 | 2a05485d | Daniel P. Berrange | FALSE, /* All events to come to our window directly */
|
925 | 2a05485d | Daniel P. Berrange | GDK_POINTER_MOTION_MASK | |
926 | 2a05485d | Daniel P. Berrange | GDK_BUTTON_PRESS_MASK | |
927 | 2a05485d | Daniel P. Berrange | GDK_BUTTON_RELEASE_MASK | |
928 | 2a05485d | Daniel P. Berrange | GDK_BUTTON_MOTION_MASK | |
929 | 2a05485d | Daniel P. Berrange | GDK_SCROLL_MASK, |
930 | 2a05485d | Daniel P. Berrange | NULL, /* Allow cursor to move over entire desktop */ |
931 | 2a05485d | Daniel P. Berrange | s->null_cursor, |
932 | 2a05485d | Daniel P. Berrange | GDK_CURRENT_TIME); |
933 | 2a05485d | Daniel P. Berrange | #endif
|
934 | 2a05485d | Daniel P. Berrange | } |
935 | 2a05485d | Daniel P. Berrange | |
936 | 2a05485d | Daniel P. Berrange | static void gd_ungrab_pointer(GtkDisplayState *s) |
937 | 2a05485d | Daniel P. Berrange | { |
938 | 2a05485d | Daniel P. Berrange | #if GTK_CHECK_VERSION(3, 0, 0) |
939 | 2a05485d | Daniel P. Berrange | GdkDisplay *display = gtk_widget_get_display(s->drawing_area); |
940 | 2a05485d | Daniel P. Berrange | GdkDeviceManager *mgr = gdk_display_get_device_manager(display); |
941 | 2a05485d | Daniel P. Berrange | GList *devices = gdk_device_manager_list_devices(mgr, |
942 | 2a05485d | Daniel P. Berrange | GDK_DEVICE_TYPE_MASTER); |
943 | 2a05485d | Daniel P. Berrange | GList *tmp = devices; |
944 | 2a05485d | Daniel P. Berrange | while (tmp) {
|
945 | 2a05485d | Daniel P. Berrange | GdkDevice *dev = tmp->data; |
946 | 2a05485d | Daniel P. Berrange | if (gdk_device_get_source(dev) == GDK_SOURCE_MOUSE) {
|
947 | 2a05485d | Daniel P. Berrange | gdk_device_ungrab(dev, |
948 | 2a05485d | Daniel P. Berrange | GDK_CURRENT_TIME); |
949 | 2a05485d | Daniel P. Berrange | } |
950 | 2a05485d | Daniel P. Berrange | tmp = tmp->next; |
951 | 2a05485d | Daniel P. Berrange | } |
952 | 2a05485d | Daniel P. Berrange | g_list_free(devices); |
953 | 2a05485d | Daniel P. Berrange | #else
|
954 | 2a05485d | Daniel P. Berrange | gdk_pointer_ungrab(GDK_CURRENT_TIME); |
955 | 2a05485d | Daniel P. Berrange | #endif
|
956 | 2a05485d | Daniel P. Berrange | } |
957 | 2a05485d | Daniel P. Berrange | |
958 | 5104a1f6 | Anthony Liguori | static void gd_menu_grab_input(GtkMenuItem *item, void *opaque) |
959 | 5104a1f6 | Anthony Liguori | { |
960 | 5104a1f6 | Anthony Liguori | GtkDisplayState *s = opaque; |
961 | 5104a1f6 | Anthony Liguori | |
962 | 5104a1f6 | Anthony Liguori | if (gd_is_grab_active(s)) {
|
963 | 5104a1f6 | Anthony Liguori | gd_grab_keyboard(s); |
964 | 2a05485d | Daniel P. Berrange | gd_grab_pointer(s); |
965 | 5104a1f6 | Anthony Liguori | } else {
|
966 | 5104a1f6 | Anthony Liguori | gd_ungrab_keyboard(s); |
967 | 2a05485d | Daniel P. Berrange | gd_ungrab_pointer(s); |
968 | 5104a1f6 | Anthony Liguori | } |
969 | 5104a1f6 | Anthony Liguori | |
970 | 5104a1f6 | Anthony Liguori | gd_update_caption(s); |
971 | 5104a1f6 | Anthony Liguori | gd_update_cursor(s, FALSE); |
972 | 5104a1f6 | Anthony Liguori | } |
973 | 5104a1f6 | Anthony Liguori | |
974 | a4ccabcf | Anthony Liguori | static void gd_change_page(GtkNotebook *nb, gpointer arg1, guint arg2, |
975 | a4ccabcf | Anthony Liguori | gpointer data) |
976 | a4ccabcf | Anthony Liguori | { |
977 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = data; |
978 | d861def3 | Anthony Liguori | guint last_page; |
979 | 5104a1f6 | Anthony Liguori | gboolean on_vga; |
980 | a4ccabcf | Anthony Liguori | |
981 | a4ccabcf | Anthony Liguori | if (!gtk_widget_get_realized(s->notebook)) {
|
982 | a4ccabcf | Anthony Liguori | return;
|
983 | a4ccabcf | Anthony Liguori | } |
984 | a4ccabcf | Anthony Liguori | |
985 | d861def3 | Anthony Liguori | last_page = gtk_notebook_get_current_page(nb); |
986 | d861def3 | Anthony Liguori | |
987 | d861def3 | Anthony Liguori | if (last_page) {
|
988 | d861def3 | Anthony Liguori | gtk_widget_set_size_request(s->vc[last_page - 1].terminal, -1, -1); |
989 | d861def3 | Anthony Liguori | } |
990 | d861def3 | Anthony Liguori | |
991 | 5104a1f6 | Anthony Liguori | on_vga = arg2 == 0;
|
992 | 5104a1f6 | Anthony Liguori | |
993 | 5104a1f6 | Anthony Liguori | if (!on_vga) {
|
994 | 5104a1f6 | Anthony Liguori | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), |
995 | 5104a1f6 | Anthony Liguori | FALSE); |
996 | c6158483 | Anthony Liguori | } else if (s->full_screen) { |
997 | c6158483 | Anthony Liguori | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), |
998 | c6158483 | Anthony Liguori | TRUE); |
999 | 5104a1f6 | Anthony Liguori | } |
1000 | 5104a1f6 | Anthony Liguori | |
1001 | d861def3 | Anthony Liguori | if (arg2 == 0) { |
1002 | d861def3 | Anthony Liguori | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->vga_item), TRUE); |
1003 | d861def3 | Anthony Liguori | } else {
|
1004 | d861def3 | Anthony Liguori | VirtualConsole *vc = &s->vc[arg2 - 1];
|
1005 | d861def3 | Anthony Liguori | VteTerminal *term = VTE_TERMINAL(vc->terminal); |
1006 | d861def3 | Anthony Liguori | int width, height;
|
1007 | d861def3 | Anthony Liguori | |
1008 | d861def3 | Anthony Liguori | width = 80 * vte_terminal_get_char_width(term);
|
1009 | d861def3 | Anthony Liguori | height = 25 * vte_terminal_get_char_height(term);
|
1010 | d861def3 | Anthony Liguori | |
1011 | d861def3 | Anthony Liguori | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(vc->menu_item), TRUE); |
1012 | d861def3 | Anthony Liguori | gtk_widget_set_size_request(vc->terminal, width, height); |
1013 | d861def3 | Anthony Liguori | } |
1014 | d861def3 | Anthony Liguori | |
1015 | 5104a1f6 | Anthony Liguori | gtk_widget_set_sensitive(s->grab_item, on_vga); |
1016 | 5104a1f6 | Anthony Liguori | |
1017 | a4ccabcf | Anthony Liguori | gd_update_cursor(s, TRUE); |
1018 | a4ccabcf | Anthony Liguori | } |
1019 | a4ccabcf | Anthony Liguori | |
1020 | 5104a1f6 | Anthony Liguori | static gboolean gd_enter_event(GtkWidget *widget, GdkEventCrossing *crossing, gpointer data)
|
1021 | 5104a1f6 | Anthony Liguori | { |
1022 | 5104a1f6 | Anthony Liguori | GtkDisplayState *s = data; |
1023 | 5104a1f6 | Anthony Liguori | |
1024 | 5104a1f6 | Anthony Liguori | if (!gd_is_grab_active(s) && gd_grab_on_hover(s)) {
|
1025 | 5104a1f6 | Anthony Liguori | gd_grab_keyboard(s); |
1026 | 5104a1f6 | Anthony Liguori | } |
1027 | 5104a1f6 | Anthony Liguori | |
1028 | 5104a1f6 | Anthony Liguori | return TRUE;
|
1029 | 5104a1f6 | Anthony Liguori | } |
1030 | 5104a1f6 | Anthony Liguori | |
1031 | 5104a1f6 | Anthony Liguori | static gboolean gd_leave_event(GtkWidget *widget, GdkEventCrossing *crossing, gpointer data)
|
1032 | 5104a1f6 | Anthony Liguori | { |
1033 | 5104a1f6 | Anthony Liguori | GtkDisplayState *s = data; |
1034 | 5104a1f6 | Anthony Liguori | |
1035 | 5104a1f6 | Anthony Liguori | if (!gd_is_grab_active(s) && gd_grab_on_hover(s)) {
|
1036 | 5104a1f6 | Anthony Liguori | gd_ungrab_keyboard(s); |
1037 | 5104a1f6 | Anthony Liguori | } |
1038 | 5104a1f6 | Anthony Liguori | |
1039 | 5104a1f6 | Anthony Liguori | return TRUE;
|
1040 | 5104a1f6 | Anthony Liguori | } |
1041 | 5104a1f6 | Anthony Liguori | |
1042 | 6db253ca | Jan Kiszka | static gboolean gd_focus_out_event(GtkWidget *widget,
|
1043 | 6db253ca | Jan Kiszka | GdkEventCrossing *crossing, gpointer data) |
1044 | 6db253ca | Jan Kiszka | { |
1045 | 6db253ca | Jan Kiszka | GtkDisplayState *s = data; |
1046 | 6db253ca | Jan Kiszka | |
1047 | 6db253ca | Jan Kiszka | gtk_release_modifiers(s); |
1048 | 6db253ca | Jan Kiszka | |
1049 | 6db253ca | Jan Kiszka | return TRUE;
|
1050 | 6db253ca | Jan Kiszka | } |
1051 | 6db253ca | Jan Kiszka | |
1052 | d861def3 | Anthony Liguori | /** Virtual Console Callbacks **/
|
1053 | d861def3 | Anthony Liguori | |
1054 | d861def3 | Anthony Liguori | static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len) |
1055 | d861def3 | Anthony Liguori | { |
1056 | d861def3 | Anthony Liguori | VirtualConsole *vc = chr->opaque; |
1057 | d861def3 | Anthony Liguori | |
1058 | d861def3 | Anthony Liguori | return write(vc->fd, buf, len);
|
1059 | d861def3 | Anthony Liguori | } |
1060 | d861def3 | Anthony Liguori | |
1061 | d861def3 | Anthony Liguori | static int nb_vcs; |
1062 | d861def3 | Anthony Liguori | static CharDriverState *vcs[MAX_VCS];
|
1063 | d861def3 | Anthony Liguori | |
1064 | 702ec69c | Gerd Hoffmann | static CharDriverState *gd_vc_handler(ChardevVC *unused)
|
1065 | d861def3 | Anthony Liguori | { |
1066 | d861def3 | Anthony Liguori | CharDriverState *chr; |
1067 | d861def3 | Anthony Liguori | |
1068 | d861def3 | Anthony Liguori | chr = g_malloc0(sizeof(*chr));
|
1069 | d861def3 | Anthony Liguori | chr->chr_write = gd_vc_chr_write; |
1070 | d861def3 | Anthony Liguori | |
1071 | d861def3 | Anthony Liguori | vcs[nb_vcs++] = chr; |
1072 | d861def3 | Anthony Liguori | |
1073 | d861def3 | Anthony Liguori | return chr;
|
1074 | d861def3 | Anthony Liguori | } |
1075 | d861def3 | Anthony Liguori | |
1076 | a4ccabcf | Anthony Liguori | void early_gtk_display_init(void) |
1077 | a4ccabcf | Anthony Liguori | { |
1078 | d861def3 | Anthony Liguori | register_vc_handler(gd_vc_handler); |
1079 | d861def3 | Anthony Liguori | } |
1080 | d861def3 | Anthony Liguori | |
1081 | d861def3 | Anthony Liguori | static gboolean gd_vc_in(GIOChannel *chan, GIOCondition cond, void *opaque) |
1082 | d861def3 | Anthony Liguori | { |
1083 | d861def3 | Anthony Liguori | VirtualConsole *vc = opaque; |
1084 | d861def3 | Anthony Liguori | uint8_t buffer[1024];
|
1085 | d861def3 | Anthony Liguori | ssize_t len; |
1086 | d861def3 | Anthony Liguori | |
1087 | d861def3 | Anthony Liguori | len = read(vc->fd, buffer, sizeof(buffer));
|
1088 | d861def3 | Anthony Liguori | if (len <= 0) { |
1089 | d861def3 | Anthony Liguori | return FALSE;
|
1090 | d861def3 | Anthony Liguori | } |
1091 | d861def3 | Anthony Liguori | |
1092 | d861def3 | Anthony Liguori | qemu_chr_be_write(vc->chr, buffer, len); |
1093 | d861def3 | Anthony Liguori | |
1094 | d861def3 | Anthony Liguori | return TRUE;
|
1095 | d861def3 | Anthony Liguori | } |
1096 | d861def3 | Anthony Liguori | |
1097 | d861def3 | Anthony Liguori | static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSList *group) |
1098 | d861def3 | Anthony Liguori | { |
1099 | d861def3 | Anthony Liguori | const char *label; |
1100 | d861def3 | Anthony Liguori | char buffer[32]; |
1101 | d861def3 | Anthony Liguori | char path[32]; |
1102 | 28d2e5b2 | Stefan Weil | #if VTE_CHECK_VERSION(0, 26, 0) |
1103 | d861def3 | Anthony Liguori | VtePty *pty; |
1104 | 28d2e5b2 | Stefan Weil | #endif
|
1105 | d861def3 | Anthony Liguori | GIOChannel *chan; |
1106 | d861def3 | Anthony Liguori | GtkWidget *scrolled_window; |
1107 | d861def3 | Anthony Liguori | GtkAdjustment *vadjustment; |
1108 | d861def3 | Anthony Liguori | int master_fd, slave_fd, ret;
|
1109 | d861def3 | Anthony Liguori | struct termios tty;
|
1110 | d861def3 | Anthony Liguori | |
1111 | d861def3 | Anthony Liguori | snprintf(buffer, sizeof(buffer), "vc%d", index); |
1112 | d861def3 | Anthony Liguori | snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index); |
1113 | d861def3 | Anthony Liguori | |
1114 | d861def3 | Anthony Liguori | vc->chr = vcs[index]; |
1115 | d861def3 | Anthony Liguori | |
1116 | d861def3 | Anthony Liguori | if (vc->chr->label) {
|
1117 | d861def3 | Anthony Liguori | label = vc->chr->label; |
1118 | d861def3 | Anthony Liguori | } else {
|
1119 | d861def3 | Anthony Liguori | label = buffer; |
1120 | d861def3 | Anthony Liguori | } |
1121 | d861def3 | Anthony Liguori | |
1122 | d861def3 | Anthony Liguori | vc->menu_item = gtk_radio_menu_item_new_with_mnemonic(group, label); |
1123 | d861def3 | Anthony Liguori | group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item)); |
1124 | d861def3 | Anthony Liguori | gtk_menu_item_set_accel_path(GTK_MENU_ITEM(vc->menu_item), path); |
1125 | d861def3 | Anthony Liguori | gtk_accel_map_add_entry(path, GDK_KEY_2 + index, GDK_CONTROL_MASK | GDK_MOD1_MASK); |
1126 | d861def3 | Anthony Liguori | |
1127 | d861def3 | Anthony Liguori | vc->terminal = vte_terminal_new(); |
1128 | d861def3 | Anthony Liguori | |
1129 | d861def3 | Anthony Liguori | ret = openpty(&master_fd, &slave_fd, NULL, NULL, NULL); |
1130 | d861def3 | Anthony Liguori | g_assert(ret != -1);
|
1131 | d861def3 | Anthony Liguori | |
1132 | d861def3 | Anthony Liguori | /* Set raw attributes on the pty. */
|
1133 | d861def3 | Anthony Liguori | tcgetattr(slave_fd, &tty); |
1134 | d861def3 | Anthony Liguori | cfmakeraw(&tty); |
1135 | d861def3 | Anthony Liguori | tcsetattr(slave_fd, TCSAFLUSH, &tty); |
1136 | d861def3 | Anthony Liguori | |
1137 | 28d2e5b2 | Stefan Weil | #if VTE_CHECK_VERSION(0, 26, 0) |
1138 | d861def3 | Anthony Liguori | pty = vte_pty_new_foreign(master_fd, NULL);
|
1139 | d861def3 | Anthony Liguori | vte_terminal_set_pty_object(VTE_TERMINAL(vc->terminal), pty); |
1140 | 28d2e5b2 | Stefan Weil | #else
|
1141 | 28d2e5b2 | Stefan Weil | vte_terminal_set_pty(VTE_TERMINAL(vc->terminal), master_fd); |
1142 | 28d2e5b2 | Stefan Weil | #endif
|
1143 | d861def3 | Anthony Liguori | |
1144 | d861def3 | Anthony Liguori | vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->terminal), -1);
|
1145 | d861def3 | Anthony Liguori | |
1146 | d861def3 | Anthony Liguori | vadjustment = vte_terminal_get_adjustment(VTE_TERMINAL(vc->terminal)); |
1147 | d861def3 | Anthony Liguori | |
1148 | d861def3 | Anthony Liguori | scrolled_window = gtk_scrolled_window_new(NULL, vadjustment);
|
1149 | d861def3 | Anthony Liguori | gtk_container_add(GTK_CONTAINER(scrolled_window), vc->terminal); |
1150 | d861def3 | Anthony Liguori | |
1151 | d861def3 | Anthony Liguori | vte_terminal_set_size(VTE_TERMINAL(vc->terminal), 80, 25); |
1152 | d861def3 | Anthony Liguori | |
1153 | d861def3 | Anthony Liguori | vc->fd = slave_fd; |
1154 | d861def3 | Anthony Liguori | vc->chr->opaque = vc; |
1155 | d861def3 | Anthony Liguori | vc->scrolled_window = scrolled_window; |
1156 | d861def3 | Anthony Liguori | |
1157 | d861def3 | Anthony Liguori | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vc->scrolled_window), |
1158 | d861def3 | Anthony Liguori | GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
1159 | d861def3 | Anthony Liguori | |
1160 | d861def3 | Anthony Liguori | gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), scrolled_window, gtk_label_new(label)); |
1161 | d861def3 | Anthony Liguori | g_signal_connect(vc->menu_item, "activate",
|
1162 | d861def3 | Anthony Liguori | G_CALLBACK(gd_menu_switch_vc), s); |
1163 | d861def3 | Anthony Liguori | |
1164 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), vc->menu_item); |
1165 | d861def3 | Anthony Liguori | |
1166 | d861def3 | Anthony Liguori | qemu_chr_generic_open(vc->chr); |
1167 | d861def3 | Anthony Liguori | if (vc->chr->init) {
|
1168 | d861def3 | Anthony Liguori | vc->chr->init(vc->chr); |
1169 | d861def3 | Anthony Liguori | } |
1170 | d861def3 | Anthony Liguori | |
1171 | d861def3 | Anthony Liguori | chan = g_io_channel_unix_new(vc->fd); |
1172 | d861def3 | Anthony Liguori | g_io_add_watch(chan, G_IO_IN, gd_vc_in, vc); |
1173 | d861def3 | Anthony Liguori | |
1174 | d861def3 | Anthony Liguori | return group;
|
1175 | a4ccabcf | Anthony Liguori | } |
1176 | a4ccabcf | Anthony Liguori | |
1177 | a4ccabcf | Anthony Liguori | /** Window Creation **/
|
1178 | a4ccabcf | Anthony Liguori | |
1179 | a4ccabcf | Anthony Liguori | static void gd_connect_signals(GtkDisplayState *s) |
1180 | a4ccabcf | Anthony Liguori | { |
1181 | a4ccabcf | Anthony Liguori | g_signal_connect(s->show_tabs_item, "activate",
|
1182 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_menu_show_tabs), s); |
1183 | a4ccabcf | Anthony Liguori | |
1184 | 73d4dc71 | Anthony Liguori | g_signal_connect(s->window, "key-press-event",
|
1185 | 73d4dc71 | Anthony Liguori | G_CALLBACK(gd_window_key_event), s); |
1186 | a4ccabcf | Anthony Liguori | g_signal_connect(s->window, "delete-event",
|
1187 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_window_close), s); |
1188 | a4ccabcf | Anthony Liguori | |
1189 | fe43bca8 | Daniel P. Berrange | #if GTK_CHECK_VERSION(3, 0, 0) |
1190 | fe43bca8 | Daniel P. Berrange | g_signal_connect(s->drawing_area, "draw",
|
1191 | fe43bca8 | Daniel P. Berrange | G_CALLBACK(gd_draw_event), s); |
1192 | fe43bca8 | Daniel P. Berrange | #else
|
1193 | a4ccabcf | Anthony Liguori | g_signal_connect(s->drawing_area, "expose-event",
|
1194 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_expose_event), s); |
1195 | fe43bca8 | Daniel P. Berrange | #endif
|
1196 | a4ccabcf | Anthony Liguori | g_signal_connect(s->drawing_area, "motion-notify-event",
|
1197 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_motion_event), s); |
1198 | a4ccabcf | Anthony Liguori | g_signal_connect(s->drawing_area, "button-press-event",
|
1199 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_button_event), s); |
1200 | a4ccabcf | Anthony Liguori | g_signal_connect(s->drawing_area, "button-release-event",
|
1201 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_button_event), s); |
1202 | a4ccabcf | Anthony Liguori | g_signal_connect(s->drawing_area, "key-press-event",
|
1203 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_key_event), s); |
1204 | a4ccabcf | Anthony Liguori | g_signal_connect(s->drawing_area, "key-release-event",
|
1205 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_key_event), s); |
1206 | a4ccabcf | Anthony Liguori | |
1207 | 30e8f22b | Jan Kiszka | g_signal_connect(s->pause_item, "activate",
|
1208 | 30e8f22b | Jan Kiszka | G_CALLBACK(gd_menu_pause), s); |
1209 | 30e8f22b | Jan Kiszka | g_signal_connect(s->reset_item, "activate",
|
1210 | 30e8f22b | Jan Kiszka | G_CALLBACK(gd_menu_reset), s); |
1211 | 30e8f22b | Jan Kiszka | g_signal_connect(s->powerdown_item, "activate",
|
1212 | 30e8f22b | Jan Kiszka | G_CALLBACK(gd_menu_powerdown), s); |
1213 | a4ccabcf | Anthony Liguori | g_signal_connect(s->quit_item, "activate",
|
1214 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_menu_quit), s); |
1215 | c6158483 | Anthony Liguori | g_signal_connect(s->full_screen_item, "activate",
|
1216 | c6158483 | Anthony Liguori | G_CALLBACK(gd_menu_full_screen), s); |
1217 | c6158483 | Anthony Liguori | g_signal_connect(s->zoom_in_item, "activate",
|
1218 | c6158483 | Anthony Liguori | G_CALLBACK(gd_menu_zoom_in), s); |
1219 | c6158483 | Anthony Liguori | g_signal_connect(s->zoom_out_item, "activate",
|
1220 | c6158483 | Anthony Liguori | G_CALLBACK(gd_menu_zoom_out), s); |
1221 | c6158483 | Anthony Liguori | g_signal_connect(s->zoom_fixed_item, "activate",
|
1222 | c6158483 | Anthony Liguori | G_CALLBACK(gd_menu_zoom_fixed), s); |
1223 | c6158483 | Anthony Liguori | g_signal_connect(s->zoom_fit_item, "activate",
|
1224 | c6158483 | Anthony Liguori | G_CALLBACK(gd_menu_zoom_fit), s); |
1225 | a4ccabcf | Anthony Liguori | g_signal_connect(s->vga_item, "activate",
|
1226 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_menu_switch_vc), s); |
1227 | 5104a1f6 | Anthony Liguori | g_signal_connect(s->grab_item, "activate",
|
1228 | 5104a1f6 | Anthony Liguori | G_CALLBACK(gd_menu_grab_input), s); |
1229 | a4ccabcf | Anthony Liguori | g_signal_connect(s->notebook, "switch-page",
|
1230 | a4ccabcf | Anthony Liguori | G_CALLBACK(gd_change_page), s); |
1231 | 5104a1f6 | Anthony Liguori | g_signal_connect(s->drawing_area, "enter-notify-event",
|
1232 | 5104a1f6 | Anthony Liguori | G_CALLBACK(gd_enter_event), s); |
1233 | 5104a1f6 | Anthony Liguori | g_signal_connect(s->drawing_area, "leave-notify-event",
|
1234 | 5104a1f6 | Anthony Liguori | G_CALLBACK(gd_leave_event), s); |
1235 | 6db253ca | Jan Kiszka | g_signal_connect(s->drawing_area, "focus-out-event",
|
1236 | 6db253ca | Jan Kiszka | G_CALLBACK(gd_focus_out_event), s); |
1237 | a4ccabcf | Anthony Liguori | } |
1238 | a4ccabcf | Anthony Liguori | |
1239 | a4ccabcf | Anthony Liguori | static void gd_create_menus(GtkDisplayState *s) |
1240 | a4ccabcf | Anthony Liguori | { |
1241 | a4ccabcf | Anthony Liguori | GtkStockItem item; |
1242 | a4ccabcf | Anthony Liguori | GtkAccelGroup *accel_group; |
1243 | a4ccabcf | Anthony Liguori | GSList *group = NULL;
|
1244 | a4ccabcf | Anthony Liguori | GtkWidget *separator; |
1245 | d861def3 | Anthony Liguori | int i;
|
1246 | a4ccabcf | Anthony Liguori | |
1247 | a4ccabcf | Anthony Liguori | accel_group = gtk_accel_group_new(); |
1248 | 30e8f22b | Jan Kiszka | s->machine_menu = gtk_menu_new(); |
1249 | 30e8f22b | Jan Kiszka | gtk_menu_set_accel_group(GTK_MENU(s->machine_menu), accel_group); |
1250 | 30e8f22b | Jan Kiszka | s->machine_menu_item = gtk_menu_item_new_with_mnemonic(_("_Machine"));
|
1251 | 30e8f22b | Jan Kiszka | |
1252 | 30e8f22b | Jan Kiszka | s->pause_item = gtk_check_menu_item_new_with_mnemonic(_("_Pause"));
|
1253 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), s->pause_item); |
1254 | 30e8f22b | Jan Kiszka | |
1255 | 30e8f22b | Jan Kiszka | separator = gtk_separator_menu_item_new(); |
1256 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), separator); |
1257 | 30e8f22b | Jan Kiszka | |
1258 | 30e8f22b | Jan Kiszka | s->reset_item = gtk_image_menu_item_new_with_mnemonic(_("_Reset"));
|
1259 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), s->reset_item); |
1260 | 30e8f22b | Jan Kiszka | |
1261 | 30e8f22b | Jan Kiszka | s->powerdown_item = gtk_image_menu_item_new_with_mnemonic(_("Power _Down"));
|
1262 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), s->powerdown_item); |
1263 | 30e8f22b | Jan Kiszka | |
1264 | 30e8f22b | Jan Kiszka | separator = gtk_separator_menu_item_new(); |
1265 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), separator); |
1266 | a4ccabcf | Anthony Liguori | |
1267 | a4ccabcf | Anthony Liguori | s->quit_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
|
1268 | a4ccabcf | Anthony Liguori | gtk_stock_lookup(GTK_STOCK_QUIT, &item); |
1269 | a4ccabcf | Anthony Liguori | gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->quit_item), |
1270 | 30e8f22b | Jan Kiszka | "<QEMU>/Machine/Quit");
|
1271 | 30e8f22b | Jan Kiszka | gtk_accel_map_add_entry("<QEMU>/Machine/Quit", item.keyval, item.modifier);
|
1272 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->machine_menu), s->quit_item); |
1273 | a4ccabcf | Anthony Liguori | |
1274 | a4ccabcf | Anthony Liguori | s->view_menu = gtk_menu_new(); |
1275 | a4ccabcf | Anthony Liguori | gtk_menu_set_accel_group(GTK_MENU(s->view_menu), accel_group); |
1276 | 834574ea | Anthony Liguori | s->view_menu_item = gtk_menu_item_new_with_mnemonic(_("_View"));
|
1277 | a4ccabcf | Anthony Liguori | |
1278 | 10409282 | Stefan Weil | s->full_screen_item = |
1279 | 10409282 | Stefan Weil | gtk_image_menu_item_new_from_stock(GTK_STOCK_FULLSCREEN, NULL);
|
1280 | c6158483 | Anthony Liguori | gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->full_screen_item), |
1281 | c6158483 | Anthony Liguori | "<QEMU>/View/Full Screen");
|
1282 | c6158483 | Anthony Liguori | gtk_accel_map_add_entry("<QEMU>/View/Full Screen", GDK_KEY_f, GDK_CONTROL_MASK | GDK_MOD1_MASK);
|
1283 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->full_screen_item); |
1284 | c6158483 | Anthony Liguori | |
1285 | c6158483 | Anthony Liguori | separator = gtk_separator_menu_item_new(); |
1286 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), separator); |
1287 | c6158483 | Anthony Liguori | |
1288 | c6158483 | Anthony Liguori | s->zoom_in_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_IN, NULL);
|
1289 | c6158483 | Anthony Liguori | gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_in_item), |
1290 | c6158483 | Anthony Liguori | "<QEMU>/View/Zoom In");
|
1291 | c6158483 | Anthony Liguori | gtk_accel_map_add_entry("<QEMU>/View/Zoom In", GDK_KEY_plus, GDK_CONTROL_MASK | GDK_MOD1_MASK);
|
1292 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->zoom_in_item); |
1293 | c6158483 | Anthony Liguori | |
1294 | c6158483 | Anthony Liguori | s->zoom_out_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_OUT, NULL);
|
1295 | c6158483 | Anthony Liguori | gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_out_item), |
1296 | c6158483 | Anthony Liguori | "<QEMU>/View/Zoom Out");
|
1297 | c6158483 | Anthony Liguori | gtk_accel_map_add_entry("<QEMU>/View/Zoom Out", GDK_KEY_minus, GDK_CONTROL_MASK | GDK_MOD1_MASK);
|
1298 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->zoom_out_item); |
1299 | c6158483 | Anthony Liguori | |
1300 | c6158483 | Anthony Liguori | s->zoom_fixed_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_100, NULL);
|
1301 | c6158483 | Anthony Liguori | gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_fixed_item), |
1302 | c6158483 | Anthony Liguori | "<QEMU>/View/Zoom Fixed");
|
1303 | c6158483 | Anthony Liguori | gtk_accel_map_add_entry("<QEMU>/View/Zoom Fixed", GDK_KEY_0, GDK_CONTROL_MASK | GDK_MOD1_MASK);
|
1304 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->zoom_fixed_item); |
1305 | c6158483 | Anthony Liguori | |
1306 | 834574ea | Anthony Liguori | s->zoom_fit_item = gtk_check_menu_item_new_with_mnemonic(_("Zoom To _Fit"));
|
1307 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->zoom_fit_item); |
1308 | c6158483 | Anthony Liguori | |
1309 | c6158483 | Anthony Liguori | separator = gtk_separator_menu_item_new(); |
1310 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), separator); |
1311 | c6158483 | Anthony Liguori | |
1312 | 834574ea | Anthony Liguori | s->grab_on_hover_item = gtk_check_menu_item_new_with_mnemonic(_("Grab On _Hover"));
|
1313 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->grab_on_hover_item); |
1314 | 5104a1f6 | Anthony Liguori | |
1315 | 834574ea | Anthony Liguori | s->grab_item = gtk_check_menu_item_new_with_mnemonic(_("_Grab Input"));
|
1316 | 5104a1f6 | Anthony Liguori | gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->grab_item), |
1317 | 5104a1f6 | Anthony Liguori | "<QEMU>/View/Grab Input");
|
1318 | 5104a1f6 | Anthony Liguori | gtk_accel_map_add_entry("<QEMU>/View/Grab Input", GDK_KEY_g, GDK_CONTROL_MASK | GDK_MOD1_MASK);
|
1319 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->grab_item); |
1320 | 5104a1f6 | Anthony Liguori | |
1321 | a4ccabcf | Anthony Liguori | separator = gtk_separator_menu_item_new(); |
1322 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), separator); |
1323 | a4ccabcf | Anthony Liguori | |
1324 | a4ccabcf | Anthony Liguori | s->vga_item = gtk_radio_menu_item_new_with_mnemonic(group, "_VGA");
|
1325 | a4ccabcf | Anthony Liguori | group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(s->vga_item)); |
1326 | a4ccabcf | Anthony Liguori | gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->vga_item), |
1327 | a4ccabcf | Anthony Liguori | "<QEMU>/View/VGA");
|
1328 | a4ccabcf | Anthony Liguori | gtk_accel_map_add_entry("<QEMU>/View/VGA", GDK_KEY_1, GDK_CONTROL_MASK | GDK_MOD1_MASK);
|
1329 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->vga_item); |
1330 | a4ccabcf | Anthony Liguori | |
1331 | d861def3 | Anthony Liguori | for (i = 0; i < nb_vcs; i++) { |
1332 | d861def3 | Anthony Liguori | VirtualConsole *vc = &s->vc[i]; |
1333 | d861def3 | Anthony Liguori | |
1334 | d861def3 | Anthony Liguori | group = gd_vc_init(s, vc, i, group); |
1335 | d861def3 | Anthony Liguori | s->nb_vcs++; |
1336 | d861def3 | Anthony Liguori | } |
1337 | d861def3 | Anthony Liguori | |
1338 | a4ccabcf | Anthony Liguori | separator = gtk_separator_menu_item_new(); |
1339 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), separator); |
1340 | a4ccabcf | Anthony Liguori | |
1341 | 834574ea | Anthony Liguori | s->show_tabs_item = gtk_check_menu_item_new_with_mnemonic(_("Show _Tabs"));
|
1342 | 530daf82 | Daniel P. Berrange | gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), s->show_tabs_item); |
1343 | a4ccabcf | Anthony Liguori | |
1344 | a4ccabcf | Anthony Liguori | g_object_set_data(G_OBJECT(s->window), "accel_group", accel_group);
|
1345 | a4ccabcf | Anthony Liguori | gtk_window_add_accel_group(GTK_WINDOW(s->window), accel_group); |
1346 | 73d4dc71 | Anthony Liguori | s->accel_group = accel_group; |
1347 | a4ccabcf | Anthony Liguori | |
1348 | 30e8f22b | Jan Kiszka | gtk_menu_item_set_submenu(GTK_MENU_ITEM(s->machine_menu_item), |
1349 | 30e8f22b | Jan Kiszka | s->machine_menu); |
1350 | 30e8f22b | Jan Kiszka | gtk_menu_shell_append(GTK_MENU_SHELL(s->menu_bar), s->machine_menu_item); |
1351 | a4ccabcf | Anthony Liguori | |
1352 | a4ccabcf | Anthony Liguori | gtk_menu_item_set_submenu(GTK_MENU_ITEM(s->view_menu_item), s->view_menu); |
1353 | a4ccabcf | Anthony Liguori | gtk_menu_shell_append(GTK_MENU_SHELL(s->menu_bar), s->view_menu_item); |
1354 | a4ccabcf | Anthony Liguori | } |
1355 | a4ccabcf | Anthony Liguori | |
1356 | 7c20b4a3 | Gerd Hoffmann | static const DisplayChangeListenerOps dcl_ops = { |
1357 | 7c20b4a3 | Gerd Hoffmann | .dpy_name = "gtk",
|
1358 | 7c20b4a3 | Gerd Hoffmann | .dpy_gfx_update = gd_update, |
1359 | c12aeb86 | Gerd Hoffmann | .dpy_gfx_switch = gd_switch, |
1360 | 7c20b4a3 | Gerd Hoffmann | .dpy_refresh = gd_refresh, |
1361 | 7c20b4a3 | Gerd Hoffmann | }; |
1362 | 7c20b4a3 | Gerd Hoffmann | |
1363 | a4ccabcf | Anthony Liguori | void gtk_display_init(DisplayState *ds)
|
1364 | a4ccabcf | Anthony Liguori | { |
1365 | a4ccabcf | Anthony Liguori | GtkDisplayState *s = g_malloc0(sizeof(*s));
|
1366 | a4ccabcf | Anthony Liguori | |
1367 | a4ccabcf | Anthony Liguori | gtk_init(NULL, NULL); |
1368 | a4ccabcf | Anthony Liguori | |
1369 | 7c20b4a3 | Gerd Hoffmann | s->dcl.ops = &dcl_ops; |
1370 | a4ccabcf | Anthony Liguori | |
1371 | a4ccabcf | Anthony Liguori | s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
1372 | 51572ab0 | Daniel P. Berrange | #if GTK_CHECK_VERSION(3, 2, 0) |
1373 | 51572ab0 | Daniel P. Berrange | s->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
1374 | 51572ab0 | Daniel P. Berrange | #else
|
1375 | a4ccabcf | Anthony Liguori | s->vbox = gtk_vbox_new(FALSE, 0);
|
1376 | 51572ab0 | Daniel P. Berrange | #endif
|
1377 | a4ccabcf | Anthony Liguori | s->notebook = gtk_notebook_new(); |
1378 | a4ccabcf | Anthony Liguori | s->drawing_area = gtk_drawing_area_new(); |
1379 | a4ccabcf | Anthony Liguori | s->menu_bar = gtk_menu_bar_new(); |
1380 | a4ccabcf | Anthony Liguori | |
1381 | a4ccabcf | Anthony Liguori | s->scale_x = 1.0; |
1382 | a4ccabcf | Anthony Liguori | s->scale_y = 1.0; |
1383 | c6158483 | Anthony Liguori | s->free_scale = FALSE; |
1384 | a4ccabcf | Anthony Liguori | |
1385 | 834574ea | Anthony Liguori | setlocale(LC_ALL, "");
|
1386 | 834574ea | Anthony Liguori | bindtextdomain("qemu", CONFIG_QEMU_LOCALEDIR);
|
1387 | 834574ea | Anthony Liguori | textdomain("qemu");
|
1388 | 834574ea | Anthony Liguori | |
1389 | a4ccabcf | Anthony Liguori | s->null_cursor = gdk_cursor_new(GDK_BLANK_CURSOR); |
1390 | a4ccabcf | Anthony Liguori | |
1391 | a4ccabcf | Anthony Liguori | s->mouse_mode_notifier.notify = gd_mouse_mode_change; |
1392 | a4ccabcf | Anthony Liguori | qemu_add_mouse_mode_change_notifier(&s->mouse_mode_notifier); |
1393 | a4ccabcf | Anthony Liguori | qemu_add_vm_change_state_handler(gd_change_runstate, s); |
1394 | a4ccabcf | Anthony Liguori | |
1395 | a4ccabcf | Anthony Liguori | gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA"));
|
1396 | a4ccabcf | Anthony Liguori | |
1397 | a4ccabcf | Anthony Liguori | gd_create_menus(s); |
1398 | a4ccabcf | Anthony Liguori | |
1399 | a4ccabcf | Anthony Liguori | gd_connect_signals(s); |
1400 | a4ccabcf | Anthony Liguori | |
1401 | a4ccabcf | Anthony Liguori | gtk_widget_add_events(s->drawing_area, |
1402 | a4ccabcf | Anthony Liguori | GDK_POINTER_MOTION_MASK | |
1403 | a4ccabcf | Anthony Liguori | GDK_BUTTON_PRESS_MASK | |
1404 | a4ccabcf | Anthony Liguori | GDK_BUTTON_RELEASE_MASK | |
1405 | a4ccabcf | Anthony Liguori | GDK_BUTTON_MOTION_MASK | |
1406 | 5104a1f6 | Anthony Liguori | GDK_ENTER_NOTIFY_MASK | |
1407 | 5104a1f6 | Anthony Liguori | GDK_LEAVE_NOTIFY_MASK | |
1408 | a4ccabcf | Anthony Liguori | GDK_SCROLL_MASK | |
1409 | a4ccabcf | Anthony Liguori | GDK_KEY_PRESS_MASK); |
1410 | a4ccabcf | Anthony Liguori | gtk_widget_set_double_buffered(s->drawing_area, FALSE); |
1411 | a4ccabcf | Anthony Liguori | gtk_widget_set_can_focus(s->drawing_area, TRUE); |
1412 | a4ccabcf | Anthony Liguori | |
1413 | a4ccabcf | Anthony Liguori | gtk_notebook_set_show_tabs(GTK_NOTEBOOK(s->notebook), FALSE); |
1414 | a4ccabcf | Anthony Liguori | gtk_notebook_set_show_border(GTK_NOTEBOOK(s->notebook), FALSE); |
1415 | a4ccabcf | Anthony Liguori | |
1416 | a4ccabcf | Anthony Liguori | gd_update_caption(s); |
1417 | a4ccabcf | Anthony Liguori | |
1418 | a4ccabcf | Anthony Liguori | gtk_box_pack_start(GTK_BOX(s->vbox), s->menu_bar, FALSE, TRUE, 0);
|
1419 | a4ccabcf | Anthony Liguori | gtk_box_pack_start(GTK_BOX(s->vbox), s->notebook, TRUE, TRUE, 0);
|
1420 | a4ccabcf | Anthony Liguori | |
1421 | a4ccabcf | Anthony Liguori | gtk_container_add(GTK_CONTAINER(s->window), s->vbox); |
1422 | a4ccabcf | Anthony Liguori | |
1423 | a4ccabcf | Anthony Liguori | gtk_widget_show_all(s->window); |
1424 | a4ccabcf | Anthony Liguori | |
1425 | a4ccabcf | Anthony Liguori | register_displaychangelistener(ds, &s->dcl); |
1426 | a4ccabcf | Anthony Liguori | |
1427 | a4ccabcf | Anthony Liguori | global_state = s; |
1428 | a4ccabcf | Anthony Liguori | } |