I'm trying out chromium-tabs. I have an issue where the icon of a tab never gets properly updated after it gets created for the first time. In my CTTabContents subclass, I have:
- (void)tabDidBecomeSelected {
NSLog(#"selected");
[self setIcon:[NSImage imageNamed:#"default"]];
}
- (void)tabDidResignSelected {
NSLog(#"resign selected");
[self setIcon:[NSImage imageNamed:#"notification"]];
}
This should change the icon if the tab resigns its selected status to a different one. But it doesn't. The icon never changes. Note that I've tried the same exact calls in (id)initWithBaseTabContents:(CTTabContents *)baseContents andJid:(NSString *)jid andStatus:(NSString *)status where they work fine, so the calls fail only on an update of the icon later.
I've also made sure the functions are getting called (I see the log statements). What's the problem here? Also, is this the fork that Chrome actually uses? It obviously works in Chrome, which is strange... Am I doing something wrong?
I even tried doing [[[self.browser.windowController window] contentView] setNeedsDisplay:YES]; in the tabDidBecomeSelected functions, to force the whole window to redraw, in case their code for updating the icon fails, but still no luck.
Related
I want to make a windowless application. The problem is that I'm using a framework that shows some alert boxes sometimes, and I'm not able to suppress them (at least not without a crash).
I've set LSBackgroundOnly to 1 (in the info.plist app file), but this doesn't seem to work. Any chance I'm missing something here (maybe some other settings that I need to set)?
I've also tried creating a category for NSWindow:
Overwritten alloc and allocWithZone: so that no window gets created. This works on some situations, but starting a modal session throws exception (because sending a nil parameter to beginModalSessionForWindow:).
Tried overwriting NSApplication's beginModalSessionForWindow: and returned nil everytime, but this leads to EXC_BADACCESS somewhere in the framework (runModalSession: and endModalSession: were also overwritten, but the crash is before any of them being called).
Any other ideas will be welcome.
In case it helps, the framework that I'm using is Twain.Framework, so if instead anyone knows a way to block all UI from twain (this includes error alerts shown when a device is not connected) it would be great if you share.
It's not clear what you're hoping for. Are you hoping for an app that doesn't normally display windows but does allow the third-party framework to show its alerts? Or are you hoping to find a way to prevent the framework from showing its alerts so your app absolutely never has any windows?
If it's the former, you're probably looking for LSUIElement. That's an app which can have some UI elements, but doesn't show in the Dock or the Command-Tab application switcher and doesn't have a menu bar.
I managed to make it 'windowless' (some windows are still shown, but at least they're not visible, and they're automatically closed). I only handled modal windows, since these where shown in my situation.
I made a category for NSWindow, so that all windows are invisible, and can't become key or main windows:
-(BOOL)canBecomeKeyWindow{
[self setOpaque:NO];
self.alphaValue = 0;
return NO;
}
-(BOOL)canBecomeMainWindow{
[self setOpaque:NO];
self.alphaValue = 0;
return NO;
}
Subclassed NSApplication:
-(NSInteger)runModalForWindow:(NSWindow *)aWindow{
return NSCancelButton;
}
-(NSModalSession)beginModalSessionForWindow:(NSWindow *)aWindow{
NSModalSession session = [super beginModalSessionForWindow:aWindow];
[aWindow performSelector:#selector(close) withObject:nil afterDelay:1];
return session;
}
However, this didn't help much. In case of runModalForWindow: everything was good, since the owner of the window received a response. In case of beginModalSessionForWindow: the application got stuck, most probably because the window's owner was waiting for a specific event (e.g. button click) which it never received.
I'm using Xcode 4.2 to write and Clang 3.0 to build a program that demonstrates a particular crash.
The program has a window that it means to keep around that is set in the nib to “Release When Closed”, so it's over-released in subsequent uses. It's meant to be a sheet, so it's shown using beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:. Trying to show the window a second or third time should crash the app.
I remember that happening a year ago, with the program receiving EXC_BAD_ACCESS and that triggering the debugger to stop at that point. I also remember being able to hunt the problem down in Instruments using the Zombies template.
That's what I want (this program is part of a presentation to show debugging techniques), but that's not what's happening now. Now, the program doesn't crash; Instruments shows that the retain count on the window gets down to 1 twice, but no lower, so it does not get deallocated.
That would be fine if the problem stopped there; I could simply hide and show the sheet another time or two. The problem is, the second time I bring up the (should-be-dead-but-still-has-at-least-one-retain-keeping-it-alive) sheet, it's numb.
By that I mean that neither the sheet nor any control in it (it contains a field, a text view, and two buttons) responds to events. The heartbeat does nothing in it; the window has an OK button, but when the window is numb, the OK button does not pulse. Nothing works to dismiss the sheet.
But the program is not crashed. I can still interact with the menus and the Dock shows that the program is responding. If I try to quit it, it beeps, since it has a sheet up.
What's causing the window to go numb, and what can I do about it?
Here's a reduced version of the program that also exhibits the problem: https://github.com/boredzo/NumbWindow
I don't think you should be using -close to make the sheet go away. If you change the [sheet close]; line to be [sheet orderOut:self];, then it works properly.
As for why they're different, I don't know. But my experience has been to always use -orderOut: to dismiss sheets, and never -close. The documentation backs me up on this:
Listing 3 Did-end selector
- (void)didEndSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
}
tl;dr:
You're using the wrong method to make the panel go away.
Here's my situation:
I've written a simple web browser. Tabbed browsing was easy enough to get working once I wrapped my head around the concepts and figured how to perform operations on specific tabs. It works well and is pretty reliable under most circumstances.
A problem has plagued me, however, and I cannot figure out its cause.
Let's say I open a new tab and navigate to YouTube. I click on a video and the flash player loads. The video plays and all works fine. I now create another new tab and navigate to some site. The audio from the youtube player stops completely.
When I switch back to the youtube tab, the page will all still be there just as it was except the player has to reload completely, as if I had just reloaded the page. This seems to apply to other plugin types as well.
What's causing this?
Garbage collection is not enabled and as far as I know I'm creating the web views properly. Is there some silly, simple little thing that I missed somewhere along the line?
The - (void)setHostWindow:(NSWindow *)hostWindow method on WebView is probably what you're looking for.
I had the same problem with the flash in a WebView reloading whenever the syle mask of the enclosing window was changed. Wrapping the call to setStyleMask fixed the problem, as follows:
NSWindow *hostWindow = [[NSWindow alloc] init];
[self.webView setHostWindow:hostWindow];
[[self windowForSheet] setStyleMask:styleMask];
[self.webView setHostWindow:nil];
[hostWindow release];
The documentation for the method isn't stellar, but it does explicitly state a having a WebView inside a NSTabView as one of the use cases:
This method sets the receiver’s host window to hostWindow. Your application should only use this method if a web view is going to be removed from its window temporarily, and you want the web view to continue operating (for example, you don’t want to interrupt a load in progress). Since the receiver retains hostWindow, it is your responsibility to set the host window to nil before closing the window to avoid a retain loop.
For example, you might invoke this method if you attach a web view to an NSTabView object (as in a tabbed browser implementation). The NSTabView object takes views out of the window when they are not in the active tab, so you need to invoke this method before the web view is removed from its window. If you don't invoke this method, plug-ins will stop operating when the web view is removed from its window.
I had a similar problem but with a window with a webView that is closed and restored. Unfortunately the solution by #mlwelles did not solve the problem alone.
What did solve however is removing the webView from the window before it closes (proper "timing" is important). What I came up with is something like this:
id contentView;
id tmpHostWindow;
[window setDelegate:self];
- (BOOL)windowShouldClose:(NSNotification *)notification
{
// set temporary hostWindow on WebView and remove it from
// the closed window to prevent stopping flash plugin
// (windowWillClose would be better but that doesn't always work)
tmpHostWindow = [[NSWindow alloc] init];
[webView setHostWindow:tmpHostWindow];
[window setContentView:nil];
[contentView removeFromSuperview];
return TRUE;
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
// restore "hidden" webview
// (would be better to do it in applicationShouldHandleReopen
// but that seems to be too early (has no effect)
if ([window contentView] != contentView) {
[window setContentView:contentView];
[webView setHostWindow:nil];
tmpHostWindow = nil;
}
}
I have created a fairly simple screensaver that runs on Mac OS 10.6.5 without issue.
The configuration screen has accumulated quite a few different options and I'm trying to implement my own preview on the configureSheet window so the user (just me, currently) can immediately see the effect of a change without having to OK and Test each change.
I've added an NSView to the configureSheet and set the custom class in Interface Builder to my ScreenSaverView subclass. I know that drawRect: is firing, because I can remove the condition for clearing the view to black, and my custom preview no longer appears with the black background.
Here is that function (based on several fine tutorials on the Internet):
- (void)drawRect:(NSRect)rect
{
if ( shouldDrawBackground )
{
[super drawRect:rect];
shouldDrawBackground = NO;
}
if (pausing == NO)
[spiroForm drawForm];
}
The spiroForm class simply draws itself into the ScreenSaverView frame using NSBezierPath and, as mentioned, is not problematical for the actual screensaver or the built-in System Preferences preview. The custom preview (configureView) frame is passed into the init method for, um, itself (since its custom class is my ScreenSaverView subclass.) The -initWithFrame method is called in configureSheet before returning the configureSheet object to the OS:
[configureView initWithFrame:[configureView bounds] isPreview:YES];
Maybe I don't have to do that? It was just something I tried to see if it was required for drawing.
I eventually added a delegate to the configureSheet to try triggering the startAnimation and stopAnimation functions of my preview via windowWillBeginSheet and windowWillEndSheet notifications, but those don't appear to be getting called for some reason. The delegate is declared as NSObject <NSWindowDelegate> and I set the delegate in the configureSheet method before returning the configureSheet object.
I've been working on this for days, but haven't been able to find anything about how the OS manages the ScreenSaverView objects (which I think is what I'm trying to emulate by running my own copy.)
Does anybody have any suggestions on how to manage this or if Apple documents it somewhere that I haven't found? This isn't really required for the screensaver to work, I just think it would be fun (I also looked for a way to use the OS preview, but it's blocked while the configureSheet is activated.)
OK, there are a couple of 'duh' moments involved with the solution:
First of all, I was setting the delegate for the sheet notifications to the sheet itself. The window that the sheet belongs to gets the notifications.
Secondly, that very window that the sheet belongs to is owned by System Preferences, I don't see any way to set my delegate class as a delegate to that window, so the whole delegate thing doesn't appear to be a viable solution.
I ended up subclassing NSWindow for the configureSheet so that I could start and stop animation on my preview by over-riding the makeKeyWindow and close methods.
- (void) makeKeyWindow
{
if (myPreview != nil)
if ( ! [myPreview isAnimating])
{
[myPreview startAnimation];
}
[super makeKeyWindow];
}
I also had to add an IBOutlet for my preview object itself and connect it in Interface Builder.
Still working out a couple of issues, but now when I click on my screensaver Options button, my configureSheet drops down and displays its own preview while you set options. Sheesh. The hoops I jump through for these little niceties. Anyway, I like it. Onward and upward.
I'm writing a mozilla plugin on the mac. I'm trying to capture events like button clicks, etc. I've done the normal thing of creating my views in inteface builder, and linking the sentActions to methods in my program. This works in stand-alone programs.
However, in my NPAPI plugin, those methods never get called. The button reacts, depresses, whatever, but it doesn't do its action.
Instead, the NPP_HandleEvent method gets called, but I never get the MouseDown or MouseUp event, only the UpdateEvt.
I set up the buttons to accept clicks via: (superview is the Mozilla view, topview is the top of my view hierarchy.)
[superView setNextResponder: topView];
[topView setNextResponder: nil];
[browserWindow makeFirstResponder: topView];
NEVER MIND: I'm an idiot. It IS calling the button sent actions. I was looking at the wrong method. That'll teach me to leave around a zoom: method when I'm actually using a doZoom: method... D'oh,.
So, the problem was that I wasn't able to get buttons to work. The buttons were supposed to (for example) zoom an image in an IKImageView. (or rather, zoom the view). It didn't appear that it was working. The screen was flashing a lot, but nothing was happening... I put a printf in my zoom method, and it was NEVER GETTING CALLED! and so I asked the question.
Later, I noticed that I wasn't TRYING to call zoom, I was calling doZoom! doZoom WAS being called. And the reason that it wasn't zooming was an unrelated problem.
The problem ended up being that I was sending setImage to my IKImageView on every event, which re-set the view to 1-1, rightside up mode. Once I took out the extra setImage call, things started to work.
In the unlikely event that anyone else every experiences this, the answer is my cunning plan for world domination:
step 1: Don't be an idiot.
step 2: ???????
step 3: Dominate the world.
(If I could master step 1, I might just be able to figure out what step 2 was B-)