Support 
RB
 Solipsism Gradient 
Support Forums
Rainer Brockerhoff
Solipsism Gradient   XML (RSS 2.0)
Goto page 1, 2, 3 ... 102, 103, 104  Next Copy this: Trackback Ping URL for this topic
   Support Forum Index -> Rainer Brockerhoff's Weblog
My latest photos [RSS 2.0]
www.flickr.com
Links & subscriptions
Your mileage may vary. Some names have been shortened. [*]s link to RSS feeds.

My Technorati profile

Comics
Dilbert [*]
Doctor Fun [*]
Liberty Meadows [*]
Medium Large [*]
PvPonline [*]

Weblogs
43 Folders [*]
Aaron Swartz [*]
Adventures of AccordionGuy [*]
Advogato [*]
Alastair's Place [*]
all noise all the time [*]
ambiguous [*]
Andy Ihnatko's YellowText [*]
andymatuschak.org [*]
Anil Dash [*]
Armed and Dangerous [*]
aurgasm [*]
Backup Brain [*]
Bag and Baggage [*]
BarlowFriendz [*]
bbum's weblog-o-mat [*]
Ben Hammersley.com [*]
Benjamen Walker's Theory Of Everything [*]
Betalogue [*]
Beyond the Beyond [*]
Big Nerd Ranch Weblog [*]
Blake Ross on Firefox and Beyond [*]
blakeseely.com - Blog [*]
Boing Boing Blog [*]
bramcohen [*]
Brilliant Corners [*]
Burningbird [*]
cabel.name [*]
Call Me Fishmeal. [*]
carpeaqua [*]
chaotic intransient prose bursts [*]
Chief Blogging Officer [*]
Chris Hanson [*]
codepoetry [*]
Cognitive Daily [*]
The Comics Curmudgeon [*]
Cool Tools [*]
Corante: Copyfight [*]
Corbin's Treehouse Blog [*]
Critical Section [*]
Cult of Mac [*]
Culture Hack [*]
Daring Fireball [*]
The Daily WTF [*]
0xDECAFBAD [*]
DeepFUN [*]
devixstudio's Photos [*]
Different Thinker [*]
The Dilbert Blog [*]
Ditchnet.org [*]
Doc Searls [*]
Don Box's Spoutlet [*]
Dowbrigade News [*]
DrunkenBlog [*]
Due Diligence [*]
Epeus' epigone [*]
Eric.Weblog() [*]
Ernie the Attorney [*]
Escapable Logic [*]
evhead [*]
FatBits: John Siracusa's Journal [*]
figby.com [*]
flow|state [*]
Folklore.org [*]
Forwarding Address: OS X [*]
Freedom To Tinker [*]
Fritz Anderson's Weblog [*]
F-Secure Antivirus Research Weblog [*]
FurdLog [*]
GlennLog [*]
Glorified Typist [*]
Godwin's Law [*]
Google Blog [*]
Google Earth Blog [*]
Google Weblog [*]
growabrain [*]
[GusMueller blog] [*]
Guy Kawasaki [*]
h4ck3r+=boi [*]
Halley's Comment [*]
Helpful Tiger [*]
How to Save the World [*]
HyperJeff Blog [*]
iClub RSS Feed [*]
Inessential [*]
Interconnected [*]
James Duncan Davidson [*]
Jeffrey Veen [*]
Jeffrey Zeldman Presents [*]
Jeremy Zawodny's blog [*]
jnd.org [*]
Joel on Software [*]
Joho the Blog [*]
Joi Ito's Web [*]
Jonathon Delacour [*]
Jon's Radio [*]
Jorgen Thelin's weblog [*]
just like heaven [*]
The J-Walk Blog [*]
Karelia Software [*]
Karelia's Cocoa Open Source [*]
kottke.org [*]
Language Log [*]
Lessig Blog [*]
Lockergnome Bytes [*]
Loic Le Meur Blog [*]
MacBlog [*]
Mac Geekery - Get your geek on. [*]
Mad Professor [*]
Making Light [*]
Matt Croydon::postneo [*]
Matt Gemmell [*]
Membranophonist's Ramblings [*]
Memepool [*]
michael-mccracken.net [*]
Michael Tsai's Weblog [*]
Mind Hacks [*]
MoCoLoco [*]
Modern Geekery [*]
Musings From the Software Underground [*]
Neil Gaiman's Journal [*]
the [non]billable hour [*]
NSBlog [*]
NSLog(); [*]
ongoing [*]
On the Thought [*]
Out of Cheese [*]
Paolo Valdemarin [*]
Paul Graham [*]
Peak Oil Optimist [*]
Philip Greenspun Weblog [*]
C:\PIRILLO.EXE [*]
Plastic Bag [*]
PragDave [*]
Presentation Zen [*]
The Presurfer [*]
Rainer Brockerhoff's Photos [*]
raoli.com [*]
Ranchero [*]
Rands in Repose [*]
Reality and Rhetoric [*]
Recycled Knowledge [*]
Red Sweater Blog [*]
Reflex›es de um c‹o com pulgas... [*]
rentzsch.com [*]
ridiculous_fish [*]
Ross Mayfield's Weblog [*]
Russ Nelson [*]
Russell Beattie Notebook [*]
Sam Ruby [*]
SATN [*]
Der Schockwellenreiter [*]
Scobleizer Weblog [*]
Sci-Fi Hi-Fi [*]
scribble, scribble, scribble... [*]
Scripting News [*]
Seb's Open Research [*]
A Shareware Life [*]
Shirt Pocket Watch [*]
Untitled Source [*]
Sifry's Alerts [*]
SIGPIPE 13 [*]
Simon Willison's Weblog [*]
Solipsism Gradient [*]
Squawks of the Parrot [*]
stanforth.org :: geekview [*]
Stefan Tilkov's Random Stuff [*]
stevenberlinjohnson.com [*]
~stevenf [*]
Superf’cie Reflexiva [*]
Surfin' Safari [*]
talblog [*]
taliesin's log [*]
Teal Sunglasses [*]
Technorati Tag: Apple [*]
Technorati Tag: cocoa [*]
Tesugen.com [*]
Theobroma Cacao [*]
The Tao of Mac [*]
ThinkMac Blog [*]
This is not your practice blog [*]
tima thinking outloud. [*]
Untitled Source [*]
TooMuchSexy.blog [*]
Toxic Software (Blog) [*]
The Trademark Blog [*]
Trader Mike [*]
The Unofficial Apple Weblog [*]
The Unofficial Photoshop Weblog [*]
Unsanity.org [*]
Urbanape : [*]
VenChar [*]
viridiandesign [*]
Webpropaganda [*]
What Do I Know [*]
Who Cares? [*]
whytheluckystiff.net [*]
Words [*]
Writers Block Live [*]
XCode Experiences [*]
Ztuff [*]

News sites
80211b News [*]
ADC Reference Library Updates [*]
Amazon SF&Fantasy [*]
Ananova: Quirkies [*]
Apple Developer Connection Headlines [*]
Apple Knowledge Base [*]
Apple Hot News [*]
Apple Press Releases [*]
Ars Technica [*]
BBC News | Technology [*]
CocoaDev RecentChanges [*]
Computerworld Shark Tank [*]
CNET News.com [*]
CNN.com [*]
CNN.com - Offbeat [*]
Digital Photography [*]
Download Squad [*]
DreamHost Blog [*]
EurekAlert! [*]
FlickrBlog [*]
Folha Online - Brasil [*]
Folha Online - Cotidiano [*]
Folha Online - Dinheiro [*]
Folha Online - Ilustrada [*]
Forbes.com News [*]
Forbes.com Technology News [*]
Gizmo Emerging Technology Magazine [*]
Gizmodo [*]
INFO Online [*]
kuro5hin.org [*]
MacBetaGroup [*]
MacDevCenter [*]
MacInTouch [*]
MacMegasite [*]
MacMerc [*]
MacNN [*]
MacUpdate - Mac OS X [*]
MacSlash [*]
Moreover Science [*]
Museum of Hoaxes [*]
Nature Science Update [*]
New Scientist [*]
NewsFactor Network [*]
NYT: Health [*]
NYT: International [*]
NYT: National [*]
NYT: Science [*]
NYT: Technology [*]
NYT: Travel [*]
Open Source Applications Foundation Blog [*]
O'Reilly Network Articles [*]
Salon.com [*]
Science Blog [*]
Scientific American [*]
Slashdot [*]
Techdirt [*]
The Register [*]
ThinkGeek: What's New [*]
TidBITS [*]
Treehugger [*]
Versiontracker [*]
Wired News [*]
View previous topic :: View next topic  
Author Message
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 02 Jan 2009 22:09:13    Year++ Reply with quote

It's been a couple of weeks since my last post, but I haven't been idle. Well, a few of the holidays excepted, of course. Here's what's on my radar for the new year, or at least for the first months.

I've finally had time to look at the SnowLeopard (Mac OS X 10.6) beta. Can't say much about it, except that there are interesting and significant changes in the infrastructure - important for programmers. I really hope that, once out, a majority of users will adopt it.

A consequence of seeing the 10.6 APIs is that I decided to do a serious rework of Klicko and Quay, so they'll be ultimately easier to migrate to 10.6 and a 64-bit environment. Klicko inherited a lot of code, and I'm really glad that I decided to do it as a training exercise, since I'll very soon back-port much of that back to Quay, after enhancing and optimizing.

If all goes well, Klicko 1.1 will be out soon. I've got all but installation and updating procedures done. Most notably, it's now a System Preferences panel that installs a background process. While this is a departure from the easy-to-run, simple-Cocoa-app mantra, splitting this type of application into a faceless background process and a foreground GUI will soon be mandatory for all practical purposes, and there are advantages; for the user, once properly installed and configured, Klicko will "just work" automatically and in the background, and use very few resources.

One new Klicko feature was requested by several users (and others who have emailed me in the past). There will be a (configurable) preference to have the window's "zoom" button do a true maximize - or at least attempt to, not all applications will support it properly. While I find the importance that Windows users attach to maximizing everything all the time a little puzzling, trying it out convinced me that it's useful now and then. I always maximize NetNewsWire, Xcode, and a few other application windows, for instance. I also decided that it may be useful in pointing users that are new to the Mac to shareware software in general and to my own applications.

Once that is done - hopefully with very few build updates - it's back to reimplementing everything I learned into Quay (probably 1.2). I'm not decided whether that will become a preferences panel too, but it may be possible. More importantly, I'm now pretty fluent with the event tap and accessibility APIs that both Quay and Klicko use.

The major new feature of Quay will be that Quay menus will also pop up for Finder icons. Ultimately, I'd like to make this work in any and all Finder window modes - icon, list and column - and in all circumstances where the Finder's own contextual menus pop up. I've done some preliminary testing and it looks like it might be possible. There are a few edge cases where I'm not sure that I'll be able to compute the correct path for the icon.

Anyway, if all works as planned, I'll be able to introduce more flexibility through plug-ins. A plug-in would get a file or folder handed to it and would produce either a popup menu, or an information window. This would allow me to finally declare XRay entirely defunct (it already runs very poorly on Leopard), and replace it with many small, specialized plug-ins. My older contextual menu plug-ins, like Zingg! and Nudge would also be trivial to rewrite as Quay plug-ins.

A similar, much more ambitious plug-in scheme, was planned for XRay II, and I can reuse some of that code... there are still some complex issues to decide, however. Opening the plug-in interface to other developers is of course what I'd like to do, but licensing, updating, keeping plug-ins from interfering with each other will be very tricky.

All in all there's lots of ideas to implement and this should keep me busy for most of the year. I'm not considering going into iPhone/iPod development for now; there's a glut of $0.99 applications and the way the App Store is working seems overly opaque to me.

More soon! Stay tuned.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 18 Dec 2008 09:00:25    Klicko 1.0.1 (123) Reply with quote

Well... let's hope this one will last more than a few hours...? icon_smile.gif
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 17 Dec 2008 20:12:41    Cocoa musings pt.2 Reply with quote

One of the nice things Objective-C inherited from C is the switch statement. If you have set different tags in all your menu items, you often find you can do things like:
Code:

- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
   switch ([menuItem action]) {
   case 1:
      ...
   case 2:
      ...
   }
   return YES;
}

Those tags have to be set in Interface Builder, and you probably will have an enum somewhere to use symbolic constants instead. However, the standard C switch() is restricted to integer values; you can't switch on strings or selectors. So, if you don't want tags and need to switch on the menu item's selectors, you'll have to do:
Code:

- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
   SEL action = [menuItem action];
   if (action==@selector(firstAction:)) {
      ...
   } else if (action==@selector(secondAction:)) {
      ...
   } else...
   return YES;
}

Bearable if you have two, or even four or five cases, but what if there are dozens? Or suppose you have to compare strings instead of selectors:
Code:

- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
   NSString* title = [menuItem title];
   if ([title isEqualToString:@"firstTitle"]) {
      ...
   } else if ([title isEqualToString:@"secondTitle"]) {
      ...
   } else...
   return YES;
}

Not that it's recommendable, in practice, to compare menu item titles, but it's a good example.

Well, there are other ways to make this more readable, or even more efficient. But here's one neat way to convert a group of strings into integers for use in a switch(). First, let's write an utility C function to do so:
Code:

NSUInteger CaseCodeForString(NSString* string) {
   static NSArray* array = nil;
   if (!array) {
      array = [[NSArray alloc] initWithObjects:
               @"zeroth string",
               @"first string",
               @"second string",
               @"third string",
               ...
            nil];
   }
   return [array indexOfObject:string];
}

Note the standard lazy allocate-once trick of declaring array static, initialize it to nil, and test before using. Anyway, this function will return 0 if you feed it @"zeroth string", 1 for @"first string" and so forth... and return NSNotFound if the string isn't in the array. So you could, in our last example, do:
Code:

- (BOOL)validateMenuItem:(NSMenuItem*)menuItem {
   switch (CaseCodeForString([menuItem title])) {
   case 0:
      ...
   case 1:
      ...
   }
   return YES;
}

If there are many strings, this will be faster than a series of isEqualToString: calls; this is because NSArray uses a hash table to find the index of a particular object, and only goes into the actual string comparison if the two string's -hash methods return the same value.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 17 Dec 2008 16:10:01    Klicko 1.0.1 builds 119 and 120 out Reply with quote

Pushed out 119, then literally a second later got a bug report, had to do 120. Sorry about that.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 15 Dec 2008 11:38:19    Re: Cocoa musings pt.1 Reply with quote

In my post on event taps, I mentioned the following code to get a global event tap:
Code:

   CFMachPortRef tapg = CGEventTapCreate(kCGAnnotatedSessionEventTap, kCGEventTapOptionDefault,
      CGEventMaskBit(kCGEventLeftMouseDown)|CGEventMaskBit(kCGEventLeftMouseUp),
      ProcessEvent,NULL);

This taps the event stream at the "annotated session" point (hence the kCGAnnotatedSessionEventTap parameter). Basically, this means that the event has already been analyzed as to destination application, and you can ask the passed event directly for that application's process ID. This is was I was using in Klicko.

Unfortunately the docs don't mention another step that takes place while "annotating" a mouse-down event: apparently, if the click was on a window's title bar (not elsewhere in the window), the owning process is brought to the front before the tap sees the event! Klicko's processing varied depending on the clicked-on window's and the owning process' state, so I was seeing different results depending on the click location - title bar or inside the window. Worse, a workaround I needed to do to bring non-main windows to the front for background processes wouldn't be applied at all if the user clicked on a title bar!

A more subtle consequence was that I was intercepting (and discarding) mouse clicks, while the system was expecting the click that brought the process to the front to actually arrive at the process... the result was that, while the menu bar changed to the process, its windows would remain in the back.

After beating my head against this wall for several days, I was rereading the CGEvent docs again for ideas and noticed that I hadn't tried applying a global tap before event annotation:
Code:

   CFMachPortRef tapg = CGEventTapCreate(kCGSessionEventTap, kCGEventTapOptionDefault,
      CGEventMaskBit(kCGEventLeftMouseDown)|CGEventMaskBit(kCGEventLeftMouseUp),
      ProcessEvent,NULL);

Note the kCGSessionEventTap parameter. This meant that I had to discover the owning application's process ID myself (instead of asking the mouse-down event directly). Premature optimization strikes again; I'd selected the annotated tap just to avoid doing these steps.

At any rate, I immediately discovered that I now could properly intercept clicks anywhere, discard them, and do process and window activation as I wanted to. Well, almost; there was still some redundant window activation to do, as Carbon and Cocoa apps seem to still have some residual differences in that regard. I'll be filing bugs at Apple about some of these things.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 15 Dec 2008 11:15:27    Klicko 1.0.1 (113) hopefully final Reply with quote

This latest build of Klicko fixes all known bugs and edge cases, and some memory leaks. Hopefully this will be the last build for a long time.

In my next post I'll explain some technical details.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 08 Dec 2008 19:25:47    Travel updates Reply with quote

Oops. I just realized I forgot to update my travel maps. Here's the current world map (44 countries visited):

and here's zooming in on Europe (28 countries visited):
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 08 Dec 2008 12:30:42    Re: Klicko and Quay bug fixes Reply with quote

Found an error in the code signature for both Klicko and Quay, induced by the presence of a newer signing certificate for iPhone apps.

So I pushed out new builds for Quay 1.1.1 (285) and Klicko 1.0.1 (103). Klicko also has other small improvements; see the release notes.
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 07 Dec 2008 21:17:33    Klicko 1.0.1 (97) Reply with quote

I decided to rev the version number, not just the build number, for this release.

The main reason is that now we have a slight difference (and a UI difference) on first run. Klicko needs "access for assistive devices" turned on in the System Preference, and complains if that's not the case. However, now you have two options:
1- turn "access for assistive devices" on, and click "Continue"
2- click "Authorize" and enter your administrator password.
In the latter case - and this will work only if you installed Klicko inside the main /Applications folder - Klicko will set itself to run in a privileged group that can use the Accessibility API without that option.

Beyond small internal optimizations, the other notable feature in 1.0.1 is that you can change the icon, if you don't like it. Just make or copy your own icon, paste onto Klicko's icon in the Finder's "Get Info" panel, and there it is - you can do this even while Klicko is running! If your icon has a 16x16-pixel version, that one will be used in the menu bar.

Of course, if you have an icon for Klicko that's better than the default one, send it in! It shouldn't be too hard to do... icon_wink.gif
View user's profile AIM Address
Rainer Brockerhoff
Site Admin


Copy this:
Trackback Ping URL
for this post

#Post 06 Dec 2008 11:42:54    Re: Cocoa musings pt.1 Reply with quote

Just saw Rob Keniger's Wrapster plug-in for Coda, an interesting use of event taps; it's a plug-in that intercepts key events for its master application.

The version I looked at (1.2) uses a global tap and checks if its master application is active:
Code:

   if(![NSApp isActive]) {
      return event;
   }

Of course, it would be conceptually more reliable to obtain the event's destination process PSN and test against that; but the best way would be to tap the current process like this:
Code:

   ProcessSerialNumber psn = {kNoProcess, kCurrentProcess};
   CFMachPortRef tapg = CGEventTapCreateForPSN(&psn, kCGTailAppendEventTap, kCGEventTapOptionDefault, CGEventMaskBit(kCGEventKeyDown), ProcessEvent, NULL);

Global event taps are a great tool, but they're also easy to abuse, and I suppose that in a year or two we might have dozens of utilities or plug-ins tapping events; the actual results might be dependent on the order they run or load, for instance, and overall responsiveness might suffer. Therefore, please make absolutely sure that you need a global tap to do whatever you want to do, that it takes as little time as possible, and that it does careful parameter checking.

One great application to test event taps (and to check their presence) is Event Tap Testbench. It's author, Bill Cheeseman, has helped me a lot with subtle details of both event taps and the Accessibility APIs; thanks Bill! Do also check out their other products.

Rob tests if Accessibility is enabled by trying to create a tap and seeing if it succeeds. While this works, I think it's easier to do it like this:
Code:

   if (!AXAPIEnabled()&&!AXIsProcessTrusted()) {
      // error dialog here
   }

The first call checks if Accessibility is enabled in System Preferences; the second checks if your process is allowed to set a key tap even with Accessibility disabled. To achieve this, you must (from a process running as root) call AXMakeProcessTrusted() on the tapping application's executable - this will take effect on its next run.

In the case of Klicko, it taps only mouse button events, for which Accessibility doesn't need to be on; however, it uses the Accessibility APIs to check out details about the clicked-on windows. Some people dislike turning Accessibility on in System Preferences, so a future version of Klicko might use AXMakeProcessTrusted() to avoid this; this means asking the user for an Administrator password and running a separate tool, like Quay does. I'm still evaluating the trade-offs for that: it precludes running Klicko from ~/Applications or from the disk image, adds to the application size, and the user has to navigate an extra dialog on first run.

Update:Klicko now uses AXMakeProcessTrusted().


Last edited by Rainer Brockerhoff on 08 Dec 2008 12:45:56; edited 1 time in total
View user's profile AIM Address
Display posts from previous:   
   Support Forum Index -> Rainer Brockerhoff's Weblog All times are GMT - 3 Hours
Goto page 1, 2, 3 ... 102, 103, 104  Next
Page 1 of 104

 
Jump to:  
You cannot post new topics
You cannot reply to topics
You cannot edit your posts
You cannot delete your posts
You cannot vote in polls


t.gif

Page generated in 2.633 seconds, 14 queries executed