Chinaunix首页 | 论坛 | 博客
  • 博客访问: 212975
  • 博文数量: 76
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 513
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-23 00:06
个人简介

展示自己、证明自己

文章分类

全部博文(76)

文章存档

2018年(1)

2014年(55)

2013年(20)

我的朋友

分类: C/C++

2014-08-04 10:38:00

spice工作过程,相当繁琐。其中经过组件依次为
1.客户端(例如spicec,spicy)
2.spice-server
3.qemu-kvm
4.guest
具体流程可参照网上资料,下面分析spice鼠标移动事件工作过程,spice鼠标相对其他是比较简单的。

1.客户端spice mouse鼠标的移动操作
<1>鼠标在Linux spice客户端进行移动时
<2>X11引擎捕获该事件
<3>发送鼠标移动信息给spice server.
<4>客户端进行鼠标设置

void RedWindow_p::win_proc(XEvent& event)
{
 switch (event.type) {
    case MotionNotify: {
        SpicePoint size = red_window->get_size();
        if (event.xmotion.x >= 0 && event.xmotion.y >= 0 &&
            event.xmotion.x < size.x && event.xmotion.y < size.y) {
            SpicePoint origin = red_window->get_origin();
            red_window->get_listener().on_pointer_motion(event.xmotion.x - origin.x,
                                                         event.xmotion.y - origin.y,
                                                         to_red_buttons_state(event.xmotion.state));
        }
        break;
    }

}
void RedScreen::on_pointer_motion(int x, int y, unsigned int buttons_state)
{                                                        
    if (_mouse_captured) {                               
        on_mouse_motion(x, y, buttons_state);
        return;
    }   
    
    _pointer_pos.x = x;
    _pointer_pos.y = y;
    _mouse_botton_state = buttons_state;
                        
    if (update_pointer_layer() || !_pointer_layer) {
        return;
    }
        
    _pointer_layer->on_pointer_motion(x, y, buttons_state);
}

void RedScreen::on_mouse_motion(int x, int y, unsigned int buttons_state)
{   
    if (x != _mouse_anchor_point.x || y != _mouse_anchor_point.y) {
        _owner.on_mouse_motion(x - _mouse_anchor_point.x,
                               y - _mouse_anchor_point.y,
                               buttons_state);
        reset_mouse_pos();
    }
}

void Application::on_mouse_motion(int dx, int dy, int buttons_state)
{
    _mouse_handler->on_mouse_motion(dx, dy, buttons_state);
}

void InputsChannel::on_mouse_motion(int dx, int dy, int buttons_state)
{
    Lock lock(_motion_lock);
    _mouse_buttons_state = buttons_state;
    _mouse_dx += dx;
    _mouse_dy += dy;
    if (!_active_motion && _motion_count < SPICE_INPUT_MOTION_ACK_BUNCH * 2) {
        _active_motion = true;
        _motion_count++;
        post_message(new MotionMessage(*this));
    }   
}

void RedScreen::reset_mouse_pos()
{
    _window.set_mouse_position(_mouse_anchor_point.x, _mouse_anchor_point.y);
}

void RedWindow::set_mouse_position(int x, int y)
{
    XWarpPointer(x_display, None, _win, 0, 0, 0, 0, x + get_origin().x, y + get_origin().y);
}

2.服务器端 spice mouse鼠标的移动信息处理
<1> 按照spice protocal协议解析客户端放送消息
<2>通过VDI接口调用,进入qemu-kvm
static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type,
                                        void *message)
{
    case SPICE_MSGC_INPUTS_MOUSE_MOTION: {
        SpiceMsgcMouseMotion *mouse_motion = (SpiceMsgcMouseMotion *)buf;

        if (++icc->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
            !g_inputs_channel->src_during_migrate) {
            red_channel_client_pipe_add_type(rcc, PIPE_ITEM_MOUSE_MOTION_ACK);
            icc->motion_count = 0;
        }
        if (mouse && reds_get_mouse_mode() == SPICE_MOUSE_MODE_SERVER) {
            SpiceMouseInterface *sif;
            sif = SPICE_CONTAINEROF(mouse->base.sif, SpiceMouseInterface, base);
            sif->motion(mouse,
                        mouse_motion->dx, mouse_motion->dy, 0,
                        RED_MOUSE_STATE_TO_LOCAL(mouse_motion->buttons_state));
        }
        break;
    }

qemu-kvm 提供VDI接口
static const SpiceMouseInterface mouse_interface = {
    .base.type          = SPICE_INTERFACE_MOUSE,
    .base.description   = "mouse",
    .base.major_version = SPICE_INTERFACE_MOUSE_MAJOR,
    .base.minor_version = SPICE_INTERFACE_MOUSE_MINOR,
    .motion             = mouse_motion,
    .buttons            = mouse_buttons,
};

static void mouse_motion(SpiceMouseInstance *sin, int dx, int dy, int dz,
                         uint32_t buttons_state)
{
    kbd_mouse_event(dx, dy, dz, map_buttons(buttons_state));
}

void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
{                        
    QEMUPutMouseEntry *entry;
    QEMUPutMouseEvent *mouse_event;
    void *mouse_event_opaque;
    int width;

    if (QTAILQ_EMPTY(&mouse_handlers)) {
        return;
    }

    entry = QTAILQ_FIRST(&mouse_handlers);
    
    mouse_event = entry->qemu_put_mouse_event;
    mouse_event_opaque = entry->qemu_put_mouse_event_opaque;
    
    if (mouse_event) {  
        if (graphic_rotate) {
            if (entry->qemu_put_mouse_event_absolute)
                width = 0x7fff;
            else
                width = graphic_width - 1;
            mouse_event(mouse_event_opaque,
                        width - dy, dx, dz, buttons_state);
        } else
            mouse_event(mouse_event_opaque,
                        dx, dy, dz, buttons_state);
    }
}

3.qemu-kvm 提供ps2 mouse鼠标硬件的模拟
<1>VDI接口是虚拟设备的接口
<2>该接口操从虚拟设备,从而影响客户机操作系统鼠标设备驱动。
qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
qemu_add_mouse_event_handler(usb_pointer_event, s,
static void ps2_mouse_event(void *opaque,
                            int dx, int dy, int dz, int buttons_state)
{
    PS2MouseState *s = opaque;

    /* check if deltas are recorded when disabled */
    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
        return;

    s->mouse_dx += dx;
    s->mouse_dy -= dy;
    s->mouse_dz += dz;
    /* XXX: SDL sometimes generates nul events: we delete them */
    if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
        s->mouse_buttons == buttons_state)
        return;
    s->mouse_buttons = buttons_state;

    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
        (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
        for(;;) {
            /* if not remote, send event. Multiple events are sent if
               too big deltas */
            ps2_mouse_send_packet(s);
            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
                break;
        }
    }
}


http://blog.csdn.net/zhuriyuxiao/article/details/8845122
阅读(3015) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~