Summary: | Add user data field in X Window structure in Xlib | ||
---|---|---|---|
Product: | xorg | Reporter: | Christian Casteyde <casteyde.christian> |
Component: | Lib/Xlib | Assignee: | Xorg Project Team <xorg-team> |
Status: | CLOSED INVALID | QA Contact: | Xorg Project Team <xorg-team> |
Severity: | enhancement | ||
Priority: | medium | ||
Version: | unspecified | ||
Hardware: | All | ||
OS: | All | ||
Whiteboard: | |||
i915 platform: | i915 features: |
Description
Christian Casteyde
2007-10-20 10:54:00 UTC
Unfortunately, it'd be pretty much useless, since either the toolkit controlling the window used it, or nothing at all. Otherwise, you could have fun collisions ... Could you elaborate the "or nothing at all" part of your last comment (I didn't understand it)? Same for 'collisions' (with what, where?)? OK, the toolkit knows the language object when it does a call to X to do something, but my proposal is for the main loop. For instance: int CWindow::Map() { return XMapWindow(m_display, m_winID); // OK, we have m_winID and this pointer } but: int CWindowedApp::RunMainLoop() { // main event loop: ... XEvent evt; XNextEvent(m_display, &evt); // Now, we need to find the CWindow object to pass it the message: CWindow *pWindow = NULL; // First solution (cumbersome): WINDOW_MAP::iterator itWindow = m_mapKnownWindows.find(evt.window); pWindow = itWindow->second; // Second solution (more elegant and performant if this call remains // inside XLib and does not get to the server: CWindow *pWindow = NULL; XGetWindowData(evt.window, &pWindow); // pWindow simply stored in XLib // structure for the Window ID // Now, pass the message: pWindow->OnMessage(&evt); // loop to the next message. } In the second example, the toolkit either has to maintain a window to language object map, for **all** known window, or it could use the proposed function to directly get the "user data object associated with the system object". Generally speeking, many APIs enable passing "user data object pointer" to an operation or a system object in order to ease integration with object oriented language. I didn't found the equivalent in Xlib, it's sad and I don't think this would garbage the Xlib internals if it already maintains a data structure for each window ID (ie: if it is not a proxy to the server that simply encodes the calls to X protocol). I admit not having looked in the Xlib source code (however I would directly have proposed a patch :-). Note that this could have other usage than the main loop, because it is a common design pattern in APIs as mentionned above. Yes, I'm aware of the void *data pattern, but usually they have a very well-defined user. What I'm saying is that if two things use it: library A: XSetWindowData(window, some_pointer); library B: XSetWindowData(window, other_pointer); library A now does XGetWindowData, and it all goes horribly wrong. So you have to add a pretty strict definition of what uses it, but it's pretty hard to sort it out: thanks to the magic of plugins, multiple toolkits and multiple languages in a single process, with a single window, is entirely possible (and does actually happen). So it would seem that just keeping a list of windows and IDs is the safest for now. Well, if multiple toolkits can handle the same window, it's quite a mess effectively. But this is only a problem because I made the assumption there was a n-1 relationship between windows and toolkits (ie: each window is handled through a single toolkit). That could be circumvented with something like that: //Toolkit key: XSetWindowData(DataKey, void *data); XGetWindowData(DataKey, void **data); and each toolkit can sets its own data pointer, provided they use unique DataKey (for instance an ATOM, or a const string specific to the toolkit, etc. I'm not going into details there). So, given a toolkit, it could do: XGetWindowData(m_MyToolkitKey, window, &pMyWindowObject); with m_MyToolkitKey the key specific to the toolkit. Thus, Xlib would only maintain "a few" user data fields, instead of all toolkits maintaining "a big" association between X windows and its objects (given that in a software, there are generally far more windows than toolkits used :-). Note I do not adress which toolkit dispatches the message to the right object. Each toolkit can dispatch the messages for its window objects, but not for the other toolkits. However this is already a problem, and mixing different toolkits indeed requires toolkit cooperation and knowledge of each others in current applications, in order to expose hooks for other toolkits integration. This leads me to another idea: X Window does not propose (same as first post, I didn't find a way to do that) a generic callback mechanism. To go further, something like that could be used: int XSetWindowCallback(Window, here maybe event mask, int (*ToolkitCallback)(XEvent *, void *), void *user_data); and ToolkitCallback would be called for each XEvent with user_data directly, and returns 0 if the event is not consumed (to call the ToolkitCallback for the next Toolkit). Please note that there is no more need of a specific toolkit key. So, the creating toolkit registers its window event callback, with its user data object. If any other toolkit wants to get events, it could registers its own callback, and so on. When the event is dispatched, each toolkit could have a chance to get the event, with its objects directly available, until a toolkit "eats" the message completly. Heh, we're going down the road to reworking Xlib, where it's better off just left for dead, as it's deprecated by XCB. OK, I'll look at XCB (in fact, I thought it was just internal changes but still with Xlib API). > I don't think this would garbage the Xlib internals if it already
> maintains a data structure for each window ID (ie: if it is not a
> proxy to the server that simply encodes the calls to X protocol).
Xlib is exactly "a proxy to the server that simply encodes the calls to
X protocol", and so is XCB. (Xlib has a lot of other stuff too, but no
list of windows anywhere.) There's no place to put the hook you want in
either library, quite aside from the nightmare Daniel mentions of
designing an API for it.
OK, I've just looked at xcb_generate_id, where my hooks would have take place. It's quite obvious that these IDs are generated from the server and retreived by clients with prefetch for performance reasons. So doing what I suggested would imply: - either modify X protocol to transfert at least one user data field in each event (of course unacceptable); - either make X lib/Xcb returns locally generated IDs referring to a table where the server IDs and user data could be found, and having the reverse association giving the local IDs from the server IDs on events. But this would place the job of finding local ID from server ID in Xlib instead of toolkits, and this association would have to be done for each event, whereas sometimes toolkit could ignore the event (for instance if they cache the object for the window that has the focus, they could pass kbd events directly). So this solution would be worse than the problem I'm trying to address; - either doing both, with XLib/Xcb the only owner of an extra field of each events to find its local IDs, and maintaining the local IDs with user data and other goodies (certainly the best solution, but not feasible). However I didn't considered designing an API an horrible task, this is simply not feasible technically in X to keep protocol compatibility, so I'm closing this bug. Thanks for giving me clues about all this. This was a long standing idea that bothered me since quite a long... |
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.