void X11Window::internalCreateWindow() { Visual *vis; int depth; unsigned int attrsMask; XSetWindowAttributes attrs; memset(&attrs, 0, sizeof(attrs)); attrs.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask | FocusChangeMask; m_colormap = XCreateColormap(m_display, m_rootWindow, m_visual->visual, AllocNone); attrs.colormap = m_colormap; attrs.border_pixel = 0; attrs.override_redirect = False; vis = m_visual->visual; depth = m_visual->depth; attrsMask = CWEventMask | CWBorderPixel | CWColormap; #ifdef OPENGL_ES attrs.override_redirect = False; attrsMask |= CWOverrideRedirect; #endif updateUnmaximizedCoords(); m_window = XCreateWindow(m_display, m_rootWindow, m_position.x, m_position.y, m_size.width(), m_size.height(), 0, depth, InputOutput, vis, attrsMask, &attrs); m_visible = true; if(!m_window) g_logger.fatal("Unable to create X11 window!"); // ensure window input focus XWMHints hints; hints.input = True; hints.flags = InputHint; XSetWMHints(m_display, m_window, &hints); // ensure window position XMoveWindow(m_display, m_window, m_position.x, m_position.y); // handle wm_delete events m_wmDelete = XInternAtom(m_display, "WM_DELETE_WINDOW", True); XSetWMProtocols(m_display, m_window, &m_wmDelete , 1); if(!internalSetupWindowInput()) g_logger.warning("Input of special keys may be messed up, because window input initialization failed"); internalConnectGLContext(); }
void WIN32Window::poll() { fireKeysPress(); MSG msg; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } updateUnmaximizedCoords(); }
void WIN32Window::internalCreateWindow() { m_defaultCursor = LoadCursor(NULL, IDC_ARROW); WNDCLASSA wc; wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC)WindowProcProxy::call; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = m_instance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = m_defaultCursor; wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = g_app.getCompactName().c_str(); if(!RegisterClassA(&wc)) g_logger.fatal("Failed to register the window class."); DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; DWORD dwStyle = WS_OVERLAPPEDWINDOW; // initialize in the center of the screen m_position = ((getDisplaySize() - m_size) / 2).toPoint(); Rect screenRect = adjustWindowRect(Rect(m_position, m_size)); updateUnmaximizedCoords(); m_window = CreateWindowExA(dwExStyle, g_app.getCompactName().c_str(), NULL, dwStyle, screenRect.left(), screenRect.top(), screenRect.width(), screenRect.height(), NULL, NULL, m_instance, NULL); if(!m_window) g_logger.fatal("Unable to create window"); ShowWindow(m_window, SW_HIDE); m_deviceContext = GetDC(m_window); if(!m_deviceContext) g_logger.fatal("GetDC failed"); }
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(); }