gtk: stop using DisplayState

Rework DisplayStateListener callbacks to not use the DisplayState
any more.  Factor out the window size handling to a separate function,
so the zoom callbacks can call that directly instead of abusing the
gd_switch DisplayStateListener callback for that.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2013-02-28 16:10:02 +01:00
parent 626e3b34e3
commit 9d9801cf80
1 changed files with 122 additions and 102 deletions

224
ui/gtk.c
View File

@ -143,7 +143,7 @@ typedef struct GtkDisplayState
GtkWidget *drawing_area;
cairo_surface_t *surface;
DisplayChangeListener dcl;
DisplayState *ds;
DisplaySurface *ds;
int button_mask;
int last_x;
int last_y;
@ -225,86 +225,8 @@ static void gd_update_caption(GtkDisplayState *s)
g_free(title);
}
/** DisplayState Callbacks **/
static void gd_update(DisplayChangeListener *dcl,
DisplayState *ds, int x, int y, int w, int h)
static void gd_update_windowsize(GtkDisplayState *s)
{
GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
int x1, x2, y1, y2;
int mx, my;
int fbw, fbh;
int ww, wh;
DPRINTF("update(x=%d, y=%d, w=%d, h=%d)\n", x, y, w, h);
x1 = floor(x * s->scale_x);
y1 = floor(y * s->scale_y);
x2 = ceil(x * s->scale_x + w * s->scale_x);
y2 = ceil(y * s->scale_y + h * s->scale_y);
fbw = ds_get_width(s->ds) * s->scale_x;
fbh = ds_get_height(s->ds) * s->scale_y;
gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
mx = my = 0;
if (ww > fbw) {
mx = (ww - fbw) / 2;
}
if (wh > fbh) {
my = (wh - fbh) / 2;
}
gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1));
}
static void gd_refresh(DisplayChangeListener *dcl,
DisplayState *ds)
{
vga_hw_update();
}
static void gd_switch(DisplayChangeListener *dcl,
DisplayState *ds,
DisplaySurface *surface)
{
GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
cairo_format_t kind;
int stride;
DPRINTF("resize(width=%d, height=%d)\n",
ds_get_width(ds), ds_get_height(ds));
if (s->surface) {
cairo_surface_destroy(s->surface);
}
switch (ds->surface->pf.bits_per_pixel) {
case 8:
kind = CAIRO_FORMAT_A8;
break;
case 16:
kind = CAIRO_FORMAT_RGB16_565;
break;
case 32:
kind = CAIRO_FORMAT_RGB24;
break;
default:
g_assert_not_reached();
break;
}
stride = cairo_format_stride_for_width(kind, ds_get_width(ds));
g_assert(ds_get_linesize(ds) == stride);
s->surface = cairo_image_surface_create_for_data(ds_get_data(ds),
kind,
ds_get_width(ds),
ds_get_height(ds),
ds_get_linesize(ds));
if (!s->full_screen) {
GtkRequisition req;
double sx, sy;
@ -321,8 +243,8 @@ static void gd_switch(DisplayChangeListener *dcl,
}
gtk_widget_set_size_request(s->drawing_area,
ds_get_width(ds) * s->scale_x,
ds_get_height(ds) * s->scale_y);
surface_width(s->ds) * s->scale_x,
surface_height(s->ds) * s->scale_y);
#if GTK_CHECK_VERSION(3, 0, 0)
gtk_widget_get_preferred_size(s->vbox, NULL, &req);
#else
@ -334,6 +256,107 @@ static void gd_switch(DisplayChangeListener *dcl,
}
}
static void gd_update_full_redraw(GtkDisplayState *s)
{
int ww, wh;
gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
}
/** DisplayState Callbacks **/
static void gd_update(DisplayChangeListener *dcl,
DisplayState *dontuse, int x, int y, int w, int h)
{
GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
int x1, x2, y1, y2;
int mx, my;
int fbw, fbh;
int ww, wh;
DPRINTF("update(x=%d, y=%d, w=%d, h=%d)\n", x, y, w, h);
x1 = floor(x * s->scale_x);
y1 = floor(y * s->scale_y);
x2 = ceil(x * s->scale_x + w * s->scale_x);
y2 = ceil(y * s->scale_y + h * s->scale_y);
fbw = surface_width(s->ds) * s->scale_x;
fbh = surface_height(s->ds) * s->scale_y;
gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
mx = my = 0;
if (ww > fbw) {
mx = (ww - fbw) / 2;
}
if (wh > fbh) {
my = (wh - fbh) / 2;
}
gtk_widget_queue_draw_area(s->drawing_area, mx + x1, my + y1, (x2 - x1), (y2 - y1));
}
static void gd_refresh(DisplayChangeListener *dcl,
DisplayState *dontuse)
{
vga_hw_update();
}
static void gd_switch(DisplayChangeListener *dcl,
DisplayState *dontuse,
DisplaySurface *surface)
{
GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl);
cairo_format_t kind;
bool resized = true;
int stride;
DPRINTF("resize(width=%d, height=%d)\n",
surface_width(surface), surface_height(surface));
if (s->surface) {
cairo_surface_destroy(s->surface);
}
if (s->ds &&
surface_width(s->ds) == surface_width(surface) &&
surface_height(s->ds) == surface_height(surface)) {
resized = false;
}
s->ds = surface;
switch (surface_bits_per_pixel(surface)) {
case 8:
kind = CAIRO_FORMAT_A8;
break;
case 16:
kind = CAIRO_FORMAT_RGB16_565;
break;
case 32:
kind = CAIRO_FORMAT_RGB24;
break;
default:
g_assert_not_reached();
break;
}
stride = cairo_format_stride_for_width(kind, surface_width(surface));
g_assert(surface_stride(surface) == stride);
s->surface = cairo_image_surface_create_for_data(surface_data(surface),
kind,
surface_width(surface),
surface_height(surface),
surface_stride(surface));
if (resized) {
gd_update_windowsize(s);
} else {
gd_update_full_redraw(s);
}
}
/** QEMU Events **/
static void gd_change_runstate(void *opaque, int running, RunState state)
@ -405,8 +428,8 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
return FALSE;
}
fbw = ds_get_width(s->ds);
fbh = ds_get_height(s->ds);
fbw = surface_width(s->ds);
fbh = surface_height(s->ds);
gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh);
@ -484,8 +507,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
int fbh, fbw;
int ww, wh;
fbw = ds_get_width(s->ds) * s->scale_x;
fbh = ds_get_height(s->ds) * s->scale_y;
fbw = surface_width(s->ds) * s->scale_x;
fbh = surface_height(s->ds) * s->scale_y;
gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
@ -501,14 +524,14 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
y = (motion->y - my) / s->scale_y;
if (x < 0 || y < 0 ||
x >= ds_get_width(s->ds) ||
y >= ds_get_height(s->ds)) {
x >= surface_width(s->ds) ||
y >= surface_height(s->ds)) {
return TRUE;
}
if (kbd_mouse_is_absolute()) {
dx = x * 0x7FFF / (ds_get_width(s->ds) - 1);
dy = y * 0x7FFF / (ds_get_height(s->ds) - 1);
dx = x * 0x7FFF / (surface_width(s->ds) - 1);
dy = y * 0x7FFF / (surface_height(s->ds) - 1);
} else if (s->last_x == -1 || s->last_y == -1) {
dx = 0;
dy = 0;
@ -589,8 +612,8 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
}
if (kbd_mouse_is_absolute()) {
dx = s->last_x * 0x7FFF / (ds_get_width(s->ds) - 1);
dy = s->last_y * 0x7FFF / (ds_get_height(s->ds) - 1);
dx = s->last_x * 0x7FFF / (surface_width(s->ds) - 1);
dy = s->last_y * 0x7FFF / (surface_height(s->ds) - 1);
} else {
dx = 0;
dy = 0;
@ -719,7 +742,8 @@ static void gd_menu_full_screen(GtkMenuItem *item, void *opaque)
gd_menu_show_tabs(GTK_MENU_ITEM(s->show_tabs_item), s);
gtk_widget_set_size_request(s->menu_bar, -1, -1);
gtk_widget_set_size_request(s->drawing_area,
ds_get_width(s->ds), ds_get_height(s->ds));
surface_width(s->ds),
surface_height(s->ds));
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item), FALSE);
s->full_screen = FALSE;
s->scale_x = 1.0;
@ -739,7 +763,7 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque)
s->scale_x += .25;
s->scale_y += .25;
gd_switch(&s->dcl, s->ds, s->ds->surface);
gd_update_windowsize(s);
}
static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
@ -755,7 +779,7 @@ static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
s->scale_x = MAX(s->scale_x, .25);
s->scale_y = MAX(s->scale_y, .25);
gd_switch(&s->dcl, s->ds, s->ds->surface);
gd_update_windowsize(s);
}
static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
@ -765,13 +789,12 @@ static void gd_menu_zoom_fixed(GtkMenuItem *item, void *opaque)
s->scale_x = 1.0;
s->scale_y = 1.0;
gd_switch(&s->dcl, s->ds, s->ds->surface);
gd_update_windowsize(s);
}
static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
{
GtkDisplayState *s = opaque;
int ww, wh;
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->zoom_fit_item))) {
s->free_scale = TRUE;
@ -779,10 +802,8 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque)
s->free_scale = FALSE;
}
gd_switch(&s->dcl, s->ds, s->ds->surface);
gdk_drawable_get_size(gtk_widget_get_window(s->drawing_area), &ww, &wh);
gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
gd_update_windowsize(s);
gd_update_full_redraw(s);
}
static void gd_grab_keyboard(GtkDisplayState *s)
@ -1298,7 +1319,6 @@ void gtk_display_init(DisplayState *ds)
gtk_init(NULL, NULL);
s->ds = ds;
s->dcl.ops = &dcl_ops;
s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);