Re: Forwarding key events to a non first responder?
Re: Forwarding key events to a non first responder?
- Subject: Re: Forwarding key events to a non first responder?
- From: Phillip Morelock <email@hidden>
- Date: Wed, 12 Jun 2002 15:45:00 -0700
Re: the first responder delegation problem
Some (unchecked) sample code (concept of it directly lifted from the
article):
#include <objc/objc-class.h>
#include<string.h>
...
- (id) aNormalMethodWeAreOverriding: (id) someArg
{
static IMP superselector = nil;
id retval;
if ( superselector == nil)
{
superselector = __myLookup( self->isa,
"aNormalMethodWeAreOverriding", "id" );
}
__doMyFunkyDanWoodStuff( someArg );
retval = __myRealityDispatcher( self->isa, superselector, someArg );
return retval;
}
and somewhere previously defined:
void __doMyFunkyDanWoodStuff( id someArg )
{
static NSTableView *tableView = nil;
if (tableView == nil)
{
tableView = [MyGlobalClass tableView];
}
if (the arg meets my criteria)
{
[tableView send: the: message: i: wanted: to: send:];
}
}
IMP __myLookup(struct objc_class *l_isa, const char *target, const char
*types )
{
const char *my_meth_name;
const char *my_meth_types;
IMP retimp = nil;
struct objc_method *currMethod;
struct objc_method_list* mlist = l_isa->methodLists;
int j = 0;
int seen = 0;
int ct = mlist->method_count;
for ( ; j < ct && seen < 1; ++j )
{
currMethod = (mlist->method_list + j);
my_meth_name = (const char *)currMethod->method_name;
my_meth_types = currMethod->method_types;
if ( 0 == strcmp(my_meth_name, target)
&& 0 == strcmp(my_meth_types, types)
)
{
++seen;
retimp = currMethod->method_imp;
}
}
return retimp;
}
Now the real challenge would be to implement:
__myRealityDispatcher( self->isa, superselector );
That one is over my head at the moment. Of course, what I just wrote might
be bad news, too, YMMV. This is all pretty nasty. I really wish someone
would come on and say "no, it's much easier to work around this."
cheers
fillup
P.S. From the documentation for NSObject:
IMP is defined as a pointer to a function that returns an id and takes a
variable number of arguments (in addition to the two "hidden" arguments-self
and _cmd-that are passed to every method implementation):
typedef id (*IMP)(id, SEL, ...);
On 6/12/02 2:12 PM, "Phillip Morelock" <email@hidden>
wrote:
>
> Any suggestions to accomplish this somewhat gracefully?
>
>
Not gracefully, but...
>
>
This problem got me thinking...a little hacking is my best idea for a
>
solution at this point.
>
>
http://www.macdevcenter.com/pub/a/mac/2002/05/31/runtime_parttwo.html
>
>
From this article about the Objective C runtime, where he talks about the
>
structure of objects, he talks about the structures that you can point into
>
to find overridden methods.
>
>
"During method lookup, the runtime traverses the arrays of methods in the
>
order they are stored. That order is the reverse of the order in which each
>
group of methods is loaded. As the class must be loaded before categories
>
are added to the class, the methods declared in a class itself are always
>
loaded first, so end up last in the list. Since the runtime does method
>
lookups from first-to-last, a category method will always override a method
>
declared in the class itself. "
>
>
Relevant code / header snippets:
>
>
struct objc_class
>
{
>
struct objc_class *isa;
>
struct objc_class *super_class;
>
const char *name;
>
long version;
>
long info;
>
long instance_size;
>
struct objc_ivar_list *ivars;
>
------> struct objc_method_list **methodLists; <--------
>
struct objc_cache *cache;
>
struct objc_protocol_list *protocols;
>
};
>
>
and:
>
void showMethodGroups(Class klass, char mType) {
>
void *iterator = 0; // Method list (category) iterator
>
struct objc_method_list* mlist;
>
Method currMethod;
>
int j;
>
while ( mlist = class_nextMethodList( klass, &iterator ) ) {
>
printf (" Methods:\n");
>
for ( j = 0; j < mlist->method_count; ++j ) {
>
currMethod = (mlist->method_list + j);
>
printf (" method: '%c%s' encodedReturnTypeAndArguments: '%s'\n",
>
mType,
>
(const char *)currMethod->method_name,
>
currMethod->method_types);
>
}
>
}
>
}
>
>
>
So, yesterday I suggested hacking NSResponder, and this is just me looking
>
into it because this problem is nagging my brain. You see how the above
>
makes it possible. To do it, you could (caveat emptor) just put a category
>
on NSResponder and override the dispatcher methods to make sure a message
>
gets sent to your tableview. Then you could walk the instance method list
>
and find the "real" implementation to pass the call to (obviously caching it
>
after the first lookup). This reminds me of that isa-swizzling light
>
flamewar of last week, so obviously buyer beware.
>
>
Idea Number 2: Here's my new idea, which I think is feasible if you don't
>
have too much to implement. Subclass the views that you're using as first
>
responders but want to pass their events to the table. Override the
>
appropriate NSResponder methods and call to [super]. There may be a
>
non-obvious-to-fillup reason why that wouldn't work. But at least at first
>
glance it appears to work without too much swizzling.
>
>
>
HTH
>
fillup
>
>
>
On 6/11/02 9:58 PM, "Dan Wood" <email@hidden> wrote:
>
>
> The subject line probably doesn't explain my question well
>
> enough. Essentially what I'd like to do is have a big
>
> NSTableView on a window that may or may not actually be first
>
> responder -- perhaps there are some buttons or text fields on
>
> the window. I'd like to be able to have keys that are
>
> interesting to the NSTableView -- e.g. up/down arrows, page up &
>
> page down -- essentially "forwarded" to the NSTableView, even if
>
> something else is actually first responder. That would make it
>
> much more intuitive for somebody to make use of the window, not
>
> having to "tab into" the table (especially useless since there
>
> is no highlighting shown when the table is first responder.
>
>
>
> Any suggestions to accomplish this somewhat gracefully?
>
>
>
>
>
> --
>
> Dan Wood
>
> Karelia Software, LLC
>
> email@hidden
>
> http://www.karelia.com/
>
> Watson for Mac OS X: http://www.karelia.com/watson/
>
> _______________________________________________
>
> cocoa-dev mailing list | email@hidden
>
> Help/Unsubscribe/Archives:
>
> http://www.lists.apple.com/mailman/listinfo/cocoa-dev
>
> Do not post admin requests to the list. They will be ignored.
>
_______________________________________________
>
cocoa-dev mailing list | email@hidden
>
Help/Unsubscribe/Archives:
>
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
>
Do not post admin requests to the list. They will be ignored.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.