wine's fullscreen code has no effect on metacity

Havoc Pennington hp at redhat.com
Thu Jul 13 09:28:13 CDT 2006


Dmitry Timoshkov wrote:
> 
> At this point WM decides to correct position of an invisible application's
> window (why?)

In the metacity log, this is in the proper order (the window is mapped, 
metacity sets its position, and the window is withdrawn). I would 
conclude that this is a race; remember that if the app calls map, unmap 
then some events that occurred prior to the unmap request can still 
arrive after the unmap request. This is the asynchronicity I was talking 
about.

  to shift it below the top GNOME top panel by 25 pixels (btw,
> that's why I wrongly thought that the top GNOME top panel remained above
> in Z order of the main game's window, actually they do not overlap each 
> other).

Metacity does this with all windows (keeps them below the panel) unless 
there's some reason not to (such as fullscreen); it's a longstanding UI 
decision.

> For some reason WM does this in a very inefficient way in multiple steps:
> 
> trace:event:process_events ConfigureNotify for hwnd/window 0x10024/2000001
> trace:x11drv:X11DRV_ConfigureNotify win 0x10024 new X rect 0,25,640x512 
> (event 0,0,640x512)
> trace:win:GetWindowRect hwnd 0x10024 (0,0)-(640,512)
> trace:x11drv:X11DRV_ConfigureNotify 0x10024 moving from (0,0) to (0,25)
> trace:win:SetWindowPos hwnd 0x10024, after (nil), 0,25 (640x512), flags 
> 00000015
> trace:win:dump_winpos_flags flags: SWP_NOSIZE SWP_NOZORDER SWP_NOACTIVATE
> trace:x11drv:X11DRV_SetWindowPos hwnd 0x10024, after (nil), swp 0,25 
> 640x512 flags 00000015
> trace:x11drv:SWP_DoWinPosChanging hwnd 0x10024, after (nil), swp 0,25 
> 640x512 flags 00001815
> trace:x11drv:SWP_DoWinPosChanging current (0,0)-(640,512) style 80000000 
> new (0,25)-(640,537)
> trace:x11drv:X11DRV_set_window_pos win 0x10024 window (0,25)-(640,537) 
> client (0,25)-(640,537) style 80000000
> trace:win:RedrawWindow 0x10024 whole window flags: RDW_ERASE 
> RDW_ERASENOW RDW_FRAME
> trace:x11drv:X11DRV_SetWindowPos  status flags = 0805
> trace:event:process_events ConfigureNotify for hwnd/window 0x10024/2000001
> trace:x11drv:X11DRV_ConfigureNotify win 0x10024 new X rect 0,25,640x512 
> (event 0,25,640x512)
> trace:win:GetWindowRect hwnd 0x10024 (0,25)-(640,537)
> trace:event:process_events ConfigureNotify for hwnd/window 0x10024/2000001
> trace:x11drv:X11DRV_ConfigureNotify win 0x10024 new X rect 0,25,640x512 
> (event 0,25,640x512)
> trace:win:GetWindowRect hwnd 0x10024 (0,25)-(640,537)
> trace:event:process_events ConfigureNotify for hwnd/window 0x10024/2000001
> trace:x11drv:X11DRV_ConfigureNotify win 0x10024 new X rect 0,25,640x512 
> (event 0,25,640x512)
> trace:win:GetWindowRect hwnd 0x10024 (0,25)-(640,537)
> trace:event:process_events ConfigureNotify for hwnd/window 0x10024/2000001
> trace:x11drv:X11DRV_ConfigureNotify win 0x10024 new X rect 0,25,640x512 
> (event 0,25,640x512)
> trace:win:GetWindowRect hwnd 0x10024 (0,25)-(640,537)
> trace:event:process_events MapNotify for hwnd/window 0x10024/2000001
> 
> Last line above confuses a lot: why WM behind our back maps a window? 
> What may
> be a reason behind that? 

 From the metacity log, it looks to me like WINE here withdraws the 
window, turns on window decorations, then remaps the window.

Metacity then has to unmap/map one more time in order to place the 
window inside its window frame. Undecorated windows don't have a frame 
so don't have the extra unmap/map caused by reparenting, but normal 
windows do.

Clients and WMs both have to distinguish between maps that are 
incidental to implementation details and maps that have a meaning in the 
ICCCM. Essentially you need a "withdrawn" flag on windows indicating 
whether you have yourself mapped or unmapped the window. The WM may also 
map/unmap in order to reparent, manage workspaces, etc. and you should 
just ignore those map events most of the time.

If you need a "steady state" mapped status that matches the Windows API, 
then you would need to "simulate" it on the client side, by e.g. using 
the client-side withdrawn flag instead of the mapped state.

> That leads to a lot of confusion later: Wine 
> thinks
> that a window is not visible and ignores take focus client message below,
> while WM starts to send focus messages to the window:
> 
> trace:event:process_events Expose for hwnd/window 0x10024/2000001
> trace:x11drv:X11DRV_Expose win 0x10024 (2000001) 0,0 640x512
> trace:win:RedrawWindow 0x10024 rect (0,0)-(640,512) flags: 
> RDW_INVALIDATE RDW_ERASE RDW_ALLCHILDREN
> trace:event:process_events FocusIn for hwnd/window 0x10024/2000001
> trace:event:EVENT_FocusIn win 0x10024 xwin 2000001 detail=NotifyNonlinear

X will not send focus events to unmapped windows btw, if it's useful to 
rely on that behavior.

> The log above makes me ask several questions:
> 
> 1. Why the WM thinks that it knows better than the app where to place 
> its window
> and insists on moving it to another position? That's not a user related 
> interaction
> related to moving a window using mouse or a keyboard, IMO the WM should 
> not do
> this kind of things behind applications back.
> 

As I mentioned before, there is no way to tell in the WM what is 
user-initiated and what isn't, so any policies on window positioning 
have to be for all configure requests (though the WM can and does adjust 
the policy for window type, etc.).

metacity keeps windows from overlapping the panel because most of the 
time that results in a better UI; this isn't anything new, it's been in 
GNOME for years.

Plenty of just normal document editor or dialog type windows try to open 
at 0,0 (which in GNOME would cover up the applications launcher menu) so 
metacity keeps them underneath that. It'd be pretty annoying to use 
GNOME otherwise.

A philosophical problem here is that you're trying to be a managed 
window and trying to do everything yourself at the same time. This can 
be done, but tends to be the hard path; the easy paths are to just be 
override redirect (though I consider that broken, it may be required to 
make wine work) or to just let the WM do everything (e.g. set the 
fullscreen state and don't do your own resizing, undecorating, and so 
forth that might confuse matters).

Some ideas:
  - if setting the vid mode viewport presumably you will also end
    up needing to grab the pointer... in this case there's
    little downside to using override redirect since no "window
    management" is possible anyhow
  - figure out how to get the fullscreen state set... unfortunately
    metacity doesn't understand vid modes, which will make this
    not really work right
  - patch metacity to understand vid modes (are there "vid mode events"?)
  - could you put the vid mode viewport in a different place, e.g.
    in the middle of the screen, then offset all Windows positions
    requests to the viewport? (too much of a hack? would it work?)

> 2. How that could happen that the WM maps a window to the screen 
> although it
> clearly was not asked to?

If your window is withdrawn, it would be a bad bug for the WM to map it; 
but in the metacity log I see no evidence of this happening. However, if 
your window is currently in the normal/managed state, the WM _must_ 
unmap/map from time to time in order to work; WMs work in different ways 
but e.g. creating the frame by ReparentWindow to the frame window is 
pretty standard and causes unmap/map events. Metacity also implements 
multiple workspaces and minimization by unmapping, it's a bit unusual to 
do workspaces this way, but many or even most WMs do minimization this way.

Havoc




More information about the wine-devel mailing list