X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=spiceterm.c;h=dd63b90e0a6c95b21d1f3add8646ca191e0e0731;hb=8a3547be3168c07a050d01bada23b94b272516ec;hp=ed4101609d4c4308433800be71c60113e4abb6c8;hpb=69a7370ccbc5546ec66132384d1cb95d41083354;p=spiceterm.git diff --git a/spiceterm.c b/spiceterm.c index ed41016..dd63b90 100644 --- a/spiceterm.c +++ b/spiceterm.c @@ -79,8 +79,10 @@ unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15 }; -static void vdagent_grab_clipboard(spiceTerm *vt); -static void vdagent_request_clipboard(spiceTerm *vt); +static void spiceterm_resize(spiceTerm *vt, uint32_t width, uint32_t height); + +static void vdagent_grab_clipboard(spiceTerm *vt, uint8_t selection); +static void vdagent_request_clipboard(spiceTerm *vt, uint8_t selection); static void print_usage(const char *msg) @@ -537,7 +539,7 @@ spiceterm_set_alternate_buffer(spiceTerm *vt, int on_off) /* clear screen */ for (y = 0; y <= vt->height; y++) { for (x = 0; x < vt->width; x++) { - spiceterm_clear_xy(vt, x, y); + // spiceterm_clear_xy(vt, x, y); } } @@ -1325,135 +1327,6 @@ spiceterm_respond_unichar2(spiceTerm *vt, gunichar2 uc) } } -static void -spiceterm_motion_event(spiceTerm *vt, uint32_t x, uint32_t y, uint32_t buttons) -{ - DPRINTF(1, "mask=%08x x=%d y=%d", buttons, x ,y); - - static int last_mask = 0; - static int sel_start_pos = 0; - static int sel_end_pos = 0; - static int button2_released = 1; - - int i; - int cx = x/8; - int cy = y/16; - - if (cx < 0) cx = 0; - if (cx >= vt->width) cx = vt->width - 1; - if (cy < 0) cy = 0; - if (cy >= vt->height) cy = vt->height - 1; - - if (vt->report_mouse && buttons != last_mask) { - last_mask = buttons; - if (buttons & 2) { - mouse_report(vt, 0, cx, cy); - } - if (buttons & 4) { - mouse_report (vt, 1, cx, cy); - } - if (buttons & 8) { - mouse_report(vt, 2, cx, cy); - } - if(!buttons) { - mouse_report(vt, 3, cx, cy); - } - } - - if (buttons & 4) { - - - if(button2_released) { - - if (1) { // fixme: - vdagent_request_clipboard(vt); - } else if (vt->selection) { - int i; - for(i = 0; i < vt->selection_len; i++) { - spiceterm_respond_unichar2(vt, vt->selection[i]); - } - spiceterm_update_watch_mask(vt, TRUE); - if (vt->y_displ != vt->y_base) { - vt->y_displ = vt->y_base; - spiceterm_refresh(vt); - } - } - } - - button2_released = 0; - } else { - button2_released = 1; - } - - if (buttons & 2) { - int pos = cy*vt->width + cx; - - // code borrowed from libvncserver (VNCconsole.c) - - if (!vt->mark_active) { - - spiceterm_unselect_all(vt); - - vt->mark_active = 1; - sel_start_pos = sel_end_pos = pos; - spiceterm_toggle_marked_cell(vt, pos); - - } else { - - if (pos != sel_end_pos) { - if (pos > sel_end_pos) { - cx = sel_end_pos; cy=pos; - } else { - cx=pos; cy=sel_end_pos; - } - - if (cx < sel_start_pos) { - if (cy < sel_start_pos) cy--; - } else { - cx++; - } - - while (cx <= cy) { - spiceterm_toggle_marked_cell(vt, cx); - cx++; - } - - sel_end_pos = pos; - } - } - - } else if (vt->mark_active) { - vt->mark_active = 0; - - if (sel_start_pos > sel_end_pos) { - int tmp = sel_start_pos - 1; - sel_start_pos = sel_end_pos; - sel_end_pos = tmp; - } - - int len = sel_end_pos - sel_start_pos + 1; - - if (vt->selection) free (vt->selection); - vt->selection = (gunichar2 *)malloc (len*sizeof(gunichar2)); - vt->selection_len = len; - - for (i = 0; i < len; i++) { - int pos = sel_start_pos + i; - int x = pos % vt->width; - int y1 = ((pos / vt->width) + vt->y_displ) % vt->total_height; - TextCell *c = &vt->cells[y1*vt->width + x]; - vt->selection[i] = c->ch; - c++; - } - - DPRINTF(1, "selection length = %d", vt->selection_len); - - vdagent_grab_clipboard(vt); - // fixme: tell client we have something seletced - //rfbGotXCutText (vt->screen, sel_latin1, len); - } -} - static void my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag) { @@ -1465,9 +1338,8 @@ my_kbd_push_key(SpiceKbdInstance *sin, uint8_t frag) } static void -my_kbd_push_keyval(SpiceKbdInstance *sin, uint32_t keySym, int flags) +spiceterm_push_keyval(spiceTerm *vt, uint32_t keySym, uint32_t flags) { - spiceTerm *vt = SPICE_CONTAINEROF(sin, spiceTerm, keyboard_sin); static int control = 0; static int shift = 0; char *esc = NULL; @@ -1476,7 +1348,7 @@ my_kbd_push_keyval(SpiceKbdInstance *sin, uint32_t keySym, int flags) DPRINTF(1, "flags=%d keySym=%08x", flags, keySym); - if (flags & 1) { + if (flags & VD_AGENT_KEYVAL_FLAG_DOWN) { if (keySym == GDK_KEY_Shift_L || keySym == GDK_KEY_Shift_R) { shift = 1; } if (keySym == GDK_KEY_Control_L || keySym == GDK_KEY_Control_R) { @@ -1573,7 +1445,7 @@ my_kbd_push_keyval(SpiceKbdInstance *sin, uint32_t keySym, int flags) if (vt->y_displ != vt->y_base) { vt->y_displ = vt->y_base; - spiceterm_refresh (vt); + spiceterm_refresh(vt); } if (esc) { @@ -1584,10 +1456,9 @@ my_kbd_push_keyval(SpiceKbdInstance *sin, uint32_t keySym, int flags) } } - ret: - if (flags & 2) { // UP + if (!(flags & VD_AGENT_KEYVAL_FLAG_DOWN)) { // UP if (keySym == GDK_KEY_Shift_L || keySym == GDK_KEY_Shift_R) { shift = 0; } else if (keySym == GDK_KEY_Control_L || keySym == GDK_KEY_Control_R) { @@ -1609,7 +1480,6 @@ static SpiceKbdInterface my_keyboard_sif = { .base.description = "spiceterm keyboard device", .base.major_version = SPICE_INTERFACE_KEYBOARD_MAJOR, .base.minor_version = SPICE_INTERFACE_KEYBOARD_MINOR, - .push_keyval = my_kbd_push_keyval, .push_scan_freg = my_kbd_push_key, .get_leds = my_kbd_get_leds, }; @@ -1622,6 +1492,178 @@ static unsigned char vdagent_write_buffer[VDAGENT_WBUF_SIZE]; static int vdagent_write_buffer_pos = 0; static int agent_owns_clipboard[256] = { 0, }; +static void +spiceterm_motion_event(spiceTerm *vt, uint32_t x, uint32_t y, uint32_t buttons) +{ + DPRINTF(1, "mask=%08x x=%d y=%d", buttons, x ,y); + + static int last_mask = 0; + static int sel_start_pos = 0; + static int sel_end_pos = 0; + static int button2_released = 1; + + int i; + int cx = x/8; + int cy = y/16; + + if (cx < 0) cx = 0; + if (cx >= vt->width) cx = vt->width - 1; + if (cy < 0) cy = 0; + if (cy >= vt->height) cy = vt->height - 1; + + if (vt->report_mouse && buttons != last_mask) { + last_mask = buttons; + if (buttons & 2) { + mouse_report(vt, 0, cx, cy); + } + if (buttons & 4) { + mouse_report (vt, 1, cx, cy); + } + if (buttons & 8) { + mouse_report(vt, 2, cx, cy); + } + if(!buttons) { + mouse_report(vt, 3, cx, cy); + } + } + + if (buttons & 4) { + + if(button2_released) { + + if (agent_owns_clipboard[VD_AGENT_CLIPBOARD_SELECTION_PRIMARY]) { + if (vt->selection) { + int i; + for(i = 0; i < vt->selection_len; i++) { + spiceterm_respond_unichar2(vt, vt->selection[i]); + } + spiceterm_update_watch_mask(vt, TRUE); + if (vt->y_displ != vt->y_base) { + vt->y_displ = vt->y_base; + spiceterm_refresh(vt); + } + } + } else { + vdagent_request_clipboard(vt, VD_AGENT_CLIPBOARD_SELECTION_PRIMARY); + } + } + + button2_released = 0; + } else { + button2_released = 1; + } + + if (buttons & 2) { + int pos = cy*vt->width + cx; + + // code borrowed from libvncserver (VNCconsole.c) + + if (!vt->mark_active) { + + spiceterm_unselect_all(vt); + + vt->mark_active = 1; + sel_start_pos = sel_end_pos = pos; + spiceterm_toggle_marked_cell(vt, pos); + + } else { + + if (pos != sel_end_pos) { + if (pos > sel_end_pos) { + cx = sel_end_pos; cy=pos; + } else { + cx=pos; cy=sel_end_pos; + } + + if (cx < sel_start_pos) { + if (cy < sel_start_pos) cy--; + } else { + cx++; + } + + while (cx <= cy) { + spiceterm_toggle_marked_cell(vt, cx); + cx++; + } + + sel_end_pos = pos; + } + } + + } else if (vt->mark_active) { + vt->mark_active = 0; + + if (sel_start_pos > sel_end_pos) { + int tmp = sel_start_pos - 1; + sel_start_pos = sel_end_pos; + sel_end_pos = tmp; + } + + int len = sel_end_pos - sel_start_pos + 1; + + if (vt->selection) free (vt->selection); + vt->selection = (gunichar2 *)malloc (len*sizeof(gunichar2)); + vt->selection_len = len; + + for (i = 0; i < len; i++) { + int pos = sel_start_pos + i; + int x = pos % vt->width; + int y1 = ((pos / vt->width) + vt->y_displ) % vt->total_height; + TextCell *c = &vt->cells[y1*vt->width + x]; + vt->selection[i] = c->ch; + c++; + } + + DPRINTF(1, "selection length = %d", vt->selection_len); + + vdagent_grab_clipboard(vt, VD_AGENT_CLIPBOARD_SELECTION_PRIMARY); + } +} + +static void +vdagent_reply(spiceTerm *vt, uint32_t type, uint32_t error) +{ + uint32_t size; + + size = sizeof(VDAgentReply); + + int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size; + g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE); + + unsigned char *buf = vdagent_write_buffer + vdagent_write_buffer_pos; + vdagent_write_buffer_pos += msg_size; + + memset(buf, 0, msg_size); + + VDIChunkHeader *hdr = (VDIChunkHeader *)buf; + VDAgentMessage *msg = (VDAgentMessage *)&hdr[1]; + VDAgentReply *reply = (VDAgentReply *)&msg[1]; + reply->type = type; + reply->error = error; + + hdr->port = VDP_CLIENT_PORT; + hdr->size = sizeof(VDAgentMessage) + size; + + msg->protocol = VD_AGENT_PROTOCOL; + msg->type = VD_AGENT_REPLY; + msg->opaque = 0; + msg->size = size; + + spice_server_char_device_wakeup(&vt->vdagent_sin); +} + +static void +dump_message(unsigned char *buf, int size) +{ + int i; + + for (i = 0; i < size; i++) { + printf("%d %02X\n", i, buf[i]); + } + + // exit(0); +} + static void vdagent_send_capabilities(spiceTerm *vt, uint32_t request) { VDAgentAnnounceCapabilities *caps; @@ -1639,6 +1681,7 @@ static void vdagent_send_capabilities(spiceTerm *vt, uint32_t request) VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_KEYVAL); int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size; g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE); @@ -1657,35 +1700,21 @@ static void vdagent_send_capabilities(spiceTerm *vt, uint32_t request) msg->size = size; memcpy(buf + sizeof(VDIChunkHeader) + sizeof(VDAgentMessage), (uint8_t *)caps, size); - - spice_server_char_device_wakeup(&vt->vdagent_sin); - - free(caps); -} -static void -dump_message(unsigned char *buf, int size) -{ - int i; + if (0) dump_message(buf, msg_size); - for (i = 0; i < size; i++) { - printf("%d %02X\n", i, buf[i]); - } + spice_server_char_device_wakeup(&vt->vdagent_sin); - exit(0); + free(caps); } -static void vdagent_grab_clipboard(spiceTerm *vt) +static void vdagent_grab_clipboard(spiceTerm *vt, uint8_t selection) { uint32_t size; - DPRINTF(0, "GRAB"); - - uint8_t selection = VD_AGENT_CLIPBOARD_SELECTION_PRIMARY; // fixme? - agent_owns_clipboard[selection] = 1; - size = 4; // fixme: HACK, because sizeof(VDAgentClipboardGrab) == 0; + size = 8; int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size; g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE); @@ -1697,9 +1726,9 @@ static void vdagent_grab_clipboard(spiceTerm *vt) VDIChunkHeader *hdr = (VDIChunkHeader *)buf; VDAgentMessage *msg = (VDAgentMessage *)&hdr[1]; - VDAgentClipboardGrab *grab = (VDAgentClipboardGrab *)&msg[1]; - *((uint32_t *)grab) = 0; + uint8_t *grab = (uint8_t *)&msg[1]; *((uint8_t *)grab) = selection; + *((uint32_t *)(grab + 4)) = VD_AGENT_CLIPBOARD_UTF8_TEXT; hdr->port = VDP_CLIENT_PORT; hdr->size = sizeof(VDAgentMessage) + size; @@ -1711,18 +1740,13 @@ static void vdagent_grab_clipboard(spiceTerm *vt) if (0) dump_message(buf, msg_size); - spice_server_char_device_wakeup(&vt->vdagent_sin); } -static void vdagent_request_clipboard(spiceTerm *vt) +static void vdagent_request_clipboard(spiceTerm *vt, uint8_t selection) { uint32_t size; - DPRINTF(0, "REQUEST"); - - uint8_t selection = VD_AGENT_CLIPBOARD_SELECTION_PRIMARY; // fixme? - agent_owns_clipboard[selection] = 1; size = 4 + sizeof(VDAgentClipboardRequest); @@ -1752,7 +1776,59 @@ static void vdagent_request_clipboard(spiceTerm *vt) if (0) dump_message(buf, msg_size); + spice_server_char_device_wakeup(&vt->vdagent_sin); +} + +static void vdagent_send_clipboard(spiceTerm *vt, uint8_t selection) +{ + uint32_t size; + if (selection != VD_AGENT_CLIPBOARD_SELECTION_PRIMARY) { + fprintf(stderr, "clipboard select %d is not supported\n", selection); + return; + } + + gchar *sel_data; + glong sel_len; + if (vt->utf8) { + sel_data = g_utf16_to_utf8(vt->selection, vt->selection_len, NULL, &sel_len, NULL); + } else { + sel_len = vt->selection_len; + sel_data = g_malloc(sel_len); + int i; + for (i = 0; i < sel_len; i++) { sel_data[i] = (char)vt->selection[i]; } + sel_data[sel_len] = 0; + } + + size = 8 + sel_len; + + int msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) + size; + g_assert((vdagent_write_buffer_pos + msg_size) < VDAGENT_WBUF_SIZE); + + unsigned char *buf = vdagent_write_buffer + vdagent_write_buffer_pos; + vdagent_write_buffer_pos += msg_size; + + memset(buf, 0, msg_size); + + VDIChunkHeader *hdr = (VDIChunkHeader *)buf; + VDAgentMessage *msg = (VDAgentMessage *)&hdr[1]; + uint8_t *data = (uint8_t *)&msg[1]; + *((uint8_t *)data) = selection; + data += 4; + *((uint32_t *)data) = VD_AGENT_CLIPBOARD_UTF8_TEXT; + data += 4; + + memcpy(data, sel_data, sel_len); + g_free(sel_data); + + hdr->port = VDP_CLIENT_PORT; + hdr->size = sizeof(VDAgentMessage) + size; + + msg->protocol = VD_AGENT_PROTOCOL; + msg->type = VD_AGENT_CLIPBOARD; + msg->opaque = 0; + msg->size = size; + spice_server_char_device_wakeup(&vt->vdagent_sin); } @@ -1770,6 +1846,11 @@ vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) DPRINTF(1, "%d %d %d %d", len, hdr->port, msg->protocol, msg->type); switch (msg->type) { + case VD_AGENT_KEYVAL: { + VDAgentKeyval *info = (VDAgentKeyval *)&msg[1]; + spiceterm_push_keyval(vt, info->keyval, info->flags); + break; + } case VD_AGENT_MOUSE_STATE: { VDAgentMouseState *info = (VDAgentMouseState *)&msg[1]; spiceterm_motion_event(vt, info->x, info->y, info->buttons); @@ -1777,12 +1858,12 @@ vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) } case VD_AGENT_ANNOUNCE_CAPABILITIES: { VDAgentAnnounceCapabilities *caps = (VDAgentAnnounceCapabilities *)&msg[1]; - DPRINTF(0, "VD_AGENT_ANNOUNCE_CAPABILITIES %d", caps->request); + DPRINTF(1, "VD_AGENT_ANNOUNCE_CAPABILITIES %d", caps->request); int i; int caps_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(hdr->size); for (i = 0; i < VD_AGENT_END_CAP; i++) { - DPRINTF(0, "CAPABILITIES %d %d", i, VD_AGENT_HAS_CAPABILITY(caps->caps, caps_size, i)); + DPRINTF(1, "CAPABILITIES %d %d", i, VD_AGENT_HAS_CAPABILITY(caps->caps, caps_size, i)); } vdagent_send_capabilities(vt, 0); @@ -1791,13 +1872,19 @@ vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) case VD_AGENT_CLIPBOARD_GRAB: { VDAgentClipboardGrab *grab = (VDAgentClipboardGrab *)&msg[1]; uint8_t selection = *((uint8_t *)grab); - DPRINTF(0, "VD_AGENT_CLIPBOARD_GRAB %d", selection); + DPRINTF(1, "VD_AGENT_CLIPBOARD_GRAB %d", selection); agent_owns_clipboard[selection] = 0; break; } case VD_AGENT_CLIPBOARD_REQUEST: { - DPRINTF(0, "VD_AGENT_CLIPBOARD_REQUEST"); - + uint8_t *req = (uint8_t *)&msg[1]; + uint8_t selection = *((uint8_t *)req); + uint32_t type = *((uint32_t *)(req + 4)); + + DPRINTF(1, "VD_AGENT_CLIPBOARD_REQUEST %d %d", selection, type); + + vdagent_send_clipboard(vt, selection); + break; } case VD_AGENT_CLIPBOARD: { @@ -1805,7 +1892,7 @@ vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) uint8_t selection = data[0]; uint32_t type = *(uint32_t *)(data + 4); int size = msg->size - 8; - DPRINTF(0, "VD_AGENT_CLIPBOARD %d %d %d", selection, type, size); + DPRINTF(1, "VD_AGENT_CLIPBOARD %d %d %d", selection, type, size); if (type == VD_AGENT_CLIPBOARD_UTF8_TEXT) { int i; @@ -1821,13 +1908,24 @@ vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) break; } case VD_AGENT_CLIPBOARD_RELEASE: { - DPRINTF(0, "VD_AGENT_CLIPBOARD_RELEASE"); - + uint8_t *data = (uint8_t *)&msg[1]; + uint8_t selection = data[0]; + + DPRINTF(0, "VD_AGENT_CLIPBOARD_RELEASE %d", selection); + break; } - case VD_AGENT_MONITORS_CONFIG: - /* ignore for now */ + case VD_AGENT_MONITORS_CONFIG: { + VDAgentMonitorsConfig *list = (VDAgentMonitorsConfig *)&msg[1]; + g_assert(list->num_of_monitors > 0); + DPRINTF(0, "VD_AGENT_MONITORS_CONFIG %d %d %d", list->num_of_monitors, + list->monitors[0].width, list->monitors[0].height); + + spiceterm_resize(vt, list->monitors[0].width, list->monitors[0].height); + + vdagent_reply(vt, VD_AGENT_MONITORS_CONFIG, VD_AGENT_SUCCESS); break; + } default: DPRINTF(0, "got uknown vdagent message type %d\n", msg->type); } @@ -1838,7 +1936,7 @@ vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) { - DPRINTF(0, "%d %d", len, vdagent_write_buffer_pos); + DPRINTF(1, "%d %d", len, vdagent_write_buffer_pos); g_assert(len >= 8); if (!vdagent_write_buffer_pos) { @@ -1848,13 +1946,12 @@ vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) int size = (len >= vdagent_write_buffer_pos) ? vdagent_write_buffer_pos : len; memcpy(buf, vdagent_write_buffer, size); if (size < vdagent_write_buffer_pos) { - DPRINTF(0, "MOVE %d", size); memmove(vdagent_write_buffer, vdagent_write_buffer + size, vdagent_write_buffer_pos - size); } vdagent_write_buffer_pos -= size; - DPRINTF(0, "RET %d %d", size, vdagent_write_buffer_pos); + DPRINTF(1, "RET %d %d", size, vdagent_write_buffer_pos); return size; } @@ -1874,36 +1971,16 @@ static SpiceCharDeviceInterface my_vdagent_sif = { .read = vmc_read, }; -static spiceTerm * -create_spiceterm(int argc, char** argv, int maxx, int maxy, guint timeout) +static void +init_spiceterm(spiceTerm *vt, uint32_t width, uint32_t height) { int i; - SpiceScreen *spice_screen; - - SpiceCoreInterface *core = basic_event_loop_init(); - spice_screen = spice_screen_new(core, timeout); - //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESS_OFF); - - spiceTerm *vt = (spiceTerm *)calloc (sizeof(spiceTerm), 1); - - vt->keyboard_sin.base.sif = &my_keyboard_sif.base; - spice_server_add_interface(spice_screen->server, &vt->keyboard_sin.base); - - vt->vdagent_sin.base.sif = &my_vdagent_sif.base; - vt->vdagent_sin.subtype = "vdagent"; - spice_server_add_interface(spice_screen->server, &vt->vdagent_sin.base); - - // screen->setXCutText = spiceterm_set_xcut_text; - // screen->ptrAddEvent = spiceterm_pointer_event; - // screen->newClientHook = new_client; - // screen->desktopName = "SPICE Command Terminal"; - - vt->maxx = spice_screen->width; - vt->maxy = spice_screen->height; + g_assert(vt != NULL); + g_assert(vt->screen != NULL); - vt->width = vt->maxx / 8; - vt->height = vt->maxy / 16; + vt->width = width / 8; + vt->height = height / 16; vt->total_height = vt->height * 20; vt->scroll_height = 0; @@ -1929,17 +2006,73 @@ create_spiceterm(int argc, char** argv, int maxx, int maxy, guint timeout) vt->cur_attrib = vt->default_attrib; + if (vt->cells) { + vt->cx = 0; + vt->cy = 0; + vt->cx_saved = 0; + vt->cy_saved = 0; + g_free(vt->cells); + } + vt->cells = (TextCell *)calloc (sizeof (TextCell), vt->width*vt->total_height); for (i = 0; i < vt->width*vt->total_height; i++) { vt->cells[i].ch = ' '; vt->cells[i].attrib = vt->default_attrib; } + + if (vt->altcells) { + g_free(vt->altcells); + } vt->altcells = (TextCell *)calloc (sizeof (TextCell), vt->width*vt->height); +} + +static void +spiceterm_resize(spiceTerm *vt, uint32_t width, uint32_t height) +{ + width = (width/8)*8; + height = (height/16)*16; + + if (vt->screen->width == width && vt->screen->height == height) { + return; + } + + DPRINTF(0, "width=%u height=%u", width, height); + + spice_screen_resize(vt->screen, width, height); + init_spiceterm(vt, width, height); + + struct winsize dimensions; + dimensions.ws_col = vt->width; + dimensions.ws_row = vt->height; + + ioctl(vt->pty, TIOCSWINSZ, &dimensions); +} + +static spiceTerm * +create_spiceterm(int argc, char** argv, uint32_t maxx, uint32_t maxy, guint timeout) +{ + SpiceCoreInterface *core = basic_event_loop_init(); + SpiceScreen *spice_screen = spice_screen_new(core, maxx, maxy, timeout); + + //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESS_OFF); + + spice_screen->image_cache = g_hash_table_new(g_int_hash, g_int_equal); + + spiceTerm *vt = (spiceTerm *)calloc (sizeof(spiceTerm), 1); + + vt->keyboard_sin.base.sif = &my_keyboard_sif.base; + spice_server_add_interface(spice_screen->server, &vt->keyboard_sin.base); + + vt->vdagent_sin.base.sif = &my_vdagent_sif.base; + vt->vdagent_sin.subtype = "vdagent"; + spice_server_add_interface(spice_screen->server, &vt->vdagent_sin.base); vt->screen = spice_screen; + init_spiceterm(vt, maxx, maxy); + return vt; } @@ -2021,7 +2154,7 @@ main (int argc, char** argv) if (0) print_usage(NULL); // fixme: - spiceTerm *vt = create_spiceterm (argc, argv, 745, 400, 10); + spiceTerm *vt = create_spiceterm (argc, argv, 744, 400, 10); setlocale(LC_ALL, ""); // set from environment @@ -2059,6 +2192,8 @@ main (int argc, char** argv) exit (-1); } + vt->pty = master; + /* watch for errors - we need to use glib directly because spice * does not have SPICE_WATCH_EVENT for this */ GIOChannel *channel = g_io_channel_unix_new(master);