Esempio n. 1
0
void X11BufferSurface::apply(const BufferGuard&) noexcept
{
	if(!active_)
	{
		warning("ny::X11BufferSurface::apply: no currently active BufferGuard");
		return;
	}

	active_ = false;

	//we use the checked versions here since those function are very error prone due to
	//the rather complex depth/visual/bpp x system. We catch invalid x request here
	//directly.

	auto depth = windowContext().visualDepth();
	auto window = windowContext().xWindow();
	if(shm_)
	{
		auto cookie = xcb_shm_put_image_checked(&xConnection(), window, gc_, size_.x, size_.y,
			0, 0, size_.x, size_.y, 0, 0, depth, XCB_IMAGE_FORMAT_Z_PIXMAP, 0, shmseg_, 0);
		windowContext().errorCategory().checkWarn(cookie, "ny::X11BufferSurface: shm_put_image");
	}
	else
	{
		auto bpp = imageDataFormatSize(format_); //Bytes per pixel (XXX NOT bits!)
		auto length = size_.x * size_.y * bpp;

		auto cookie = xcb_put_image_checked(&xConnection(), XCB_IMAGE_FORMAT_Z_PIXMAP, window,
			gc_, size_.x, size_.y, 0, 0, 0, depth, length, data_);
		windowContext().errorCategory().checkWarn(cookie, "ny::X11BufferSurface: put_image");
	}
}
Esempio n. 2
0
BufferGuard WaylandBufferSurface::buffer()
{
	if(active_)
		throw std::logic_error("ny::WlBufferSurface: there is already an active BufferGuard");

	auto size = windowContext().size();
	for(auto& b : buffers_)
	{
		if(b.used()) continue;
		if(!nytl::allEqual(b.size(), size)) b.size(size);

		b.use();
		active_ = &b;
		auto format = waylandToImageFormat(b.format());
		return {*this, {&b.data(), size, format, b.stride()}};
	}

	//create new buffer if none is unused
	buffers_.emplace_back(windowContext().appContext(), size);
	buffers_.back().use();
	active_ = &buffers_.back();
	auto format = waylandToImageFormat(buffers_.back().format());
	if(format == ImageDataFormat::none)
		throw std::runtime_error("ny::WaylandBufferSurface: failed to parse shm buffer format");

	return {*this, {&buffers_.back().data(), size, format, buffers_.back().stride()}};
}
Esempio n. 3
0
void WaylandBufferSurface::apply(const BufferGuard& buffer) noexcept
{
	if(!active_ || buffer.get().data != &active_->data())
	{
		warning("ny::WaylandBufferSurface::apply: invalid BufferGuard given");
		return;
	}

	if(windowContext().shown()) windowContext().attachCommit(&active_->wlBuffer());
	active_ = nullptr;
}
Esempio n. 4
0
void Icon::paint(GraphicsContext* context, const IntRect& r)
{
    if (context->paintingDisabled())
        return;

#if OS(WINCE)
#if !USE(CAIRO)
    context->drawIcon(m_hIcon, r, DI_NORMAL);
#else
    IntRect translatedRect = context->getCTM().mapRect(r);
    LocalWindowsContext windowContext(context, translatedRect);
    DrawIconEx(windowContext.hdc(), translatedRect.x(), translatedRect.y(), m_hIcon, r.width(), r.height(), 0, 0, DI_NORMAL);
#endif
#else
    LocalWindowsContext windowContext(context, r);
    DrawIconEx(windowContext.hdc(), r.x(), r.y(), m_hIcon, r.width(), r.height(), 0, 0, DI_NORMAL);
#endif
}
Esempio n. 5
0
X11BufferSurface::X11BufferSurface(X11WindowContext& wc) : windowContext_(&wc)
{
	gc_ = xcb_generate_id(&xConnection());
	std::uint32_t value[] = {0, 0};
	auto c = xcb_create_gc_checked(&xConnection(), gc_, wc.xWindow(), XCB_GC_FOREGROUND, value);
	windowContext().errorCategory().checkThrow(c, "ny::X11BufferSurface: create_gc");

	//query the format
	//this is needed because the xserver may need a different bpp for an image
	//with the depth of the window.
	//For 24-bit depth images the xserver often required 32 bpp.
	auto setup = xcb_get_setup(&xConnection());
	auto fmtit = xcb_setup_pixmap_formats(setup);
	auto fmtend = fmtit + xcb_setup_pixmap_formats_length(setup);
	xcb_format_t* fmt {};

	while(fmtit != fmtend)
	{
		if(fmtit->depth == windowContext().visualDepth())
		{
			fmt = fmtit;
			break;
		}

		++fmtit;
	}

	if(!fmt)
		throw std::runtime_error("ny::X11BufferSurface: couldn't query depth format bpp");

	format_ = visualToFormat(*windowContext().xVisualType(), fmt->bits_per_pixel);
	if(format_ == ImageDataFormat::none)
		throw std::runtime_error("ny::X11BufferSurface: couldn't parse visual format");

	//check if the server has shm suport
	//it is also implemented without shm but the performance might be worse
    auto cookie = xcb_shm_query_version(&xConnection());
    auto reply = xcb_shm_query_version_reply(&xConnection(), cookie, nullptr);

	shm_ = reply;
	if(reply) free(reply);

	if(!shm_) warning("ny::X11BufferSurface: shm server does not support shm extension");
}
Esempio n. 6
0
void Icon::paint(GraphicsContext* context, const IntRect& r)
{
    if (context->paintingDisabled())
        return;

#if OS(WINCE)
    context->drawIcon(m_hIcon, r, DI_NORMAL);
#else
    LocalWindowsContext windowContext(context, r);
    DrawIconEx(windowContext.hdc(), r.x(), r.y(), m_hIcon, r.width(), r.height(), 0, 0, DI_NORMAL);
#endif
}
Esempio n. 7
0
void WinapiBufferSurface::apply(const BufferGuard& bufferGuard) noexcept
{
    if(!active_ || bufferGuard.get().data != data_.get())
    {
        warning("ny::WinapiBufferSurface::apply: invalid bufferGuard");
        return;
    }

    active_ = false;
    auto bitmap = ::CreateBitmap(size_.x, size_.y, 1, 32, data_.get());
    auto whdc = ::GetDC(windowContext().handle());
    auto bhdc = ::CreateCompatibleDC(whdc);

    auto prev = ::SelectObject(bhdc, bitmap);
    ::BitBlt(whdc, 0, 0, size_.x, size_.y, bhdc, 0, 0, SRCCOPY);
    ::SelectObject(bhdc, prev);

    ::DeleteDC(bhdc);
    ::ReleaseDC(windowContext().handle(), whdc);
    ::DeleteObject(bitmap);
}
Esempio n. 8
0
BufferGuard X11BufferSurface::buffer()
{
	if(active_)
		throw std::logic_error("ny::X11BufferSurface::buffer: there is already a BufferGuard");

	//check if resize is needed
	auto size = windowContext().size();
	auto bpp = imageDataFormatSize(format_); //bytes per pixel (XXX NOT bits!)
	auto newBytes = size.x * size.y * bpp; //the needed size
	if(newBytes > byteSize_)
	{
		//we alloc more than is really needed because this will
		//speed up (especially the shm version) resizes. We don't have to reallocated
		//every time the window is resized and redrawn for the cost of higher memory
		//consumption
		byteSize_ = newBytes * 4;

		if(shm_)
		{
			if(shmseg_)
			{
				xcb_shm_detach(&xConnection(), shmseg_);
				shmdt(data_);
				shmctl(shmid_, IPC_RMID, 0);
			}
			else
			{
				shmseg_ = xcb_generate_id(&xConnection());
			}


			shmid_ = shmget(IPC_PRIVATE, byteSize_, IPC_CREAT | 0777);
			data_ = static_cast<uint8_t*>(shmat(shmid_, 0, 0));
			shmseg_ = xcb_generate_id(&xConnection());
			xcb_shm_attach(&xConnection(), shmseg_, shmid_, 0);
		}
		else
		{
			ownedBuffer_ = std::make_unique<uint8_t[]>(byteSize_);
			data_ = ownedBuffer_.get();
		}
	}

	size_ = size;
	active_ = true;

	return {*this, {data_, {size_.x, size_.y}, format_, size_.x * bpp}};
}
Esempio n. 9
0
BufferGuard WinapiBufferSurface::buffer()
{
    if(active_)
        throw std::logic_error("ny::WinapiBufferSurface::get: has already an active BufferGuard");

    auto currSize = windowContext().clientExtents().size;
    auto currTotal = nytl::multiply(currSize);

    //TODO: allocate more than needed? store really allocated size
    if(currTotal > nytl::multiply(size_))
        data_ = std::make_unique<std::uint8_t[]>(currTotal * 4);

    size_ = currSize;
    active_ = true;
    return {*this, {data_.get(), size_, ImageDataFormat::bgra8888, size_.x * 4}};
}
Esempio n. 10
0
bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
{
    event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));

    ASSERT(!eventDispatchForbidden());
    ASSERT(event->target());
    ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.

    RefPtr<EventTarget> originalTarget = event->target();
    ensureEventAncestors(event.get());

    WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());

    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowContext.window(), m_node.get(), m_ancestors);

    // Give the target node a chance to do some work before DOM event handlers get a crack.
    void* data = m_node->preDispatchEventHandler(event.get());
    if (m_ancestors.isEmpty() || m_shouldPreventDispatch || event->propagationStopped())
        goto doneDispatching;

    // Trigger capturing event handlers, starting at the top and working our way down.
    event->setEventPhase(Event::CAPTURING_PHASE);

    if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
        goto doneDispatching;

    for (size_t i = m_ancestors.size() - 1; i > 0; --i) {
        const EventContext& eventContext = m_ancestors[i];
        if (eventContext.currentTargetSameAsTarget()) {
            if (event->bubbles())
                continue;
            event->setEventPhase(Event::AT_TARGET);
        } else
            event->setEventPhase(Event::CAPTURING_PHASE);
        eventContext.handleLocalEvents(event.get());
        if (event->propagationStopped())
            goto doneDispatching;
    }

    event->setEventPhase(Event::AT_TARGET);
    event->setTarget(originalTarget.get());
    event->setCurrentTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
    m_ancestors[0].handleLocalEvents(event.get());
    if (event->propagationStopped())
        goto doneDispatching;

    if (event->bubbles() && !event->cancelBubble()) {
        // Trigger bubbling event handlers, starting at the bottom and working our way up.
        event->setEventPhase(Event::BUBBLING_PHASE);

        size_t size = m_ancestors.size();
        for (size_t i = 1; i < size; ++i) {
            const EventContext& eventContext = m_ancestors[i];
            if (eventContext.currentTargetSameAsTarget())
                event->setEventPhase(Event::AT_TARGET);
            else
                event->setEventPhase(Event::BUBBLING_PHASE);
            eventContext.handleLocalEvents(event.get());
            if (event->propagationStopped() || event->cancelBubble())
                goto doneDispatching;
        }
        windowContext.handleLocalEvents(event.get());
    }

doneDispatching:
    event->setTarget(originalTarget.get());
    event->setCurrentTarget(0);
    event->setEventPhase(0);

    // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
    m_node->postDispatchEventHandler(event.get(), data);

    // Call default event handlers. While the DOM does have a concept of preventing
    // default handling, the detail of which handlers are called is an internal
    // implementation detail and not part of the DOM.
    if (!event->defaultPrevented() && !event->defaultHandled()) {
        // Non-bubbling events call only one default event handler, the one for the target.
        m_node->defaultEventHandler(event.get());
        ASSERT(!event->defaultPrevented());
        if (event->defaultHandled())
            goto doneWithDefault;
        // For bubbling events, call default event handlers on the same targets in the
        // same order as the bubbling phase.
        if (event->bubbles()) {
            size_t size = m_ancestors.size();
            for (size_t i = 1; i < size; ++i) {
                m_ancestors[i].node()->defaultEventHandler(event.get());
                ASSERT(!event->defaultPrevented());
                if (event->defaultHandled())
                    goto doneWithDefault;
            }
        }
    }

doneWithDefault:

    // Ensure that after event dispatch, the event's target object is the
    // outermost shadow DOM boundary.
    event->setTarget(windowContext.target());
    event->setCurrentTarget(0);
    InspectorInstrumentation::didDispatchEvent(cookie);

    return !event->defaultPrevented();
}
Esempio n. 11
0
void X11AppContext::processEvent(const x11::GenericEvent& ev)
{
	//macro for easier event creation for registered EventHandler
	#define EventHandlerEvent(T, W) \
		auto handler = eventHandler(W); \
		if(!handler) return; \
		auto event = T(handler);

	auto dispatch = [&](Event& event){
		if(event.handler) event.handler->handleEvent(event);
	};

	auto responseType = ev.response_type & ~0x80;
    switch(responseType)
    {

    case XCB_MOTION_NOTIFY:
    {
		auto& motion = reinterpret_cast<const xcb_motion_notify_event_t&>(ev);
		auto pos = nytl::Vec2i(motion.event_x, motion.event_y);
		mouseContext_->move(pos);

		EventHandlerEvent(MouseMoveEvent, motion.event);
        event.position = pos;
        event.screenPosition = nytl::Vec2i(motion.root_x, motion.root_y);

		dispatch(event);
		break;
    }

    case XCB_EXPOSE:
    {
		auto& expose = reinterpret_cast<const xcb_expose_event_t&>(ev);
        if(expose.count == 0)
		{
			EventHandlerEvent(DrawEvent, expose.window);
			dispatch(event);
		}

		break;
    }

    case XCB_MAP_NOTIFY:
    {
		auto& map = reinterpret_cast<const xcb_map_notify_event_t&>(ev);
		EventHandlerEvent(DrawEvent, map.window);
		dispatch(event);
		break;
    }

    case XCB_BUTTON_PRESS:
    {
		auto& button = reinterpret_cast<const xcb_button_press_event_t&>(ev);

		int scroll = 0;
		if(button.detail == 4) scroll = 1;
		else if(button.detail == 5) scroll = -1;

		if(scroll)
		{
			EventHandlerEvent(MouseWheelEvent, button.event);
			event.data = std::make_unique<X11EventData>(ev);
			event.value = scroll;

			mouseContext_->onWheel(*mouseContext_, scroll);
			dispatch(event);

			break;
		}

		auto b = x11ToButton(button.detail);
		mouseContext_->mouseButton(b, true);

		EventHandlerEvent(MouseButtonEvent, button.event);
		event.data = std::make_unique<X11EventData>(ev);
        event.button = b;
        event.position = nytl::Vec2i(button.event_x, button.event_y);
		event.pressed = true;

		dispatch(event);
		break;
    }

    case XCB_BUTTON_RELEASE:
    {
		auto& button = reinterpret_cast<const xcb_button_release_event_t&>(ev);
		if(button.detail == 4 || button.detail == 5) break;

		auto b = x11ToButton(button.detail);
		mouseContext_->mouseButton(b, false);

		EventHandlerEvent(MouseButtonEvent, button.event);
		event.data = std::make_unique<X11EventData>(ev);
        event.button = b;
        event.position = nytl::Vec2i(button.event_x, button.event_y);
		event.pressed = false;

		dispatch(event);
		break;
    }

    case XCB_ENTER_NOTIFY:
    {
		auto& enter = reinterpret_cast<const xcb_enter_notify_event_t&>(ev);
		auto wc = windowContext(enter.event);
		mouseContext_->over(wc);

		EventHandlerEvent(MouseCrossEvent, enter.event);
        event.position = nytl::Vec2i(enter.event_x, enter.event_y);
		event.entered = true;
		dispatch(event);

		break;
    }

    case XCB_LEAVE_NOTIFY:
    {
		auto& leave = reinterpret_cast<const xcb_enter_notify_event_t&>(ev);
		auto wc = windowContext(leave.event);
		if(mouseContext_->over() == wc) mouseContext_->over(nullptr);

		EventHandlerEvent(MouseCrossEvent, leave.event);
        event.position = nytl::Vec2i(leave.event_x, leave.event_y);
		event.entered = false;
		dispatch(event);

		break;
    }

    case XCB_FOCUS_IN:
    {
		auto& focus = reinterpret_cast<const xcb_focus_in_event_t&>(ev);
		auto wc = windowContext(focus.event);
		keyboardContext_->focus(wc);

		EventHandlerEvent(FocusEvent, focus.event);
		event.focus = true;
		dispatch(event);

		break;
    }

    case XCB_FOCUS_OUT:
    {
		auto& focus = reinterpret_cast<const xcb_focus_in_event_t&>(ev);
		auto wc = windowContext(focus.event);
		if(keyboardContext_->focus() == wc)keyboardContext_->focus(nullptr);

		EventHandlerEvent(FocusEvent, focus.event);
		event.focus = false;
		dispatch(event);

		break;
    }

    case XCB_KEY_PRESS:
    {
		auto& key = reinterpret_cast<const xcb_key_press_event_t&>(ev);

		EventHandlerEvent(KeyEvent, key.event);
		event.pressed = true;
		if(!keyboardContext_->keyEvent(key.detail, event)) bell();
		dispatch(event);

		break;
    }

    case XCB_KEY_RELEASE:
    {
		auto& key = reinterpret_cast<const xcb_key_press_event_t&>(ev);

		EventHandlerEvent(KeyEvent, key.event);
		event.pressed = false;
		if(!keyboardContext_->keyEvent(key.detail, event)) bell();
		dispatch(event);

		break;
    }

	case XCB_REPARENT_NOTIFY:
	{
		auto& reparent = reinterpret_cast<const xcb_reparent_notify_event_t&>(ev);
		auto wc = windowContext(reparent.window);
		if(wc) wc->reparentEvent();

		break;
	}

    case XCB_CONFIGURE_NOTIFY:
	{
		auto& configure = reinterpret_cast<const xcb_configure_notify_event_t&>(ev);

        //todo: something about window state
        auto nsize = nytl::Vec2ui(configure.width, configure.height);
        // auto npos = nytl::Vec2i(configure.x, configure.y); //positionEvent

		auto wc = windowContext(configure.window);
		if(wc) wc->sizeEvent(nsize);

        if(!eventHandler(configure.window)) break;

		/* TODO XXX !important
        if(any(windowContext(configure.window)->window().size() != nsize)) //sizeEvent
		{
			EventHandlerEvent(SizeEvent, configure.window);
			event->size = nsize;
			event->change = 0;
			dispatcher.dispatch(std::move(event));

			auto wc = windowContext(configure.window);
			if(!wc) return true;
			auto wevent = std::make_unique<SizeEvent>(wc);
			wevent->size = nsize;
			wevent->change = 0;
			dispatcher.dispatch(std::move(wevent));
		}

        if(any(windowContext(configure.window)->window().position() != npos))
		{
			EventHandlerEvent(PositionEvent, configure.window);
			event->position = npos;
			event->change = 0;
			dispatcher.dispatch(std::move(event));
		}
		*/

		break;
    }

    case XCB_CLIENT_MESSAGE:
    {
		auto& client = reinterpret_cast<const xcb_client_message_event_t&>(ev);
		auto protocol = static_cast<unsigned int>(client.data.data32[0]);
        if(protocol == atoms().wmDeleteWindow)
        {
			EventHandlerEvent(CloseEvent, client.window);
			dispatch(event);
        }

		break;
	}

	case 0u:
	{
		//an error occurred!
		int code = reinterpret_cast<const xcb_generic_error_t&>(ev).error_code;
		auto errorMsg = x11::errorMessage(xDisplay(), code);
		warning("ny::X11AppContext::processEvent: retrieved error code ", code, ", ", errorMsg);

		break;
	}

	default:
	{
		//check for xkb event
		if(ev.response_type == keyboardContext_->xkbEventType())
			keyboardContext_->processXkbEvent(ev);

		// May be needed for gl to work correctly... (TODO: test)
		// XLockDisplay(xDisplay_);
	    // auto proc = XESetWireToEvent(xDisplay_, ev.response_type & ~0x80, nullptr);
	    // if(proc)
		// {
	    //     XESetWireToEvent(xDisplay_, ev.response_type & ~0x80, proc);
	    //     XEvent dummy;
	    //     ev.sequence = LastKnownRequestProcessed(xDisplay_);
	    //     if(proc(xDisplay_, &dummy, (xEvent*) &ev)) //not handled
		// 	{
		// 		//TODO
		// 	}
	    // }
		//
		// XUnlockDisplay(xDisplay_);
	}

	}

	#undef EventHandlerEvent
}
Esempio n. 12
0
EventHandler* X11AppContext::eventHandler(xcb_window_t w)
{
    auto* wc = windowContext(w);
    return wc ? wc->eventHandler() : nullptr;
}
Esempio n. 13
0
//wndProc
LRESULT WinapiAppContext::eventProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
	auto wc = windowContext(window);

	WinapiEventData eventData;
	eventData.windowContext = wc;
	eventData.window = window;
	eventData.message = message;
	eventData.wparam = wparam;
	eventData.lparam = lparam;

	LRESULT result = 0;

	switch(message)
	{
		case WM_PAINT:
		{
			if(wc) wc->listener().draw(&eventData);
			result = ::DefWindowProc(window, message, wparam, lparam); //to validate the window
			break;
		}

		case WM_DESTROY:
		{
			if(wc) wc->listener().close(&eventData);
			break;
		}

		case WM_SIZE:
		{
			nytl::Vec2ui size(LOWORD(lparam), HIWORD(lparam));
			if(wc) wc->listener().resize(size, &eventData);
			break;
		}

		case WM_MOVE:
		{
			nytl::Vec2i position(LOWORD(lparam), HIWORD(lparam));
			if(wc) wc->listener().position(position, &eventData);
			break;
		}

		case WM_SYSCOMMAND:
		{
			if(wc)
			{
	            constexpr auto SC_DRAGMOVE = 0xf012;
				ToplevelState state;

				if(wparam == SC_MAXIMIZE) state = ToplevelState::maximized;
				else if(wparam == SC_MINIMIZE) state = ToplevelState::minimized;
				else if(wparam == SC_RESTORE) state = ToplevelState::normal;
                else if(wparam >= SC_SIZE && wparam <= SC_SIZE + 8)
                {
                    auto currentCursor = ::GetClassLongPtr(wc->handle(), -12);

                    auto edge = winapiToEdges(wparam - SC_SIZE);
                    auto cursor = sizeCursorFromEdge(edge);
                    wc->cursor(cursor);

			        result = ::DefWindowProc(window, message, wparam, lparam);
	                ::SetClassLongPtr(wc->handle(), -12, currentCursor);

                    break;
                }

				//TODO: shown parameter? check WS_VISIBLE?
				wc->listener().state(true, state, &eventData);
			}

			result = ::DefWindowProc(window, message, wparam, lparam);
			break;
		}

		case WM_GETMINMAXINFO:
		{
			if(wc)
			{
				::MINMAXINFO* mmi = reinterpret_cast<MINMAXINFO*>(lparam);
				mmi->ptMaxTrackSize.x = wc->maxSize().x;
				mmi->ptMaxTrackSize.y = wc->maxSize().y;
				mmi->ptMinTrackSize.x = wc->minSize().x;
				mmi->ptMinTrackSize.y = wc->minSize().y;
			}

			break;
		}

		case WM_ERASEBKGND:
		{
			//prevent the background erase
			result = 1;
			break;
		}

		//XXX: needed?
		case WM_CLIPBOARDUPDATE:
		{
			clipboardSequenceNumber_ = ::GetClipboardSequenceNumber();
			clipboardOffer_.reset();

			IDataObject* obj;
			::OleGetClipboard(&obj);
			if(obj) clipboardOffer_ = std::make_unique<winapi::DataOfferImpl>(*obj);
			break;
		}

		case WM_QUIT:
		{
			receivedQuit_ = 1;
			break;
		}

		default:
		{
			//process mouse/keyboard events
			if(keyboardContext_.processEvent(eventData, result)) break;
			if(mouseContext_.processEvent(eventData, result)) break;

			result = ::DefWindowProc(window, message, wparam, lparam);
			break;
		}
	}

	return result;
}