daktronics / cef-mixer

High Performance off-screen rendering (OSR) demo using CEF
MIT License
228 stars 57 forks source link

Key Event and Typing on OSR MIXER #16

Open mirufa1121 opened 5 years ago

mirufa1121 commented 5 years ago

Excuse me ! can you help me press key event on mixer as default browser ? me using PreTranslateMessage(MSG* pMsg) on C++/MFC for KEY_DOWN,KEY_UP and broadcast key event for all Layer by code void Composition::key_press(KeyPress key_event, char keycode) { decltype(layers) layers; { lockguard guard(lock); layers.assign(layers.begin(), layers.end()); } for (auto const& layer : layers) { layer->key_press(key_event,key_code); } }

WebView class me Using void WebView::key_press(KeyPress key_event, char key_code) { auto const browser = safe_browser();

if (browser)
{
    CefKeyEvent keyEvent;
    keyEvent.type = cef_key_event_type_t::KEYEVENT_CHAR;
    keyEvent.windows_key_code = key_code;
    browser->GetHost()->SendKeyEvent(keyEvent);

    switch (key_event)
    {
    case KeyPress::Up: keyEvent.type = cef_key_event_type_t::KEYEVENT_KEYUP; break;
    case KeyPress::Down: keyEvent.type = cef_key_event_type_t::KEYEVENT_KEYDOWN; break;
    case KeyPress::Char: keyEvent.type = cef_key_event_type_t::KEYEVENT_CHAR;
    default:break;
    }
    browser->GetHost()->SendKeyEvent(keyEvent);
}

} but me press key value is double , and can't using special key same Ctrl+... Shift + ...

wesselsga commented 5 years ago

I might be able to assist if I can see the code for your project. It's hard to know what is going on without seeing more of the MFC side.

I have done something similar to the following where I ignore WM_KEYDOWN forwarding when the message simply represents the modifier key:

auto const key = static_cast<uint16_t>(virtkey & 0x0000ffff);

// ignore when modifier keys are the only key sent
if (key == VK_CONTROL || key == VK_SHIFT || key == VK_MENU) {
   return;
}

// are the shift and/or ctrls down as well?
// fill out a structure representing all key information

KeyEvent kevent;
kevent.set_type(KeyPress::Down);
kevent.set_code(key);
kevent.set_alt(GetKeyState(VK_MENU) < 0);
kevent.set_ctrl(GetKeyState(VK_CONTROL) < 0);
kevent.set_shift(GetKeyState(VK_SHIFT) < 0);

composition->key_press(kevent);
mirufa1121 commented 5 years ago

thanks you answer ! i was able to use by sample code on https://bitbucket.org/chromiumembedded/cef/src/aefb5ccce879f308f0bcc3ac719c86defe2f9715/tests/cefclient/browser/osr_window_win.cc?at=master&fileviewer=file-view-default

but i not understand browser can't input by lostfocus . if me click other windows and use Ctrl + Tab for target ==> ok input .if me using Tab button for change text input is ok ,but if me click change input by mouse ... can't input :)

Code in my Dialog `BOOL CVIEBrowserDlg::PreTranslateMessage(MSG* pMsg) { switch (pMsg->message) { case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_MOUSEMOVE: case WM_MOUSELEAVE: case WM_MOUSEWHEEL: OnMouseEvent(pMsg->message, pMsg->wParam, pMsg->lParam); break;

    case WM_SIZE:
        //OnSize();
        break;

/*  case WM_SETFOCUS:
    case WM_KILLFOCUS:
        OnFocus(pMsg->message == WM_SETFOCUS);
        break;*/

    case WM_CAPTURECHANGED:
    case WM_CANCELMODE:
        //OnCaptureLost();
        break;

    case WM_SYSCHAR:
    case WM_SYSKEYDOWN:
    case WM_SYSKEYUP:
    case WM_KEYDOWN:
    case WM_KEYUP:
    case WM_CHAR:
        OnKeyEvent(pMsg->message, pMsg->wParam, pMsg->lParam);
        break;

    case WM_PAINT:
        //self->OnPaint();
        return 0;

    case WM_ERASEBKGND:
        //if (OnEraseBkgnd())
            break;
        // Don't erase the background.
        return 0;

    //case WM_NCDESTROY:
        // Clear the reference to |self|.
        //SetUserDataPtr(hWnd, NULL);
        //self->hwnd_ = NULL;
        //break;
}

// Chặn sự kiện keyDown
if (pMsg->message == WM_KEYDOWN)
{
    if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
    {
        if (GetWindowLong(pMsg->hwnd, GWL_STYLE) & ES_MULTILINE) {
            return CDialog::PreTranslateMessage(pMsg);
        }
        ::SendMessage(::GetFocus(), pMsg->message, pMsg->wParam, pMsg->lParam);
        return TRUE;
    }
}

return 0;

} `

Code in WebView class: `void WebView::OnMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) {

auto const browser = safe_browser();

CefRefPtr<CefBrowserHost> browser_host;
if (browser)
    browser_host = browser->GetHost();

LONG currentTime = 0;
bool cancelPreviousClick = false;

if (message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN ||
    message == WM_MBUTTONDOWN || message == WM_MOUSEMOVE ||
    message == WM_MOUSELEAVE) {
    currentTime = GetMessageTime();
    int x = GET_X_LPARAM(lParam);
    int y = GET_Y_LPARAM(lParam);
    cancelPreviousClick =
        (abs(last_click_x_ - x) > (GetSystemMetrics(SM_CXDOUBLECLK) / 2))
        || (abs(last_click_y_ - y) > (GetSystemMetrics(SM_CYDOUBLECLK) / 2))
        || ((currentTime - last_click_time_) > GetDoubleClickTime());
    if (cancelPreviousClick &&
        (message == WM_MOUSEMOVE || message == WM_MOUSELEAVE)) {
        last_click_count_ = 0;
        last_click_x_ = 0;
        last_click_y_ = 0;
        last_click_time_ = 0;
    }
}

switch (message) {
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN: {
    ::SetCapture(browser_host->GetWindowHandle());
    ::SetFocus(browser_host->GetWindowHandle());
    int x = GET_X_LPARAM(lParam);
    int y = GET_Y_LPARAM(lParam);
    if (wParam & MK_SHIFT) {
        // Start rotation effect.
        last_mouse_pos_.x = current_mouse_pos_.x = x;
        last_mouse_pos_.y = current_mouse_pos_.y = y;
        mouse_rotation_ = true;
    }
    else {
        CefBrowserHost::MouseButtonType btnType =
            (message == WM_LBUTTONDOWN ? MBT_LEFT : (
                message == WM_RBUTTONDOWN ? MBT_RIGHT : MBT_MIDDLE));
        if (!cancelPreviousClick && (btnType == last_click_button_)) {
            ++last_click_count_;
        }
        else {
            last_click_count_ = 1;
            last_click_x_ = x;
            last_click_y_ = y;
        }
        last_click_time_ = currentTime;
        last_click_button_ = btnType;

        CefRefPtr<CefBrowserHost> browser_host = browser->GetHost();
        if (browser_host) {
            CefMouseEvent mouse_event;
            mouse_event.x = x;
            mouse_event.y = y;
            last_mouse_down_on_view_ = !IsOverPopupWidget(x, y);
            ApplyPopupOffset(mouse_event.x, mouse_event.y);
            mouse_event.modifiers = client::GetCefMouseModifiers(wParam);
            browser_host->SendMouseClickEvent(mouse_event, btnType, false,
                last_click_count_);
        }
    }
} break;

case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
    if (GetCapture() == browser->GetHost()->GetWindowHandle())
        ReleaseCapture();
    if (mouse_rotation_) {
        // End rotation effect.
        /*mouse_rotation_ = false;
        renderer_.SetSpin(0, 0);
        Invalidate();*/
    }
    else {
        int x = GET_X_LPARAM(lParam);
        int y = GET_Y_LPARAM(lParam);
        CefBrowserHost::MouseButtonType btnType =
            (message == WM_LBUTTONUP ? MBT_LEFT : (
                message == WM_RBUTTONUP ? MBT_RIGHT : MBT_MIDDLE));
        if (browser_host) {
            CefMouseEvent mouse_event;
            mouse_event.x = x;
            mouse_event.y = y;
            if (last_mouse_down_on_view_ &&
                IsOverPopupWidget(x, y) &&
                (GetPopupXOffset() || GetPopupYOffset())) {
                break;
            }
            ApplyPopupOffset(mouse_event.x, mouse_event.y);
            mouse_event.modifiers = client::GetCefMouseModifiers(wParam);
            browser_host->SendMouseClickEvent(mouse_event, btnType, true,
                last_click_count_);
        }
    }
    break;

case WM_MOUSEMOVE: {
    int x = GET_X_LPARAM(lParam);
    int y = GET_Y_LPARAM(lParam);
    if (mouse_rotation_) {
        // Apply rotation effect.
        current_mouse_pos_.x = x;
        current_mouse_pos_.y = y;
    /*  renderer_.IncrementSpin(
            current_mouse_pos_.x - last_mouse_pos_.x,
            current_mouse_pos_.y - last_mouse_pos_.y);*/
        last_mouse_pos_.x = current_mouse_pos_.x;
        last_mouse_pos_.y = current_mouse_pos_.y;
        //Invalidate();
    }
    else {
        if (!mouse_tracking_) {
            // Start tracking mouse leave. Required for the WM_MOUSELEAVE event to
            // be generated.
            TRACKMOUSEEVENT tme;
            tme.cbSize = sizeof(TRACKMOUSEEVENT);
            tme.dwFlags = TME_LEAVE;
            tme.hwndTrack = browser->GetHost()->GetWindowHandle();
            TrackMouseEvent(&tme);
            mouse_tracking_ = true;
        }

        if (browser_host) {
            CefMouseEvent mouse_event;
            mouse_event.x = x;
            mouse_event.y = y;
            ApplyPopupOffset(mouse_event.x, mouse_event.y);
            mouse_event.modifiers = client::GetCefMouseModifiers(wParam);
            browser_host->SendMouseMoveEvent(mouse_event, false);
        }
    }
    break;
}

case WM_MOUSELEAVE: {
    if (mouse_tracking_) {
        // Stop tracking mouse leave.
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_LEAVE & TME_CANCEL;
        tme.hwndTrack = browser->GetHost()->GetWindowHandle();
        TrackMouseEvent(&tme);
        mouse_tracking_ = false;
    }

    if (browser_host) {
        // Determine the cursor position in screen coordinates.
        POINT p;
        ::GetCursorPos(&p);
        ::ScreenToClient(browser->GetHost()->GetWindowHandle(), &p);

        CefMouseEvent mouse_event;
        mouse_event.x = p.x;
        mouse_event.y = p.y;
        mouse_event.modifiers = client::GetCefMouseModifiers(wParam);
        browser_host->SendMouseMoveEvent(mouse_event, true);
    }
} break;

case WM_MOUSEWHEEL:
    if (browser_host) {
        POINT screen_point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
        HWND scrolled_wnd = ::WindowFromPoint(screen_point);
        if (scrolled_wnd != browser->GetHost()->GetWindowHandle())
            break;

        ScreenToClient(browser->GetHost()->GetWindowHandle(), &screen_point);
        int delta = GET_WHEEL_DELTA_WPARAM(wParam);

        CefMouseEvent mouse_event;
        mouse_event.x = screen_point.x;
        mouse_event.y = screen_point.y;
        ApplyPopupOffset(mouse_event.x, mouse_event.y);
        mouse_event.modifiers = client::GetCefMouseModifiers(wParam);

        browser_host->SendMouseWheelEvent(mouse_event,
            client::IsKeyDown(VK_SHIFT) ? delta : 0,
            !client::IsKeyDown(VK_SHIFT) ? delta : 0);
    }
    break;
}

} void WebView::OnKeyEvent(UINT message, WPARAM wParam, LPARAM lParam) {

auto const browser = safe_browser();

if (browser)
{
    CefKeyEvent event;
    event.windows_key_code = wParam;
    event.native_key_code  = lParam;
    event.is_system_key = message == WM_SYSCHAR ||
        message == WM_SYSKEYDOWN ||
        message == WM_SYSKEYUP;

    if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
        event.type = KEYEVENT_RAWKEYDOWN;
    else if (message == WM_KEYUP || message == WM_SYSKEYUP)
        event.type = KEYEVENT_KEYUP;
    else
        event.type = KEYEVENT_CHAR;

    event.modifiers = client::GetCefKeyboardModifiers(wParam, lParam);

    browser->GetHost()->SendKeyEvent(event);
}

}`

mirufa1121 commented 5 years ago

if possible ! Can you help me with the capture screen problem with the on paint function or not ! i want using screen image for computer vision but capture on windows . I used to capture it via Handler windows but could not take a picture when the window was overlaid in windows 7 but windows 10 is ok.