Dev:Source/Architecture/Ghost Refactoring

提供: wiki
移動先: 案内検索

GhostRefactoring

What?

This project intends to modify some aspects of the underlying window system of blender, GHOST which is a replacement for GLUT. For the moment, we will focus solely on the version of GHOST embeded in blender, but we will of course port back the changes in the standalone project if they are checked to fit.

Why?

There are some problems and shortcomings in the current implementation which need attention. As the OS X maintainer, I have been aware of OS X specific problems, but most apply on other platforms too. As it's planned that the blender event system will be worked on, prior solving of GHOST pending issues would be good.

Mainly :

  • international keyboard support,
  • multiple levels of key mapping, from system, GHOST, then blender,
  • some of the redraw problems on OS X can be traced to bad OpenGL context change handling,
  • multiscreen support,
  • modifiers keys methods are not used in the smartest way, IMHO,
  • mouse tracking,
  • smarter fullscreen support,
  • user prefs for window creation and placement,
  • other means of input than mouse & keyboard (tablet, configurable keypad, space ball...).
  • people with deep understanding of X11 programming are also needed to review the existing code.
this could also permit to allow user key bindings customization.

At least the first 3 items on this list are targeted for blender 2.35 release.

Analysis

Note: this document does not take into account Game Engine needs for the moment.

International keyboard support

Blender needs to read the keyboard in 2 ways, ascii code, and rawcode for it's internal event system

rawcode value is mapped on 3 levels :

  • system provides the code of the typed key without any modifiers
  • the key's value is mapped against a GHOST MAP
  • the GHOST MAP is mapped against BlenderMap

The BlenderMap is strongly based on the values commonly accessible without any modifers on an US keyboard.

ascii code is provided by the system, taking in account modifiers keys. ISO8859-1 map is used which may cause problem to some langages but seems safe enough. We want to support more, it would need to be moved to unicode (providing the 2 are possible).

We have 2 distinct problems here :

  • different physical layouts exits (even if an ISO standard exist) where some keys may not exist
  • depending of the langage used, layout will be different and on some keys may need eg a shift to be typed. In this case the raw values won't be recognized correctly. This happens on the French layout where numerals are accessed only as shifted, or for layouts where the numpad separator key is ',' and not '.'

That means :

  • some keys won't be usable for commands as their unmodified value is not present on the US-keyboard without a modifier key
  • some keys dont return the code you would expect.
  • we use 3 levels where 2 would suffice.

However we can take advantage of the current design by simply allowing customizing of the intermediate GHOST MAP instead of the current hardcoded one. This way we can configure the keyboard so that all important codes are available, and detect conflicts due to international layout. This also provides basic user global configuration of the keyboard, but it may not desirable for all keys.

There are many ways of doing this customization from the true Unix way of a config file, to an interactive view (Mac Os X can even retrieve the physical layout of the keyboard). In a first step, a small config file and a python parser seems to me to be the easiest.

If you look closely at BlenderMap, not many keys cause problems, the 0-9 can be automaticaly relinked to their correct value (simply by looking for their rawcode in an US keyboard) as their location does not change on any latin keyboard I know, only the unmodified value they return.

So we are left only with other signs.

The config file would also a nice way to handle other means of input. At least for USB devices, the rawcodes available and their range can be always found by system APIs.

IMHO we should use this opportunity to pack all events the modifierskeys state. This is more reliable as we get the true value when the event occured and we can also check the state when tracking. We had some bug reports (on OS X) where modifier key changes were not handled correctly (may be interaction with dock).

Successive mouse displaced events should be packed in one, this would reduce lag and risks of overflow of the system queue (some systems can provide this automatically). Problems that may be related to that were reported on X11.

Also we could think about filtering key-up events most of the time, as they are only needed when tracking in a mode.

multiscreen support / Redraw problem

GHOST does not explicitly support multiple screens (this works on OS X if the same video card handles different screens) and this may the cause of redraw problems. OS X has also problems when interacting with dock or X11 windows (does not detect correctly the context change).

others leads : more full screen choice / user prefs

to be done when the rest is ok.

Planned work

The first thing to do is to define how we allow configuration of GHOST MAP

--JeanLucPeuriere - 21 Aug 2004

Platform Specific Issues

Just a note on solaris the F# keys are not in numerical order so F11 and F12 currently do not work. Might be nice to look at how SDL does stuff as well.

Shift+Numpad0 is the same as shift+insert on windows. This combo is a system combo for inserting clipboard content. Instead of VK_NUMPAD0 the virtual key VK_INSERT is fired when shift is pressed.

specs for this refactor

multi screen explicit support 2005/11

Important note: the ideas here are reflect of what we can do within the OS X API, and as such it must be checked what changes are needed for Windows or X11. I won't be able to rework all of this without the help of a coder for each of those APIs.

Currently dual screen support is only implicit when the physical screens share the same video card.

First let do some definitions :

- desktop is a rectangle that covers all pixels adressable for output
- the desktop is divided in smaller rectangles, one per physical screen
- blender window is where we draw each of the blender spaces.

the main constraint we have here is that to get full accelerated drawing by the graphics card, we must take into account that each card has its own area (GL graphic context) that covers only part of the desktop. One card can cover more than one physical screen, so an OpenGL area rendered across 2 physical screens but driven by same card will still be accelerated, while the same area across 2 cards areas will fall back on the software renderer. Each card is linked to a specific renderer.

On OS X, this concept is handled nicely by the concept of virtual screens that cover area given by one card. Situations like overlaps of screen and/or mirroring can defeat that, but there is no real solution in such case.

Allowing more than renderer per window is tricky and bound to cause problems in higher level blender code. So my idea is to allow splitting windows in such way that each window (and the blender spaces inside) are drawn in one and only one virtual screen. Each space is drawn in one and only one window.

So we have this hierarchy :

- desktop
- virtual screen <---linked to ---> card renderer
- windows
- blender spaces

Note that the physical screens have been eliminated, we dont care for them, except in one situation, where 2 physical screens are not contiguous in desktop spaces. in that case, we will have to have to cut the virtual screen in 2.

For windows in same context we want to insure the non-overlapping concept. Windows in different contexts are non overlapping by default.

All windows share the same umbrella so that for the blender spaces nothing changes. Which window is actually used is of no interest for them. Than means that all windows are active or inactive at the same time. The easiest way to handle that is to consider a main window with satellite palettes, that concept works on all systems

Each space can be so teared off from main window in a satelite and each satelite can be closed or rattached to main window

The render window (and possibly others) is managed independently.

GHOST manages all window related stuff but nothing from the space which is done at blender level. Communication between spaces is done at the umbrella level which is the only part communicating with GHOST.

events handling

GHOST is responsible for receiving all system events and sending them to the proper consumer.

System events fall into the following categories :

- main level events as a request to close app or file opening
- window level events
- input devices (keyboard & mouse +...) driven by the system

We want to be able to add the following to this list:

- generic USB input peripheral (eg knob or joystick)
- eventually signal from another process (eg external renderer or verse)

For USB we may or may not need to have our own app level driver, depending on if the system can report it or not. USB peripherals describe themselves, those are the only ones that we can safely be confident to be able to handle ourselves without a specific driver (HID or equivalent interface).

Some peripherals can hide themselves via the generic mouse or keyboard but we may then loose input data (eg tablet). Some configuration method is needed, at least a registration step so that spaces interested in such events get them but only them.

The raw events must be then decoded (taken in account international keyboards unlike current solution) and either handled directly (windows related one) or passed to the upper levels

GHOST can also receive back events from upper level and manage timers, set cursors.

Events are sent to a stack composed of :

- the space in focus (the one under the mouse). with the non overlapping rule, there is at most one
- the umbrella for all windows
- the app itself.

The event is passed down until handled.

If a space needs to go into a modal state, it can add a private handler on top of that

IMHO we should use this opportunity to pack with all events the modifierskeys state. This is more reliable as we get the true value when the event occured and we can also check the state when tracking. We had some bug reports (on OS X) where modifier key changes were not handled correctly (may be interaction with dock). Successive mouse displaced events should be packed in one, this would reduce lag and risks of overflow of the system queue (some systems can provide this automatically). Problems that may be related to that were reported on X11. Also we could think about filtering key-up events most of the time, as they are only needed when tracking in a mode.


kaito: what GHOST actually needs (for speed in all OSs) is a 'swap sub-rect from back to front'