8,12,10,14, 9,13,11,15 };
+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)
{
/* 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);
}
}
}
}
-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 && 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);
-
- // fixme: tell client we have something seletced
- //rfbGotXCutText (vt->screen, sel_latin1, len);
- }
-}
-
static void
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;
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) {
if (vt->y_displ != vt->y_base) {
vt->y_displ = vt->y_base;
- spiceterm_refresh (vt);
+ spiceterm_refresh(vt);
}
if (esc) {
}
}
-
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) {
.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,
};
+
/* vdagent interface - to get mouse/clipboarde support */
+
+#define VDAGENT_WBUF_SIZE (1024*50)
+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;
+ uint32_t size;
+
+ size = sizeof(*caps) + VD_AGENT_CAPS_BYTES;
+ caps = calloc(1, size);
+ g_assert(caps != NULL);
+
+ caps->request = request;
+ VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MOUSE_STATE);
+ VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG);
+ VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_REPLY);
+ VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
+ 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);
+
+ unsigned char *buf = vdagent_write_buffer + vdagent_write_buffer_pos;
+ vdagent_write_buffer_pos += msg_size;
+
+ VDIChunkHeader *hdr = (VDIChunkHeader *)buf;
+ VDAgentMessage *msg = (VDAgentMessage *)&hdr[1];
+
+ hdr->port = VDP_CLIENT_PORT;
+ hdr->size = sizeof(VDAgentMessage) + size;
+ msg->protocol = VD_AGENT_PROTOCOL;
+ msg->type = VD_AGENT_ANNOUNCE_CAPABILITIES;
+ msg->opaque = 0;
+ msg->size = size;
+
+ memcpy(buf + sizeof(VDIChunkHeader) + sizeof(VDAgentMessage), (uint8_t *)caps, size);
+
+ if (0) dump_message(buf, msg_size);
+
+ spice_server_char_device_wakeup(&vt->vdagent_sin);
+
+ free(caps);
+}
+
+static void vdagent_grab_clipboard(spiceTerm *vt, uint8_t selection)
+{
+ uint32_t size;
+
+ agent_owns_clipboard[selection] = 1;
+
+ size = 8;
+
+ 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 *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;
+
+ msg->protocol = VD_AGENT_PROTOCOL;
+ msg->type = VD_AGENT_CLIPBOARD_GRAB;
+ msg->opaque = 0;
+ msg->size = size;
+
+ if (0) dump_message(buf, msg_size);
+
+ spice_server_char_device_wakeup(&vt->vdagent_sin);
+}
+
+static void vdagent_request_clipboard(spiceTerm *vt, uint8_t selection)
+{
+ uint32_t size;
+
+ agent_owns_clipboard[selection] = 1;
+
+ size = 4 + sizeof(VDAgentClipboardRequest);
+
+ 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];
+ *((uint32_t *)data) = 0;
+ data[0] = selection;
+ ((uint32_t *)data)[1] = VD_AGENT_CLIPBOARD_UTF8_TEXT;
+
+ hdr->port = VDP_CLIENT_PORT;
+ hdr->size = sizeof(VDAgentMessage) + size;
+
+ msg->protocol = VD_AGENT_PROTOCOL;
+ msg->type = VD_AGENT_CLIPBOARD_REQUEST;
+ msg->opaque = 0;
+ msg->size = size;
+
+ 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);
+}
+
static int
vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
{
DPRINTF(1, "%d %d %d %d", len, hdr->port, msg->protocol, msg->type);
- if (msg->type == VD_AGENT_MOUSE_STATE) {
+ 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);
- } else if (msg->type == VD_AGENT_ANNOUNCE_CAPABILITIES) {
- /* ignore for now */
- } else if (msg->type == VD_AGENT_MONITORS_CONFIG) {
- /* ignore for now */
- } else {
+ break;
+ }
+ case VD_AGENT_ANNOUNCE_CAPABILITIES: {
+ VDAgentAnnounceCapabilities *caps = (VDAgentAnnounceCapabilities *)&msg[1];
+ 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(1, "CAPABILITIES %d %d", i, VD_AGENT_HAS_CAPABILITY(caps->caps, caps_size, i));
+ }
+
+ vdagent_send_capabilities(vt, 0);
+ break;
+ }
+ case VD_AGENT_CLIPBOARD_GRAB: {
+ VDAgentClipboardGrab *grab = (VDAgentClipboardGrab *)&msg[1];
+ uint8_t selection = *((uint8_t *)grab);
+ DPRINTF(1, "VD_AGENT_CLIPBOARD_GRAB %d", selection);
+ agent_owns_clipboard[selection] = 0;
+ break;
+ }
+ case 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: {
+ uint8_t *data = (uint8_t *)&msg[1];
+ uint8_t selection = data[0];
+ uint32_t type = *(uint32_t *)(data + 4);
+ int size = msg->size - 8;
+ DPRINTF(1, "VD_AGENT_CLIPBOARD %d %d %d", selection, type, size);
+
+ if (type == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
+ int i;
+ for (i = 0; i < size; i++) {
+ if ((vt->ibuf_count + 1) < IBUFSIZE) {
+ vt->ibuf[vt->ibuf_count++] = *(char *)(data + 8 + i);
+ } else {
+ fprintf(stderr, "warning: input buffer overflow\n");
+ }
+ }
+ spiceterm_update_watch_mask(vt, TRUE);
+ }
+ break;
+ }
+ case 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: {
+ 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);
}
static int
vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
{
- DPRINTF(1, "%d", len);
+ DPRINTF(1, "%d %d", len, vdagent_write_buffer_pos);
+ g_assert(len >= 8);
- return 0;
+ if (!vdagent_write_buffer_pos) {
+ return 0;
+ }
+
+ int size = (len >= vdagent_write_buffer_pos) ? vdagent_write_buffer_pos : len;
+ memcpy(buf, vdagent_write_buffer, size);
+ if (size < vdagent_write_buffer_pos) {
+ memmove(vdagent_write_buffer, vdagent_write_buffer + size,
+ vdagent_write_buffer_pos - size);
+ }
+ vdagent_write_buffer_pos -= size;
+
+ DPRINTF(1, "RET %d %d", size, vdagent_write_buffer_pos);
+ return size;
}
static void
.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;
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;
}
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
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);