Sorry to reply to my reply (to my reply), but now that I am home and can test
with an external monitor too, I found that changing which was the main monitor
does behave differently than the bug I reported.
However, as a really crude test, in GrowlPositionController.m, I added a
NSScreen* global variable (horrible style, but just for a test), which I set to
the first NSScreen pointer -reservedRectsForScreen observed, and then always
used that screen in that method, even if the incoming screen was different.
What I observed when I did this was:
1) Changing graphics cards no longer overlapped. Messages appeared in the
correct place with no errors
2) Plugging in an external monitor and leaving my laptop monitor as the main
monitor worked as expected, with new notifications still appearing on my laptop
screen, in the correct place, without overlapping
3) Changing to make my external monitor the main monitor changed to make
notifications appear on the external display, but they properly started at the
top of the screen (old stickies were still on the laptop screen).
4) Changing back to make my laptop screen the main screen, and new
notifications again appeared on my laptop screen, and still were in the correct
position (no overlapping).
Of course, I cannot test every case, but from this, it seems that reusing the
same NSScreen pointer fixes my bug and did not crash.
Can anyone think of a case where this approach will fail? If I can test it, I
will. Or by caching that pointer (all I do is assign a NSScreen* the value of
the passed in screen), am I creating a memory leak when the screens change? I
don't trust caching a raw pointer. I just suspect that that introduces a chance
for a crash, or else a leak, but as I said, it seems to work so far
Anyway, I'll pretty up my changes and run my custom build for a few days and
see if it ever crashes or uses outrageous memory. But basically, I changed this:
//Returns the set of reserved rect for a specific screen. The return value *is*
the storage!
- (NSMutableSet *)reservedRectsForScreen:(NSScreen *)screen {
NSMutableSet *result = nil;
//Treat nil as the main screen
if (!screen)
screen = [NSScreen mainScreen];
to this:
NSScreen* cachedScreen=0;
//Returns the set of reserved rect for a specific screen. The return value *is*
the storage!
- (NSMutableSet *)reservedRectsForScreen:(NSScreen *)screen {
NSMutableSet *result = nil;
//Treat nil as the main screen
if (!screen)
screen = [NSScreen mainScreen];
if(!cachedScreen)
cachedScreen=screen;
screen=cachedScreen;
Again, as I said, it's quick and dirty, but seems to work so far. If this
change ends up being implemented, there is probably a better way than a global,
but I'm not used to this language and just used what I could make compile!
On May 9, 2011, at 2:45 PM, Dylan Ryan wrote:
> Ok, finally found where the ultimate problem is (I think). After changing the
> video card, [NSScreen mainScreen], and the only element of [NSScreen screens]
> (on my laptop w/o external monitor) change to a different value than they
> used to be, which causes Growl to start using a new, empty set of occupied
> rectangles in the function I referenced earlier (because it looks to growl, I
> assume, like we changed monitors).
>
> That is probably as far as I can debug it directly. It seems that to fix
> this, we have to be able to figure out when a change in mainScreen represents
> a graphics card change but not a screen change, and when it represents
> actually changing the screen. Unfortunately, I am not at all familiar with
> this kind of code, so I am not well-equipped to make a fix. But, at least I
> (think I) found the underlying problem. However, if this is the case, then
> other people may be able to test this, if you have a dual monitor setup on
> any mac, by simply changing which monitor is the "main" monitor (in System
> Preferences) while growl is running (I am blindly guessing that this will
> have a similar effect). I can double-check this later tonight when I get home
> with an external monitor.
>
>
>
> On May 9, 2011, at 2:03 PM, Dylan Ryan wrote:
>
>> Well, I've partially narrowed it down. Still working further, but this may
>> help.
>>
>> I narrowed it GrowlPositionController.m, the -reservedRectsForScreen
>> function (around line 544ish). It looks like after the graphics card change,
>> the
>>
>> result = (NSMutableSet *)CFDictionaryGetValue(reservedRects, screen);
>>
>> line returns nil, and so a new one is created and used. All OTHER
>> notifications always have the same address, but every card change, that
>> function returns nil so a new one is made. Further, it looks like the screen
>> variable that that call uses has a different address only after changing the
>> cards. I'll look further to see if I can find out why, but at least this is
>> something changing when the graphics card changes. Maybe that's enough to
>> make sense to someone else, though, since I'm really shooting blind here.
>>
>>
>> On May 9, 2011, at 11:25 AM, Peter Hosey wrote:
>>
>>> On May 9, 2011, at 11:16:14, Dylan Ryan wrote:
>>>> Do you have any suggestions on where to look in the code?
>>>
>>> Positions are allocated and tracked by the position controller. Like all
>>> GHA and prefpane classes, it's in Core/Source.
>>>
>>> Displays are in Plugins/Displays. This includes the handful of classes that
>>> are technically compiled into GHA but used only by the displays, mainly if
>>> not exclusively as superclasses.
>>>
>>> Each display is represented by a GrowlDisplayPlugin instance. Each visual
>>> display's GrowlDisplayPlugin is responsible for creating
>>> GrowlNotificationDisplayBridges, each of which creates one or more
>>> (currently always one) GrowlDisplayWindowController, each of which manages
>>> one notification window. Each window controller is what requests
>>> reservation of an area on the screen from the position controller.
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "Growl Discuss" group.
>>> To post to this group, send email to [email protected].
>>> To unsubscribe from this group, send email to
>>> [email protected].
>>> For more options, visit this group at
>>> http://groups.google.com/group/growldiscuss?hl=en.
>>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Growl Discuss" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/growldiscuss?hl=en.
>
--
You received this message because you are subscribed to the Google Groups
"Growl Discuss" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/growldiscuss?hl=en.