Пример #1
0
LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    m_inputEvent.keyboardModifiers = 0;
    if(IsKeyDown(VK_CONTROL))
        m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier;
    if(IsKeyDown(VK_SHIFT))
        m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier;
    if(IsKeyDown(VK_MENU))
        m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier;

    switch(uMsg)
    {
        case WM_SETCURSOR: {
            if(m_cursor)
                SetCursor(m_cursor);
            else
                return DefWindowProc(hWnd, uMsg, wParam, lParam);
            break;
        }
        case WM_ACTIVATE: {
            m_focused = !(wParam == WA_INACTIVE);
            releaseAllKeys();
            break;
        }
        case WM_SETFOCUS:
        case WM_KILLFOCUS: {
            releaseAllKeys();
            break;
        }
        case WM_CHAR: {
            if(wParam >= 32 && wParam <= 255) {
                m_inputEvent.reset(Fw::KeyTextInputEvent);
                m_inputEvent.keyText = wParam;
                if(m_onInputEvent)
                    m_onInputEvent(m_inputEvent);
            }
            break;
        }
        case WM_CLOSE: {
            m_onClose();
            break;
        }
        case WM_KEYDOWN: {
            processKeyDown(retranslateVirtualKey(wParam, lParam));
            break;
        }
        case WM_KEYUP: {
            processKeyUp(retranslateVirtualKey(wParam, lParam));
            break;
        }
        case WM_SYSKEYUP: {
            processKeyUp(retranslateVirtualKey(wParam, lParam));
            break;
        }
        case WM_SYSKEYDOWN: {
            if(wParam == VK_F4 && m_inputEvent.keyboardModifiers & Fw::KeyboardAltModifier)
                return DefWindowProc(hWnd, uMsg, wParam, lParam);

            processKeyDown(retranslateVirtualKey(wParam, lParam));
            break;
        }
        case WM_LBUTTONDOWN: {
            SetCapture(m_window);
            m_inputEvent.reset(Fw::MousePressInputEvent);
            m_inputEvent.mouseButton = Fw::MouseLeftButton;
            m_mouseButtonStates[Fw::MouseLeftButton] = true;
            if(m_onInputEvent)
                m_onInputEvent(m_inputEvent);
            break;
        }
        case WM_LBUTTONUP: {
            SetCapture(NULL);
            m_inputEvent.reset(Fw::MouseReleaseInputEvent);
            m_inputEvent.mouseButton = Fw::MouseLeftButton;
            m_mouseButtonStates[Fw::MouseLeftButton] = false;
            if(m_onInputEvent)
                m_onInputEvent(m_inputEvent);
            break;
        }
        case WM_MBUTTONDOWN: {
            SetCapture(m_window);
            m_inputEvent.reset(Fw::MousePressInputEvent);
            m_inputEvent.mouseButton = Fw::MouseMidButton;
            m_mouseButtonStates[Fw::MouseMidButton] = true;
            if(m_onInputEvent)
                m_onInputEvent(m_inputEvent);
            break;
        }
        case WM_MBUTTONUP: {
            SetCapture(NULL);
            m_inputEvent.reset(Fw::MouseReleaseInputEvent);
            m_inputEvent.mouseButton = Fw::MouseMidButton;
            m_mouseButtonStates[Fw::MouseMidButton] = false;
            if(m_onInputEvent)
                m_onInputEvent(m_inputEvent);
            break;
        }
        case WM_RBUTTONDOWN: {
            SetCapture(m_window);
            m_inputEvent.reset(Fw::MousePressInputEvent);
            m_inputEvent.mouseButton = Fw::MouseRightButton;
            m_mouseButtonStates[Fw::MouseRightButton] = true;
            if(m_onInputEvent)
                m_onInputEvent(m_inputEvent);
            break;
        }
        case WM_RBUTTONUP: {
            SetCapture(NULL);
            m_inputEvent.reset(Fw::MouseReleaseInputEvent);
            m_inputEvent.mouseButton = Fw::MouseRightButton;
            m_mouseButtonStates[Fw::MouseRightButton] = false;
            if(m_onInputEvent)
                m_onInputEvent(m_inputEvent);
            break;
        }
        case WM_MOUSEMOVE: {
            m_inputEvent.reset(Fw::MouseMoveInputEvent);

            Point newMousePos(LOWORD(lParam), HIWORD(lParam));
            if(newMousePos.x >= 32767)
                newMousePos.x = 0;
            else
                newMousePos.x = std::min<int32>(newMousePos.x, m_size.width());

            if(newMousePos.y >= 32767)
                newMousePos.y = 0;
            else
                newMousePos.y = std::min<int32>(newMousePos.y, m_size.height());

            m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos;
            m_inputEvent.mousePos = newMousePos;
            if(m_onInputEvent)
                m_onInputEvent(m_inputEvent);
            break;
        }
        case WM_MOUSEWHEEL: {
            m_inputEvent.reset(Fw::MouseWheelInputEvent);
            m_inputEvent.mouseButton = Fw::MouseMidButton;
            m_inputEvent.wheelDirection = ((short)HIWORD(wParam)) > 0 ? Fw::MouseWheelUp : Fw::MouseWheelDown;
            if(m_onInputEvent)
                m_onInputEvent(m_inputEvent);
            break;
        }
        case WM_MOVE: {
            m_position.x = (short)LOWORD(lParam);
            m_position.y = (short)HIWORD(lParam);
            break;
        }
        case WM_GETMINMAXINFO: {
            LPMINMAXINFO pMMI = (LPMINMAXINFO)lParam;
            Rect adjustedRect = adjustWindowRect(Rect(0, 0, m_minimumSize));
            pMMI->ptMinTrackSize.x = adjustedRect.width();
            pMMI->ptMinTrackSize.y = adjustedRect.height();
            break;
        }
        case WM_SIZE: {
            bool forceResize = false;
            switch(wParam) {
                case SIZE_MAXIMIZED:
                    m_maximized = true;
                    m_visible = true;
                    forceResize = true;
                    break;
                case SIZE_RESTORED:
                    m_maximized = false;
                    m_visible = true;
                    forceResize = true;
                    break;
                case SIZE_MINIMIZED:
                    m_visible = false;
                    break;
            }

            if(m_visible && m_deviceContext)
                internalRestoreGLContext();

            Size size = Size(LOWORD(lParam), HIWORD(lParam));
            size.setWidth(std::max<int32>(std::min<int32>(size.width(), 7680), 32));
            size.setHeight(std::max<int32>(std::min<int32>(size.height(), 4320), 32));

            if(m_visible && (forceResize || m_size != size)) {
                m_size = size;
                m_onResize(m_size);
            }

            break;
        }
        default:
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }

    return 0;
}
Пример #2
0
void X11Window::poll()
{
    bool needsResizeUpdate = false;

    XEvent event, peekEvent;
    while(XPending(m_display) > 0) {
        XNextEvent(m_display, &event);

        // check for repeated key releases
        bool repatedKeyRelease = false;
        if(event.type == KeyRelease && XPending(m_display)) {
            XPeekEvent(m_display, &peekEvent);
            if((peekEvent.type == KeyPress) && (peekEvent.xkey.keycode == event.xkey.keycode) && ((peekEvent.xkey.time-event.xkey.time) < 2))
                repatedKeyRelease = true;
        }

        // process keydown and keyrelease events first
        if(event.type == KeyPress || (event.type == KeyRelease && !repatedKeyRelease)) {
            // remove caps lock and shift maks
            XKeyEvent xkey = event.xkey;
            xkey.state &= ~(ShiftMask | LockMask);

            // lookup keysym and translate it
            KeySym keysym;
            char buf[32];
            XLookupString(&xkey, buf, sizeof(buf), &keysym, 0);
            Fw::Key keyCode = Fw::KeyUnknown;

            if(m_keyMap.find(keysym) != m_keyMap.end())
                keyCode = m_keyMap[keysym];

            if(event.type == KeyPress)
                processKeyDown(keyCode);
            else if(event.type == KeyRelease)
                processKeyUp(keyCode);
        }

        // call filter because xim will discard KeyPress events when keys still composing
        if(XFilterEvent(&event, m_window))
            continue;

        // discard repated key releases
        if(repatedKeyRelease)
            continue;

        switch(event.type) {
            case ClientMessage: {
                // close event
                if((Atom)event.xclient.data.l[0] == m_wmDelete && m_onClose)
                    m_onClose();
                break;
            }
            case ConfigureNotify: {
                Size newSize(event.xconfigure.width, event.xconfigure.height);
                Point newPos(event.xconfigure.x, event.xconfigure.y);

                // updates window size
                if(m_size != newSize) {
                    m_size = newSize;
                    needsResizeUpdate = true;
                }

                // checks if the window is maximized
                if(m_visible) {
                    m_maximized = false;
                    Atom wmState = XInternAtom(m_display, "_NET_WM_STATE", False);
                    Atom wmStateMaximizedVert = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
                    Atom wmStateMaximizedHorz = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
                    Atom actualType;
                    ulong i, numItems, bytesAfter;
                    uchar *propertyValue = NULL;
                    int actualFormat;

                    if(XGetWindowProperty(m_display, m_window, wmState,
                                        0, 1024, False, XA_ATOM, &actualType,
                                        &actualFormat, &numItems, &bytesAfter,
                                        &propertyValue) == Success) {
                        Atom *atoms = (Atom*)propertyValue;
                        int maximizedMask = 0;

                        for(i=0; i<numItems; ++i) {
                            if(atoms[i] == wmStateMaximizedVert)
                                maximizedMask |= 1;
                            else if(atoms[i] == wmStateMaximizedHorz)
                                maximizedMask |= 2;
                        }

                        if(maximizedMask == 3)
                            m_maximized = true;

                        XFree(propertyValue);
                    }
                }

                // updates window pos
                if(m_visible)
                    m_position = newPos;
                updateUnmaximizedCoords();
                break;
            }
            case SelectionRequest: {
                XEvent respond;
                XSelectionRequestEvent *req = &(event.xselectionrequest);

                Atom targets = XInternAtom(m_display, "TARGETS", False);
                if(req->target == targets) {
                    Atom typeList[] = { XInternAtom(m_display, "UTF8_STRING", False),
                                        XInternAtom(m_display, "TEXT", False),
                                        XInternAtom(m_display, "STRING", False),
                                        XInternAtom(m_display, "text/plain", False),
                                        XInternAtom(m_display, "COMPOUND_TEXT", False),
                                        XA_STRING };

                    XChangeProperty(m_display, req->requestor,
                                    req->property, req->target,
                                    8, PropModeReplace,
                                    (uchar *)&typeList,
                                    sizeof(typeList));
                    respond.xselection.property = req->property;
                } else {
                    XChangeProperty(m_display,
                                    req->requestor,
                                    req->property, req->target,
                                    8,
                                    PropModeReplace,
                                    (uchar *)m_clipboardText.c_str(),
                                    m_clipboardText.length());
                    respond.xselection.property = req->property;
                }

                respond.xselection.type = SelectionNotify;
                respond.xselection.display = req->display;
                respond.xselection.requestor = req->requestor;
                respond.xselection.selection = req->selection;
                respond.xselection.target = req->target;
                respond.xselection.time = req->time;
                XSendEvent(m_display, req->requestor, 0, 0, &respond);
                XFlush(m_display);
                break;
            }
            // process text events
            case KeyPress: {
                // text cant be insert while holding ctrl or alt
                if(event.xkey.state & ControlMask || event.xkey.state & Mod1Mask)
                    break;

                // process key text events
                KeySym keysym;
                char buf[32];
                memset(buf, 0, 32);
                int len;

                // lookup for keyText
                if(m_xic) { // with xim we can get latin1 input correctly
                    Status status;
                    len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status);
                } else { // otherwise use XLookupString, but often it doesn't work right with dead keys
                    static XComposeStatus compose = {NULL, 0};
                    len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose);
                }

                // filter unwanted characters
                if(len == 0 || (uchar)(buf[0]) < 32 || keysym == XK_BackSpace || keysym == XK_Return || keysym == XK_Delete || keysym == XK_Escape)
                    break;
                std::string text = buf;

                //g_logger.debug("char: ", buf[0], " code: ", (int)((uchar)buf[0]));

                if(m_onInputEvent && text.length() > 0) {
                    m_inputEvent.reset(Fw::KeyTextInputEvent);
                    m_inputEvent.keyText = text;
                    m_onInputEvent(m_inputEvent);
                }
                break;
            }
            case ButtonPress:
            case ButtonRelease: {
                m_inputEvent.reset();
                m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent;
                switch(event.xbutton.button) {
                    case Button1:
                        m_inputEvent.mouseButton = Fw::MouseLeftButton;
                        m_mouseButtonStates[Fw::MouseLeftButton] = (event.type == ButtonPress);
                        break;
                    case Button3:
                        m_inputEvent.mouseButton = Fw::MouseRightButton;
                        m_mouseButtonStates[Fw::MouseRightButton] = (event.type == ButtonPress);
                        break;
                    case Button2:
                        m_inputEvent.mouseButton = Fw::MouseMidButton;
                        m_mouseButtonStates[Fw::MouseMidButton] = (event.type == ButtonPress);
                        break;
                    case Button4:
                        if(event.type == ButtonPress) {
                            m_inputEvent.type = Fw::MouseWheelInputEvent;
                            m_inputEvent.mouseButton = Fw::MouseMidButton;
                            m_inputEvent.wheelDirection = Fw::MouseWheelUp;
                        }
                        break;
                    case Button5:
                        if(event.type == ButtonPress) {
                            m_inputEvent.type = Fw::MouseWheelInputEvent;
                            m_inputEvent.mouseButton = Fw::MouseMidButton;
                            m_inputEvent.wheelDirection = Fw::MouseWheelDown;
                        }
                        break;
                    default:
                        m_inputEvent.type = Fw::NoInputEvent;
                        break;
                }
                if(m_inputEvent.type != Fw::NoInputEvent && m_onInputEvent)
                    m_onInputEvent(m_inputEvent);
                break;
            }

            case MotionNotify: {
                m_inputEvent.reset();
                m_inputEvent.type = Fw::MouseMoveInputEvent;
                Point newMousePos(event.xbutton.x, event.xbutton.y);
                m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos;
                m_inputEvent.mousePos = newMousePos;
                if(m_onInputEvent)
                    m_onInputEvent(m_inputEvent);
                break;
            }
            case MapNotify:
                m_visible = true;
                needsResizeUpdate = true;
                break;
            case UnmapNotify:
                m_visible = false;
                releaseAllKeys();
                break;
            case FocusIn:
                m_focused = true;
                releaseAllKeys();
                break;
            case FocusOut:
                m_focused = false;
                releaseAllKeys();
                break;
            case Expose:
                // window needs redraw
                break;
        }
    }

    if(needsResizeUpdate && m_onResize)
        m_onResize(m_size);

    fireKeysPress();
}
Пример #3
0
	void Window::close()
	{
		if(m_onClose)
			m_onClose(*this);
		this->as<Widget>().remove();
	}