]> git.proxmox.com Git - spiceterm.git/blobdiff - screen.c
implement resize
[spiceterm.git] / screen.c
index 1dbbedba89b4591837c1506e13c0ea9731e7b498..ff36f18d98ef35ffd4449c48b7c8060ad5184312 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -39,6 +39,7 @@
 #include <spice/enums.h>
 #include <spice/macros.h>
 #include <spice/qxl_dev.h>
+#include <spice/vd_agent.h>
 
 #include "glyphs.h"
 
@@ -89,10 +90,7 @@ spice_screen_destroy_update(SimpleSpiceUpdate *update)
     g_free(update);
 }
 
-#define DEFAULT_WIDTH 640
-#define DEFAULT_HEIGHT 320
-
-static int unique = 1;
+static int unique = 0x0ffff + 1;
 
 static void 
 set_cmd(QXLCommandExt *ext, uint32_t type, QXLPHYSICAL data)
@@ -134,7 +132,7 @@ push_command(SpiceScreen *spice_screen, QXLCommandExt *ext)
 
 /* bitmap are freed, so they must be allocated with g_malloc */
 static SimpleSpiceUpdate *
-spice_screen_update_from_bitmap_cmd(uint32_t surface_id, QXLRect bbox, uint8_t *bitmap)
+spice_screen_update_from_bitmap_cmd(uint32_t surface_id, QXLRect bbox, uint8_t *bitmap, int cache_id)
 {
     SimpleSpiceUpdate *update;
     QXLDrawable *drawable;
@@ -165,7 +163,11 @@ spice_screen_update_from_bitmap_cmd(uint32_t surface_id, QXLRect bbox, uint8_t *
     drawable->u.copy.src_area.right  = bw;
     drawable->u.copy.src_area.bottom = bh;
 
-    QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, unique);
+    if (cache_id) {
+        QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, cache_id);
+    } else {
+        QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ++unique);
+    }
     image->descriptor.type   = SPICE_IMAGE_TYPE_BITMAP;
     image->bitmap.flags      = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN;
     image->bitmap.stride     = bw * 4;
@@ -182,7 +184,7 @@ spice_screen_update_from_bitmap_cmd(uint32_t surface_id, QXLRect bbox, uint8_t *
 
 static SimpleSpiceUpdate *
 spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c, 
-                           int fg, int bg)
+                           int fg, int bg, gboolean uline)
 {
     int top, left;
     uint8_t *dst;
@@ -190,12 +192,15 @@ spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c,
     int bw, bh;
     int i, j;
     QXLRect bbox;
+    int cache_id = 0;
+
+    if (!uline && c < 256) {
+        cache_id = ((fg << 12) | (bg << 8) | (c & 255)) & 0x0ffff;
+    }
 
     left = x*8;
     top = y*16;
  
-    unique++;
-
     bw       = 8;
     bh       = 16;
 
@@ -215,12 +220,13 @@ spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c,
     unsigned char bgc_green = default_grn[bg];
 
     for (j = 0; j < 16; j++) {
+        gboolean ul = (j == 14) && uline;
         for (i = 0; i < 8; i++) {
-            if ((i&7) == 0) {
+            if (i == 0) {
                 d=*data;
                 data++;
             }
-            if (d&0x80) {
+            if (ul || d&0x80) {
                  *(dst) = fgc_blue;
                  *(dst+1) = fgc_green;
                  *(dst+2) = fgc_red;
@@ -239,7 +245,7 @@ spice_screen_draw_char_cmd(SpiceScreen *spice_screen, int x, int y, int c,
     bbox.left = left; bbox.top = top;
     bbox.right = left + bw; bbox.bottom = top + bh;
 
-    return spice_screen_update_from_bitmap_cmd(0, bbox, bitmap);
+    return spice_screen_update_from_bitmap_cmd(0, bbox, bitmap, cache_id);
 }
 
 void 
@@ -341,6 +347,22 @@ create_primary_surface(SpiceScreen *spice_screen, uint32_t width,
     qxl_worker->create_primary_surface(qxl_worker, 0, &surface);
 }
 
+void 
+spice_screen_resize(SpiceScreen *spice_screen, uint32_t width,
+                    uint32_t height)
+{
+    QXLWorker *qxl_worker = spice_screen->qxl_worker;
+
+    if (spice_screen->width == width && spice_screen->height == height) {
+        return;
+    }
+
+    qxl_worker->destroy_primary_surface(qxl_worker, 0);
+
+    create_primary_surface(spice_screen, width, height);
+}
+                       
+
 QXLDevMemSlot slot = {
     .slot_group_id = MEM_SLOT_GROUP_ID,
     .slot_id = 0,
@@ -362,7 +384,7 @@ attache_worker(QXLInstance *qin, QXLWorker *_qxl_worker)
  
     spice_screen->qxl_worker = _qxl_worker;
     spice_screen->qxl_worker->add_memslot(spice_screen->qxl_worker, &slot);
-    create_primary_surface(spice_screen, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    create_primary_surface(spice_screen, spice_screen->width, spice_screen->height);
     spice_screen->qxl_worker->start(spice_screen->qxl_worker);
 }
 
@@ -558,7 +580,7 @@ set_client_capabilities(QXLInstance *qin, uint8_t client_present,
 {
     SpiceScreen *spice_screen = SPICE_CONTAINEROF(qin, SpiceScreen, qxl_instance);
 
-    DPRINTF(1, "%s: present %d caps %d", __func__, client_present, caps[0]);
+    DPRINTF(1, "present %d caps %d", client_present, caps[0]);
 
     if (spice_screen->on_client_connected && client_present) {
         spice_screen->on_client_connected(spice_screen);
@@ -575,7 +597,7 @@ client_connected(SpiceScreen *spice_screen)
 {
     client_count++;
 
-    DPRINTF(1, "%s: client_count = %d", __func__, client_count);
+    DPRINTF(1, "client_count = %d", client_count);
 }
 
 static void 
@@ -583,7 +605,7 @@ client_disconnected(SpiceScreen *spice_screen)
 {    
     if (client_count > 0) {
         client_count--;
-        DPRINTF(1, "%s: client_count = %d", __func__, client_count);
+        DPRINTF(1, "client_count = %d", client_count);
         exit(0); // fixme: cleanup?
     }
 }
@@ -623,60 +645,21 @@ QXLInterface display_sif = {
     .set_client_capabilities = set_client_capabilities,
 };
 
-void 
-spice_screen_add_display_interface(SpiceScreen* spice_screen)
-{
-    spice_server_add_interface(spice_screen->server, &spice_screen->qxl_instance.base);
-}
-
-/* vdagent interface - not sure why we need that? */
-static int 
-vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
-{
-    return len;
-}
-
-static int 
-vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
-{
-    return 0;
-}
-
-static void 
-vmc_state(SpiceCharDeviceInstance *sin, int connected)
-{
-
-}
-
-static SpiceCharDeviceInterface vdagent_sif = {
-    .base.type          = SPICE_INTERFACE_CHAR_DEVICE,
-    .base.description   = "spice virtual channel char device",
-    .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
-    .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
-    .state              = vmc_state,
-    .write              = vmc_write,
-    .read               = vmc_read,
-};
-
-SpiceCharDeviceInstance vdagent_sin = {
-    .base = {
-        .sif = &vdagent_sif.base,
-    },
-    .subtype = "vdagent",
-};
-
-void 
-spice_screen_add_agent_interface(SpiceServer *server)
-{
-    spice_server_add_interface(server, &vdagent_sin.base);
-}
 
 void 
-spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar ch, TextAttributes attrib)
+spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar2 ch, 
+                       TextAttributes attrib)
 {
     int fg, bg;
 
+    int invers;
     if (attrib.invers) {
+        invers = attrib.selected ? 0 : 1;
+    } else {
+        invers = attrib.selected ? 1 : 0;
+    }        
+
+    if (invers) {
         bg = attrib.fgcol;
         fg = attrib.bgcol;
     } else {
@@ -690,25 +673,23 @@ spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar ch, Tex
 
     // unsuported attributes = (attrib.blink || attrib.unvisible)
 
-    // fixme:
-    //if (attrib.uline) {
-    //rfbDrawLine (vt->screen, rx, ry + 14, rxe, ry + 14, fg);
-    //}
-
     int c = vt_fontmap[ch];
 
     SimpleSpiceUpdate *update;
-    update = spice_screen_draw_char_cmd(spice_screen, x, y, c, fg, bg);
+    update = spice_screen_draw_char_cmd(spice_screen, x, y, c, fg, bg, attrib.uline);
     push_command(spice_screen, &update->ext);
 }
 
 SpiceScreen *
-spice_screen_new(SpiceCoreInterface *core)
+spice_screen_new(SpiceCoreInterface *core, uint32_t width, uint32_t height, guint timeout)
 {
     int port = 5912;
     SpiceScreen *spice_screen = g_new0(SpiceScreen, 1);
     SpiceServer* server = spice_server_new();
 
+    spice_screen->width = width;
+    spice_screen->height = height;
+
     spice_screen->command_cond = g_cond_new();
     spice_screen->command_mutex = g_mutex_new();
 
@@ -735,9 +716,10 @@ spice_screen_new(SpiceCoreInterface *core)
 
     cursor_init();
 
-    int timeout = 10; // max time to wait for client connection
     spice_screen->conn_timeout_timer = core->timer_add(do_conn_timeout, spice_screen);
     spice_screen->core->timer_start(spice_screen->conn_timeout_timer, timeout*1000);
 
+    spice_server_add_interface(spice_screen->server, &spice_screen->qxl_instance.base);
+
     return spice_screen;
 }