There is confusion in (gtk2) nsWindow::IsVisible over whether it really returns whether the nsWindow is visible or merely that Show(TRUE) has been called. The following callers of nsIWidget::IsVisible are interpreting the return value as IsShown: nsViewManager::AddCoveringWidgetsToOpaqueRegion nsWindowWatcher::OpenWindowJSInternal nsContainerFrame::SyncFrameViewProperties And the windows implementation of nsIWidget::IsVisible returns a value consistent with IsShown. The callers within (gtk2) nsWindow seem to have been designed around VisibilityNotify events and thus seem interested in whether the window is visible to the user. The original (gtk2) nsWindow::IsVisible implementation was based only on VisibilityNotify events. The implementation was changed for bug 241187, when it was discovered that VisibiltyNotify events don't get sent when the window becomes unmapped, and again in bug 281551, when it was discovered that callers wanted IsShown.
Created attachment 362355 [details] [diff] [review] patch This suppresses passing invalidation regions to gdk when the drawing area is not visible to the user. A new IsVisible method is added for use within nsWindow to indicate whether any part of the window is visible to the user. It is unfortunate to have two methods with the same name but different meaning, but I can't think of a name better than IsVisible for the new method. Really it seems that the nsIWidget method has the wrong name but I'd prefer not to change that interface. I've tested this with kwin-3.5.9. Painting is suppressed when windows are minimized or on inactive desktops. Without kompmgr running, painting is also suppressed when windows are fully obscured by other windows. (Apparently the window remains unobscured when mapped and the window manager is compositing, even when the window is behind an opaque window.)
I've been using the patch for a few months, and haven't noticed any problems, and I have noticed that performance is better for invalidation-intensive things on other desktops.
Created attachment 390560 [details] [diff] [review] patch v1.1 updated to trunk and changed the name of the new IsVisible method to CanBeSeen
+ if (!mIsShown || !mIsVisible) + return PR_FALSE; ... + mIsVisible = + topWidget && + !(gdk_window_get_state(topWidget->window) & + (GDK_WINDOW_STATE_ICONIFIED|GDK_WINDOW_STATE_WITHDRAWN)); If mIsVisible gets set to false due to the toplevel window being iconified/withdrawn, how does it ever get set to true again?
(In reply to comment #5) > If mIsVisible gets set to false due to the toplevel window being > iconified/withdrawn, how does it ever get set to true again? It gets set to true in OnVisibilityNotifyEvent() in response to VisibilityNotify events. VisibilityNotify events do not get sent when window changes state from viewable to not viewable (it or an ancestor is unmapped - the X11 concept of viewable [and mapped] differs from GDK's concept when windows are iconified). But VisibilityNotify events do get sent when the window changes state from not viewable to viewable. This is documented here: http://tronche.com/gui/x/xlib/events/window-state-change/visibility.html * When the window changes state from ... not viewable to viewable and completely unobscured, the X server generates the event with the state member of the XVisibilityEvent structure set to VisibilityUnobscured. * When the window changes state from ... not viewable to viewable and partially obscured, the X server generates the event with the state member of the XVisibilityEvent structure set to VisibilityPartiallyObscured. * When the window changes state from ... not viewable to viewable and fully obscured, the X server generates the event with the state member of the XVisibilityEvent structure set to VisibilityFullyObscured.
Comment on attachment 390560 [details] [diff] [review] patch v1.1 Please add a comment explaining that.
Attachment #390560 - Flags: review?(roc) → review+
Status: ASSIGNED → RESOLVED
Last Resolved: 9 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.