On Sun, Feb 27, 2011 at 12:15:49PM +0100, Szabolcs Nagy wrote: > > 2) The bar gets cut off because configurenotify() expects updategeom() > > to return true only if the ConfigureEvent reports a change to the root > > window's dimensions. While updategeom() does this correctly when > i don't quite understand why the reported width is not the > full display width there
Sorry. Here's what I hope is a clearer explanation: dwm checks for resolution changes by passing ConfigureNotify events through configurenotify, which checks to see if the event is associated with the root window (not 'ConfigureEvent', which doesn't even exist. Whoops!). If it is, the function sets sw and sh (its display resolution variables) to the event's width and height and then runs updategeom to check if the display resolution has actually changed. updategeom returns True if it has, and then configurenotify recreates the bar pixmap with sw as its width and redraws the bar (and everything else). If the resolution's the same, sw and sh remain updated but nothing else happens. It turns out that several root window ConfigureNotify events are generated when a resolution change occurs, but when using the older RandR calls, some of the first ones occur before the root window is resized. The non-Xinerama code responds correctly to this because it checks to see if the new sw and sh values are different than the width and height stored in mons; if they are, then it knows a resolution change has occurred since this is the only place where mons->mw/ww and ->mh/wh are set. These values are updated, updategeom is made to return True (lines 1851-7), and things proceed as described above. Since the other ConfigureNotify events are ignored, the pixmap is redrawn only when sw has been set to the newer horizontal resolution. The Xinerama code in updategeom, however, doesn't check sw and sh when it decides whether or not the resolution's changed (lines 1812-37). Because the information it gets from Xinerama reflects the new screen resolution, it has updategeom return True even when processing an early ConfigureNotify event that occurred before the root window got resized, and which therefore resulted in sw and sh being set to the the previous resolution. This is mostly OK; since the Xinerama information is accurate the members in the monitor struct(s) are set to the correct values, and since the last ConfigureNotify event generated has the new, accurate root window dimensions, sw and sh are also set to correct values before they're used in applysizehints or whereever. However, sw has not been set to the correct value before XCreatePixmap is called in configurenotify. When going from a smaller resolution to a larger one, this means that the bar pixmap gets recreated with the smaller resolution's width. The ConfigureNotify events that occur after the root window has been resized do not cause the pixmap to be recreated correctly because by then the Xinerama code has updated the values it checks and thus does not detect any change. In short: the Xinerama code does not keep track of sw the way the non-Xinerama code does and the way the XCreatePixmap call in configurenotify expects it to. This is a problem when the root window generates a ConfigureNotify event before it's been resized, as occurs when resizing the screen with the RandR < 1.2 calls. Again, this is definitely an edge case! One solution is to have the Xinerama code update sw and sh to the right dimensions when it detects a change. I chose instead to compare them to the sums of the widths and heights stored in the mons list because a) this is closer to what the non-Xinerama code does and b) looping through the mons list and adding everything up seemed less expensive than the Xinerama checks. > > 3) Interestingly, the current code and the previous solution create a > > dc.drawable pixmap that's as wide as the aggregate horizontal > > resolution across all monitors. That makes sense for the non-Xinerama > > code, where the bar stretches from monitor to monitor, but it doesn't > > when each has its own bar. In the latter case the pixmap only has to > > be as wide as the largest monitor's horizontal resolution. The second > this seems reasonable > > i'd use a max-monitor-width global instead of dc.dw > (like sw and sh it's a display geometry related var, > not a dc internal) > imho updategeom shouldn't modify dc or if it does > then do all the work there (createpixmap, updatebars) I originally thought to use a global too, but when I couldn't think of a use for the value aside from creating the bar pixmap, I stuck it in the DC struct. To my mind it's not any different than updating the various members of the Monitor structs, so modifying it in updategeom didn't seem so bad. I'll be happy to rewrite the patch to use max-monitor-width if I'm wrong. Also, maybe it's a good idea to combine the sw and sh check from patch one with the pixmap width adjustment from patch two? > > Even though this happens because of other people's weak code, I think > > 3 (or 2) is the best solution since dwm itself seems to be making some > > incorrect assumptions; however, if the BUGS entry is the right > > solution I'll be happy to write the explanation. > thanks for looking into this Thanks for such great software!