Questions About Add-On Dev: Working My Way Through The NVDA Add-ons Development Guide


Bhavya shah
 

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my way
through the incredible add-ons development guide. My hope is to, in
the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up at
irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship. I
look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


 

Hi Bhavya,
The example you gave ultimately came from NVDA's own development guide, which became the basis for the add-on dev guide.
To answer the first set of questions:
First, regarding event handler method parameters: generally, there are two event handler method signatures:
# From the plugin class level:
def event_eventName(self, obj, nextHandler)
# At the NVDA object level:
def event_eventName(self)

Parameters:
* self: the instance of the class itself (plugin class or an NVDA object class).
* obj: NVDA object that fired the event in question.
* nextHandler: a callable that will handle the given event at the next level.

In NVDA, event handling goes through the following steps:
1. An object (UIA element, MSAA object, JAB object, etc.) fires an event, and accessibility API's notifies NVDA of this fact.
2. After the events are filtered (such as not responding to duplicate events), a chain of generators is called. This chain, called event executor, calls event handlers defined in global plugins, app modules, tree interceptors, and NVDA objects, in that order.
3. The event handler at the global plugin, app module, or tree interceptor level can "cut" the event execution chain by NOT calling nextHandler() function defined as the event handler parameter. To put it differently, calling nextHandler() (a generator) causes NVDA to move down the event execution chain.
Note that event handling and chaining is described in NVDA's event handler source code module (eventHandler.py).
As for add-on development practice, I'm about to announce something that might be of use for you.
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io> On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 5:49 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: [nvda-addons] Questions About Add-On Dev: Working My Way Through The NVDA Add-ons Development Guide

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying Mathematical and Computational Science and am currently working my way through the incredible add-ons development guide. My hope is to, in the near future, be able to meaningfully contribute code either to NVDA core or add-ons. Since I may have multiple questions coming up at irregular intervals, I thought it would be better to initiate a unified thread to house them all rather than spammily starting new ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does that mean practically?
* What does obj refer to (the variable does not seem to have been defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into Python, or is it coming from either tones or appModuleHandler? In case the latter, then why don't we need to do {module of origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship. I look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


Bhavya shah
 

Dear all,

With respect to "Example 1: am I on the right app where the focus is
located?" whose code is pasted below for convenient access:
import api
def sameApp(obj=None):
if obj is None:
obj = api.getNavigatorObject()
return api.getFocusObject().appModule == obj.appModule

* I take it that obj=None assigns the value None to the variable obj
as part of the function definition. Is it common to assign the value
of a parameter during the function definition itself? It seems
slightly odd to me at first glance.
* I don't follow why we check if obj is None right after it was
assigned that value by us, but I am probably missing something. What
is the purpose of that conditional?
* There is an explanatory sentence in this section: "Each NVDA object
includes appModule member which records on which app an object is
located." Where can I learn more about the NVDA object? Is it a
module, class, method, or something else? What methods and/or members
does an NVDA object have access to?

Thanks.

On 1/9/22, Bhavya shah <bhavya.shah125@gmail.com> wrote:
Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my way
through the incredible add-ons development guide. My hope is to, in
the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up at
irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship. I
look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/
--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


Bhavya shah
 

Dear Joseph,

Thank you so much for the detailed and informative response! Based on
my understanding of your explanation, if I were to go back to my
questions, I have understood the following:
* Could you please explain the parameters for a general event method?
Response: The two event method signatures you noted.
* Here, it looks like self refers to the current class - what does
that mean practically?
Response: Self is just an instance of the class we began to define. It
doesn't mean anything unusual, but is what we will keep using to
define methods for that class of things.
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
Response: obj refers to the NVDA object that fired the event in
question. But in the example's code, how did we identify when we
landed on an object inside Notepad in the first place?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?
Response: Your (Joseph's) explanation of event handling sheds a lot of
light on how nextHandler works especially in the bigger picture. Just
to confirm then, is nextHandler provided by Python or part of one of
the NVDA moduels we imported?

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
The example you gave ultimately came from NVDA's own development guide,
which became the basis for the add-on dev guide.
To answer the first set of questions:
First, regarding event handler method parameters: generally, there are two
event handler method signatures:
# From the plugin class level:
def event_eventName(self, obj, nextHandler)
# At the NVDA object level:
def event_eventName(self)

Parameters:
* self: the instance of the class itself (plugin class or an NVDA object
class).
* obj: NVDA object that fired the event in question.
* nextHandler: a callable that will handle the given event at the next
level.

In NVDA, event handling goes through the following steps:
1. An object (UIA element, MSAA object, JAB object, etc.) fires an event,
and accessibility API's notifies NVDA of this fact.
2. After the events are filtered (such as not responding to duplicate
events), a chain of generators is called. This chain, called event executor,
calls event handlers defined in global plugins, app modules, tree
interceptors, and NVDA objects, in that order.
3. The event handler at the global plugin, app module, or tree interceptor
level can "cut" the event execution chain by NOT calling nextHandler()
function defined as the event handler parameter. To put it differently,
calling nextHandler() (a generator) causes NVDA to move down the event
execution chain.
Note that event handling and chaining is described in NVDA's event handler
source code module (eventHandler.py).
As for add-on development practice, I'm about to announce something that
might be of use for you.
Cheers,
Joseph


-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 5:49 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: [nvda-addons] Questions About Add-On Dev: Working My Way Through
The NVDA Add-ons Development Guide

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying Mathematical and
Computational Science and am currently working my way through the incredible
add-ons development guide. My hope is to, in the near future, be able to
meaningfully contribute code either to NVDA core or add-ons. Since I may
have multiple questions coming up at irregular intervals, I thought it would
be better to initiate a unified thread to house them all rather than
spammily starting new ones for each query. My first set of questions is
under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does that mean
practically?
* What does obj refer to (the variable does not seem to have been defined
previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into Python,
or is it coming from either tones or appModuleHandler? In case the latter,
then why don't we need to do {module of origin}.nextHandler like we had to
do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship. I look
forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/










--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


 

Hi,
In regards to how we know that NVDA object came from Notepad app: this is because of the fact that event handler is defined for an app module, which becomes active as long as the given app is in use (focused). So when writing app modules, you can assume that the NVDA object that fired the event is NVDA's representation of a control from the app in question, which in this case, can be anything from Notepad.
Regarding where next handler come from: it is not defined in Python, but rather it is a convention used to identify the next event handler chain. Think of it as a tagged function pointer (hope I'm using the term correctly) - as far as Python is concerned, functions are internally seen as pointers to addresses, and you can name that "address" whatever you like.
To go a bit into computer science way of thinking about this (WARNING: will get really geeky here), computers don't care about how things are named as long as they can access whatever they are told to read from specific locations. To explain:
Computer memory is a collection of integers known as "memory addresses" (or "addresses" for short). Each address, in turn, consists of bits, with eight bits making a byte (at the hardware level, they are really boxes filled with transistors; you won't learn about how that is possible until you take computer engineering or electrical engineering courses). When a computer is powered on, memory is "empty" - they are not really set to zero's, but are random things but computers treat it as "empty". (or rather, not filled with recognizable things).
When a program loads and wants to do something with variables, the central processing unit (CPU) performs a complicated operation that ultimately results in reading something from a memory location. This involves:
1. The processor reads the instruction to read the value of a variable.
2. The processor first locates the location of the variable within the program's working memory set (the amount of memory the program/process is occupying at that moment).
3. Since the variable "points" to the memory location of whatever it points to, a special component of the processor, called memory management unit (MMU) looks up the actual memory address the variable points to.
4. Once the memory location is fetched, the processor returns whatever value the "variable" references (points to). This is why computer scientists and programmers sometimes call variables "pointers", as variables are really tagged memory locations as far as the operating system and the computer hardware is concerned.
Although different programming languages use different strategies internally, generally when folks talk about variable names, they are really talking about the memory location the variable points to. Therefore, when we talk about Python variables, it is better to say "the variable references this memory location that contains a specific thing" rather than "something is assigned to a variable". But that's at the advanced level - for convenience, when people teach introductory programming, instructors say "something is assigned to a variable".
Building on this, it is perfectly possible to "rename" a variable; after all, a variable is a tag for a memory location, so all you are doing is changing the "outside tag" without changing the memory location the tag points to (or references). This is the reason why we can name the event chaining function anything, but for convenience, we call this "nextHandler" - ultimately, what Python will look at is the address of the function tagged "nextHandler".
Hope this helps - I understand what I described above is quite a geeky explanation, but since you are studying computer science, I felt it is time to introduce you to the actual internals of computer science (math and computer science go hand in hand because computer science began as a branch of mathematics; although Alan Turing and John von Neumann popularized computer science in the 20th century, the foundations were laid centuries earlier).
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io> On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:44 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way Through The NVDA Add-ons Development Guide

Dear Joseph,

Thank you so much for the detailed and informative response! Based on my understanding of your explanation, if I were to go back to my questions, I have understood the following:
* Could you please explain the parameters for a general event method?
Response: The two event method signatures you noted.
* Here, it looks like self refers to the current class - what does that mean practically?
Response: Self is just an instance of the class we began to define. It doesn't mean anything unusual, but is what we will keep using to define methods for that class of things.
* What does obj refer to (the variable does not seem to have been defined previously and I am not sure if this is a keyword)?
Response: obj refers to the NVDA object that fired the event in question. But in the example's code, how did we identify when we landed on an object inside Notepad in the first place?
* Where are we getting the nextHandler method from? Is it built into Python, or is it coming from either tones or appModuleHandler? In case the latter, then why don't we need to do {module of origin}.nextHandler like we had to do tones.beep?
Response: Your (Joseph's) explanation of event handling sheds a lot of light on how nextHandler works especially in the bigger picture. Just to confirm then, is nextHandler provided by Python or part of one of the NVDA moduels we imported?

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
The example you gave ultimately came from NVDA's own development
guide, which became the basis for the add-on dev guide.
To answer the first set of questions:
First, regarding event handler method parameters: generally, there are
two event handler method signatures:
# From the plugin class level:
def event_eventName(self, obj, nextHandler) # At the NVDA object
level:
def event_eventName(self)

Parameters:
* self: the instance of the class itself (plugin class or an NVDA
object class).
* obj: NVDA object that fired the event in question.
* nextHandler: a callable that will handle the given event at the next
level.

In NVDA, event handling goes through the following steps:
1. An object (UIA element, MSAA object, JAB object, etc.) fires an
event, and accessibility API's notifies NVDA of this fact.
2. After the events are filtered (such as not responding to duplicate
events), a chain of generators is called. This chain, called event
executor, calls event handlers defined in global plugins, app modules,
tree interceptors, and NVDA objects, in that order.
3. The event handler at the global plugin, app module, or tree
interceptor level can "cut" the event execution chain by NOT calling
nextHandler() function defined as the event handler parameter. To put
it differently, calling nextHandler() (a generator) causes NVDA to
move down the event execution chain.
Note that event handling and chaining is described in NVDA's event
handler source code module (eventHandler.py).
As for add-on development practice, I'm about to announce something
that might be of use for you.
Cheers,
Joseph


-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 5:49 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my way
through the incredible add-ons development guide. My hope is to, in
the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up at
irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship. I
look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


 

Hi Bhavya,
Ah, these are really good questions - reminds me of a day (many years ago) when I learned about algorithms...
To answer the third question first: NVDA objects are housed inside NVDAObjects folder inside nVDA's source code folder (source/NvDAObjects). As far as runtime is concerned (when NVDA Runs), an NVDA object is an instance of NvDAObjects.NVDAObject abstract class. Because abstract classes only gives us a blueprint, we often deal with concrete NVDA objects such as API classes from IAccessible, UIA, and others.
As for the other two questions, they go hand in hand sometimes, but to explain:
Suppose you need to travel from home to campus. You know that you need to walk several blocks, and that takes this amount of minutes. Now suppose that you need to go somewhere on campus.
Questions:
* How long will that take?
* What are your assumptions as you walk from home to somewhere on campus?
The above scenario describes keyword arguments - functions can take in keyword parameters that effectively tells Python that it should use whatever thing that was passed into the parameter if nothing else comes in. For example, suppose that it takes five minutes to walk from home to campus. Then:
* Without keywords (positional parameters): def walkFromHomeToCampus(durationInMinutes)
* With keyword parameters: def walkFromHomeToCampus(durationInMinutes=5)
In the first case, you MUST tell the walk function how long it takes to walk from home to campus. With keyword parameters, when duration is not specified, you can assume that it takes five minutes to walk from home to campus.
A special situation arises when you must check something against None (NULL in some languages), which is a way of saying, "this variable points to nowhere or to a possibly invalid location". The function fragment:
def something(obj=None):
if obj is None:
# Do something when obj points to nowhere (None)

Without this, you may get the following traceback that ends with:
AttributeError: obj has no attribute "someAttribute"
So for example, suppose you want to look at obj.appModule. Without checking for None, when trying to access obj.appModule, you may get an attribute error exception if obj happens to point to nowhere (technically, it points to a None object when var = None).
Hope this helps.
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io> On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:24 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way Through The NVDA Add-ons Development Guide

Dear all,

With respect to "Example 1: am I on the right app where the focus is located?" whose code is pasted below for convenient access:
import api
def sameApp(obj=None):
if obj is None:
obj = api.getNavigatorObject()
return api.getFocusObject().appModule == obj.appModule

* I take it that obj=None assigns the value None to the variable obj as part of the function definition. Is it common to assign the value of a parameter during the function definition itself? It seems slightly odd to me at first glance.
* I don't follow why we check if obj is None right after it was assigned that value by us, but I am probably missing something. What is the purpose of that conditional?
* There is an explanatory sentence in this section: "Each NVDA object includes appModule member which records on which app an object is located." Where can I learn more about the NVDA object? Is it a module, class, method, or something else? What methods and/or members does an NVDA object have access to?

Thanks.

On 1/9/22, Bhavya shah <bhavya.shah125@gmail.com> wrote:
Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my way
through the incredible add-ons development guide. My hope is to, in
the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up at
irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship. I
look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/

--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


Bhavya shah
 

Dear Joseph,

Much appreciated again! The exposition about what variables really are
and do was quite illuminating. I am taking a systems class this
quarter, so will be dealing with pointers much more extensively there.
I think I have one final question on the Notepad example then.
* What did we do in the code to produce the beep only when we first
entered Notepad as opposed to all of the time we spent doing things
(and thus firing events) in Notepad? I suspect nextHandler is to
thank, but I thought nextHandler was only to allow for the *current*
event to continue to be handled and would not affect any subsequent
events.

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi,
In regards to how we know that NVDA object came from Notepad app: this is
because of the fact that event handler is defined for an app module, which
becomes active as long as the given app is in use (focused). So when writing
app modules, you can assume that the NVDA object that fired the event is
NVDA's representation of a control from the app in question, which in this
case, can be anything from Notepad.
Regarding where next handler come from: it is not defined in Python, but
rather it is a convention used to identify the next event handler chain.
Think of it as a tagged function pointer (hope I'm using the term correctly)
- as far as Python is concerned, functions are internally seen as pointers
to addresses, and you can name that "address" whatever you like.
To go a bit into computer science way of thinking about this (WARNING: will
get really geeky here), computers don't care about how things are named as
long as they can access whatever they are told to read from specific
locations. To explain:
Computer memory is a collection of integers known as "memory addresses" (or
"addresses" for short). Each address, in turn, consists of bits, with eight
bits making a byte (at the hardware level, they are really boxes filled with
transistors; you won't learn about how that is possible until you take
computer engineering or electrical engineering courses). When a computer is
powered on, memory is "empty" - they are not really set to zero's, but are
random things but computers treat it as "empty". (or rather, not filled with
recognizable things).
When a program loads and wants to do something with variables, the central
processing unit (CPU) performs a complicated operation that ultimately
results in reading something from a memory location. This involves:
1. The processor reads the instruction to read the value of a variable.
2. The processor first locates the location of the variable within the
program's working memory set (the amount of memory the program/process is
occupying at that moment).
3. Since the variable "points" to the memory location of whatever it points
to, a special component of the processor, called memory management unit
(MMU) looks up the actual memory address the variable points to.
4. Once the memory location is fetched, the processor returns whatever value
the "variable" references (points to). This is why computer scientists and
programmers sometimes call variables "pointers", as variables are really
tagged memory locations as far as the operating system and the computer
hardware is concerned.
Although different programming languages use different strategies
internally, generally when folks talk about variable names, they are really
talking about the memory location the variable points to. Therefore, when we
talk about Python variables, it is better to say "the variable references
this memory location that contains a specific thing" rather than "something
is assigned to a variable". But that's at the advanced level - for
convenience, when people teach introductory programming, instructors say
"something is assigned to a variable".
Building on this, it is perfectly possible to "rename" a variable; after
all, a variable is a tag for a memory location, so all you are doing is
changing the "outside tag" without changing the memory location the tag
points to (or references). This is the reason why we can name the event
chaining function anything, but for convenience, we call this "nextHandler"
- ultimately, what Python will look at is the address of the function tagged
"nextHandler".
Hope this helps - I understand what I described above is quite a geeky
explanation, but since you are studying computer science, I felt it is time
to introduce you to the actual internals of computer science (math and
computer science go hand in hand because computer science began as a branch
of mathematics; although Alan Turing and John von Neumann popularized
computer science in the 20th century, the foundations were laid centuries
earlier).
Cheers,
Joseph




-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:44 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear Joseph,

Thank you so much for the detailed and informative response! Based on my
understanding of your explanation, if I were to go back to my questions, I
have understood the following:
* Could you please explain the parameters for a general event method?
Response: The two event method signatures you noted.
* Here, it looks like self refers to the current class - what does that mean
practically?
Response: Self is just an instance of the class we began to define. It
doesn't mean anything unusual, but is what we will keep using to define
methods for that class of things.
* What does obj refer to (the variable does not seem to have been defined
previously and I am not sure if this is a keyword)?
Response: obj refers to the NVDA object that fired the event in question.
But in the example's code, how did we identify when we landed on an object
inside Notepad in the first place?
* Where are we getting the nextHandler method from? Is it built into Python,
or is it coming from either tones or appModuleHandler? In case the latter,
then why don't we need to do {module of origin}.nextHandler like we had to
do tones.beep?
Response: Your (Joseph's) explanation of event handling sheds a lot of light
on how nextHandler works especially in the bigger picture. Just to confirm
then, is nextHandler provided by Python or part of one of the NVDA moduels
we imported?

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
The example you gave ultimately came from NVDA's own development
guide, which became the basis for the add-on dev guide.
To answer the first set of questions:
First, regarding event handler method parameters: generally, there are
two event handler method signatures:
# From the plugin class level:
def event_eventName(self, obj, nextHandler) # At the NVDA object
level:
def event_eventName(self)

Parameters:
* self: the instance of the class itself (plugin class or an NVDA
object class).
* obj: NVDA object that fired the event in question.
* nextHandler: a callable that will handle the given event at the next
level.

In NVDA, event handling goes through the following steps:
1. An object (UIA element, MSAA object, JAB object, etc.) fires an
event, and accessibility API's notifies NVDA of this fact.
2. After the events are filtered (such as not responding to duplicate
events), a chain of generators is called. This chain, called event
executor, calls event handlers defined in global plugins, app modules,
tree interceptors, and NVDA objects, in that order.
3. The event handler at the global plugin, app module, or tree
interceptor level can "cut" the event execution chain by NOT calling
nextHandler() function defined as the event handler parameter. To put
it differently, calling nextHandler() (a generator) causes NVDA to
move down the event execution chain.
Note that event handling and chaining is described in NVDA's event
handler source code module (eventHandler.py).
As for add-on development practice, I'm about to announce something
that might be of use for you.
Cheers,
Joseph


-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 5:49 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my way
through the incredible add-ons development guide. My hope is to, in
the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up at
irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship. I
look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/










--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


Bhavya shah
 

Dear Joseph,

Perfect - nearly everything makes complete sense (and thanks for the
helpful analogy)! Just two remarks:
* I went into C drive>Program Files (x86)>NVDA and was unable to find
a folder called "Source" or "Source Code." Where might I find this
folder so as to then access the NVDA Objects folder?
* I don't fully understand what an API class from IAccessible looks
like at present. I think I have a high-level guess, and should revisit
this later when I am exploring the api module.

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
Ah, these are really good questions - reminds me of a day (many years ago)
when I learned about algorithms...
To answer the third question first: NVDA objects are housed inside
NVDAObjects folder inside nVDA's source code folder (source/NvDAObjects). As
far as runtime is concerned (when NVDA Runs), an NVDA object is an instance
of NvDAObjects.NVDAObject abstract class. Because abstract classes only
gives us a blueprint, we often deal with concrete NVDA objects such as API
classes from IAccessible, UIA, and others.
As for the other two questions, they go hand in hand sometimes, but to
explain:
Suppose you need to travel from home to campus. You know that you need to
walk several blocks, and that takes this amount of minutes. Now suppose that
you need to go somewhere on campus.
Questions:
* How long will that take?
* What are your assumptions as you walk from home to somewhere on campus?
The above scenario describes keyword arguments - functions can take in
keyword parameters that effectively tells Python that it should use whatever
thing that was passed into the parameter if nothing else comes in. For
example, suppose that it takes five minutes to walk from home to campus.
Then:
* Without keywords (positional parameters): def
walkFromHomeToCampus(durationInMinutes)
* With keyword parameters: def walkFromHomeToCampus(durationInMinutes=5)
In the first case, you MUST tell the walk function how long it takes to walk
from home to campus. With keyword parameters, when duration is not
specified, you can assume that it takes five minutes to walk from home to
campus.
A special situation arises when you must check something against None (NULL
in some languages), which is a way of saying, "this variable points to
nowhere or to a possibly invalid location". The function fragment:
def something(obj=None):
if obj is None:
# Do something when obj points to nowhere (None)

Without this, you may get the following traceback that ends with:
AttributeError: obj has no attribute "someAttribute"
So for example, suppose you want to look at obj.appModule. Without checking
for None, when trying to access obj.appModule, you may get an attribute
error exception if obj happens to point to nowhere (technically, it points
to a None object when var = None).
Hope this helps.
Cheers,
Joseph





-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:24 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear all,

With respect to "Example 1: am I on the right app where the focus is
located?" whose code is pasted below for convenient access:
import api
def sameApp(obj=None):
if obj is None:
obj = api.getNavigatorObject()
return api.getFocusObject().appModule == obj.appModule

* I take it that obj=None assigns the value None to the variable obj as part
of the function definition. Is it common to assign the value of a parameter
during the function definition itself? It seems slightly odd to me at first
glance.
* I don't follow why we check if obj is None right after it was assigned
that value by us, but I am probably missing something. What is the purpose
of that conditional?
* There is an explanatory sentence in this section: "Each NVDA object
includes appModule member which records on which app an object is located."
Where can I learn more about the NVDA object? Is it a module, class, method,
or something else? What methods and/or members does an NVDA object have
access to?

Thanks.

On 1/9/22, Bhavya shah <bhavya.shah125@gmail.com> wrote:
Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my way
through the incredible add-ons development guide. My hope is to, in
the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up at
irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship. I
look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/

--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/










--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


 

Hi,
This depends on which event we wish to listen to (after all, GUI programs rely on what's called an "event loop" to respond to things happening on screen). Gain focus event is fired whenever system focus moves to a new object on screen. This is prominent in Notepad when we switch to it from other programs. Looking at which events are fired by which objects will require observing and debugging accessible events, and one such tool is AccEvent from Windows SDK (and it is one of the reasons for writing Event Tracker add-on so this process can be done easily).
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io> On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 10:06 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way Through The NVDA Add-ons Development Guide

Dear Joseph,

Much appreciated again! The exposition about what variables really are and do was quite illuminating. I am taking a systems class this quarter, so will be dealing with pointers much more extensively there.
I think I have one final question on the Notepad example then.
* What did we do in the code to produce the beep only when we first entered Notepad as opposed to all of the time we spent doing things (and thus firing events) in Notepad? I suspect nextHandler is to thank, but I thought nextHandler was only to allow for the *current* event to continue to be handled and would not affect any subsequent events.

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi,
In regards to how we know that NVDA object came from Notepad app: this
is because of the fact that event handler is defined for an app
module, which becomes active as long as the given app is in use
(focused). So when writing app modules, you can assume that the NVDA
object that fired the event is NVDA's representation of a control from
the app in question, which in this case, can be anything from Notepad.
Regarding where next handler come from: it is not defined in Python,
but rather it is a convention used to identify the next event handler chain.
Think of it as a tagged function pointer (hope I'm using the term
correctly)
- as far as Python is concerned, functions are internally seen as
pointers to addresses, and you can name that "address" whatever you like.
To go a bit into computer science way of thinking about this (WARNING:
will get really geeky here), computers don't care about how things are
named as long as they can access whatever they are told to read from
specific locations. To explain:
Computer memory is a collection of integers known as "memory
addresses" (or "addresses" for short). Each address, in turn, consists
of bits, with eight bits making a byte (at the hardware level, they
are really boxes filled with transistors; you won't learn about how
that is possible until you take computer engineering or electrical
engineering courses). When a computer is powered on, memory is "empty"
- they are not really set to zero's, but are random things but
computers treat it as "empty". (or rather, not filled with recognizable things).
When a program loads and wants to do something with variables, the
central processing unit (CPU) performs a complicated operation that
ultimately results in reading something from a memory location. This involves:
1. The processor reads the instruction to read the value of a variable.
2. The processor first locates the location of the variable within the
program's working memory set (the amount of memory the program/process
is occupying at that moment).
3. Since the variable "points" to the memory location of whatever it
points to, a special component of the processor, called memory
management unit
(MMU) looks up the actual memory address the variable points to.
4. Once the memory location is fetched, the processor returns whatever
value the "variable" references (points to). This is why computer
scientists and programmers sometimes call variables "pointers", as
variables are really tagged memory locations as far as the operating
system and the computer hardware is concerned.
Although different programming languages use different strategies
internally, generally when folks talk about variable names, they are
really talking about the memory location the variable points to.
Therefore, when we talk about Python variables, it is better to say
"the variable references this memory location that contains a specific
thing" rather than "something is assigned to a variable". But that's
at the advanced level - for convenience, when people teach
introductory programming, instructors say "something is assigned to a variable".
Building on this, it is perfectly possible to "rename" a variable;
after all, a variable is a tag for a memory location, so all you are
doing is changing the "outside tag" without changing the memory
location the tag points to (or references). This is the reason why we
can name the event chaining function anything, but for convenience, we call this "nextHandler"
- ultimately, what Python will look at is the address of the function
tagged "nextHandler".
Hope this helps - I understand what I described above is quite a geeky
explanation, but since you are studying computer science, I felt it is
time to introduce you to the actual internals of computer science
(math and computer science go hand in hand because computer science
began as a branch of mathematics; although Alan Turing and John von
Neumann popularized computer science in the 20th century, the
foundations were laid centuries earlier).
Cheers,
Joseph




-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:44 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear Joseph,

Thank you so much for the detailed and informative response! Based on
my understanding of your explanation, if I were to go back to my
questions, I have understood the following:
* Could you please explain the parameters for a general event method?
Response: The two event method signatures you noted.
* Here, it looks like self refers to the current class - what does
that mean practically?
Response: Self is just an instance of the class we began to define. It
doesn't mean anything unusual, but is what we will keep using to
define methods for that class of things.
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
Response: obj refers to the NVDA object that fired the event in question.
But in the example's code, how did we identify when we landed on an
object inside Notepad in the first place?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?
Response: Your (Joseph's) explanation of event handling sheds a lot of
light on how nextHandler works especially in the bigger picture. Just
to confirm then, is nextHandler provided by Python or part of one of
the NVDA moduels we imported?

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
The example you gave ultimately came from NVDA's own development
guide, which became the basis for the add-on dev guide.
To answer the first set of questions:
First, regarding event handler method parameters: generally, there
are two event handler method signatures:
# From the plugin class level:
def event_eventName(self, obj, nextHandler) # At the NVDA object
level:
def event_eventName(self)

Parameters:
* self: the instance of the class itself (plugin class or an NVDA
object class).
* obj: NVDA object that fired the event in question.
* nextHandler: a callable that will handle the given event at the
next level.

In NVDA, event handling goes through the following steps:
1. An object (UIA element, MSAA object, JAB object, etc.) fires an
event, and accessibility API's notifies NVDA of this fact.
2. After the events are filtered (such as not responding to duplicate
events), a chain of generators is called. This chain, called event
executor, calls event handlers defined in global plugins, app
modules, tree interceptors, and NVDA objects, in that order.
3. The event handler at the global plugin, app module, or tree
interceptor level can "cut" the event execution chain by NOT calling
nextHandler() function defined as the event handler parameter. To put
it differently, calling nextHandler() (a generator) causes NVDA to
move down the event execution chain.
Note that event handling and chaining is described in NVDA's event
handler source code module (eventHandler.py).
As for add-on development practice, I'm about to announce something
that might be of use for you.
Cheers,
Joseph


-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 5:49 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my
way through the incredible add-ons development guide. My hope is to,
in the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up
at irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In
case the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship.
I look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


 

Hi,
To view NvDA objects folder in source code, you must clone NVDA source code (believe it or not). To do, you must install Git (Git for Windows, part of Windows Subsystem for Linux (WSL), etc.), then Git clone the following URL:
https://github.com/nvaccess/nvda

For best results, try cloning recursively. If using command line, do:
1. cd sourceFolderLocationWhereYouWantToStoreNVDASource
2. git clone --recursive https://github.com/nvaccess/nvda
You can then build NVDA itself from source code (a requirement if you wish to send NVDA pull requests in the future). Sometimes it is helpful to have the NVDA source code handy if you want to learn the magic behind NVDA add-ons (although NVDA source code is not exactly a good case of software documentation, at least it is readable when trying to understand basics; to grasp the full power of NVDA, you must be familiar with both Python and C++; my point about documentation is the biggest reason for writing add-on dev guide, and the number one wish remains the same for the last five years or so: better source code documentation).
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io> On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 10:14 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way Through The NVDA Add-ons Development Guide

Dear Joseph,

Perfect - nearly everything makes complete sense (and thanks for the helpful analogy)! Just two remarks:
* I went into C drive>Program Files (x86)>NVDA and was unable to find a folder called "Source" or "Source Code." Where might I find this folder so as to then access the NVDA Objects folder?
* I don't fully understand what an API class from IAccessible looks like at present. I think I have a high-level guess, and should revisit this later when I am exploring the api module.

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
Ah, these are really good questions - reminds me of a day (many years
ago) when I learned about algorithms...
To answer the third question first: NVDA objects are housed inside
NVDAObjects folder inside nVDA's source code folder
(source/NvDAObjects). As far as runtime is concerned (when NVDA Runs),
an NVDA object is an instance of NvDAObjects.NVDAObject abstract
class. Because abstract classes only gives us a blueprint, we often
deal with concrete NVDA objects such as API classes from IAccessible, UIA, and others.
As for the other two questions, they go hand in hand sometimes, but to
explain:
Suppose you need to travel from home to campus. You know that you need
to walk several blocks, and that takes this amount of minutes. Now
suppose that you need to go somewhere on campus.
Questions:
* How long will that take?
* What are your assumptions as you walk from home to somewhere on campus?
The above scenario describes keyword arguments - functions can take in
keyword parameters that effectively tells Python that it should use
whatever thing that was passed into the parameter if nothing else
comes in. For example, suppose that it takes five minutes to walk from home to campus.
Then:
* Without keywords (positional parameters): def
walkFromHomeToCampus(durationInMinutes)
* With keyword parameters: def
walkFromHomeToCampus(durationInMinutes=5)
In the first case, you MUST tell the walk function how long it takes
to walk from home to campus. With keyword parameters, when duration is
not specified, you can assume that it takes five minutes to walk from
home to campus.
A special situation arises when you must check something against None
(NULL in some languages), which is a way of saying, "this variable
points to nowhere or to a possibly invalid location". The function fragment:
def something(obj=None):
if obj is None:
# Do something when obj points to nowhere (None)

Without this, you may get the following traceback that ends with:
AttributeError: obj has no attribute "someAttribute"
So for example, suppose you want to look at obj.appModule. Without
checking for None, when trying to access obj.appModule, you may get an
attribute error exception if obj happens to point to nowhere
(technically, it points to a None object when var = None).
Hope this helps.
Cheers,
Joseph





-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:24 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear all,

With respect to "Example 1: am I on the right app where the focus is
located?" whose code is pasted below for convenient access:
import api
def sameApp(obj=None):
if obj is None:
obj = api.getNavigatorObject()
return api.getFocusObject().appModule == obj.appModule

* I take it that obj=None assigns the value None to the variable obj
as part of the function definition. Is it common to assign the value
of a parameter during the function definition itself? It seems
slightly odd to me at first glance.
* I don't follow why we check if obj is None right after it was
assigned that value by us, but I am probably missing something. What
is the purpose of that conditional?
* There is an explanatory sentence in this section: "Each NVDA object
includes appModule member which records on which app an object is located."
Where can I learn more about the NVDA object? Is it a module, class,
method, or something else? What methods and/or members does an NVDA
object have access to?

Thanks.

On 1/9/22, Bhavya shah <bhavya.shah125@gmail.com> wrote:
Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my
way through the incredible add-ons development guide. My hope is to,
in the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up
at irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In
case the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship.
I look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/

--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


Bhavya shah
 

Dear Joseph,

I just installed your Event Tracker add-on and look forward to using
it as we go. In this case, you noted the gain focus event. My earlier
understanding was that event_gainFocus was just a random name for a
function wherein "event_" told Python that this method was an event
method and "gainFocus" was only to make it clear for humans. I tested
this hypothesis by modifying event_gainFocus to event_testing and the
app module stopped working which tells me that the "gainFocus" bit is
also significant for Python. I used to think function names only acted
as placeholders but clearly that is not the case. I learnt something
new.

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi,
This depends on which event we wish to listen to (after all, GUI programs
rely on what's called an "event loop" to respond to things happening on
screen). Gain focus event is fired whenever system focus moves to a new
object on screen. This is prominent in Notepad when we switch to it from
other programs. Looking at which events are fired by which objects will
require observing and debugging accessible events, and one such tool is
AccEvent from Windows SDK (and it is one of the reasons for writing Event
Tracker add-on so this process can be done easily).
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 10:06 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear Joseph,

Much appreciated again! The exposition about what variables really are and
do was quite illuminating. I am taking a systems class this quarter, so will
be dealing with pointers much more extensively there.
I think I have one final question on the Notepad example then.
* What did we do in the code to produce the beep only when we first entered
Notepad as opposed to all of the time we spent doing things (and thus firing
events) in Notepad? I suspect nextHandler is to thank, but I thought
nextHandler was only to allow for the *current* event to continue to be
handled and would not affect any subsequent events.

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi,
In regards to how we know that NVDA object came from Notepad app: this
is because of the fact that event handler is defined for an app
module, which becomes active as long as the given app is in use
(focused). So when writing app modules, you can assume that the NVDA
object that fired the event is NVDA's representation of a control from
the app in question, which in this case, can be anything from Notepad.
Regarding where next handler come from: it is not defined in Python,
but rather it is a convention used to identify the next event handler
chain.
Think of it as a tagged function pointer (hope I'm using the term
correctly)
- as far as Python is concerned, functions are internally seen as
pointers to addresses, and you can name that "address" whatever you like.
To go a bit into computer science way of thinking about this (WARNING:
will get really geeky here), computers don't care about how things are
named as long as they can access whatever they are told to read from
specific locations. To explain:
Computer memory is a collection of integers known as "memory
addresses" (or "addresses" for short). Each address, in turn, consists
of bits, with eight bits making a byte (at the hardware level, they
are really boxes filled with transistors; you won't learn about how
that is possible until you take computer engineering or electrical
engineering courses). When a computer is powered on, memory is "empty"
- they are not really set to zero's, but are random things but
computers treat it as "empty". (or rather, not filled with recognizable
things).
When a program loads and wants to do something with variables, the
central processing unit (CPU) performs a complicated operation that
ultimately results in reading something from a memory location. This
involves:
1. The processor reads the instruction to read the value of a variable.
2. The processor first locates the location of the variable within the
program's working memory set (the amount of memory the program/process
is occupying at that moment).
3. Since the variable "points" to the memory location of whatever it
points to, a special component of the processor, called memory
management unit
(MMU) looks up the actual memory address the variable points to.
4. Once the memory location is fetched, the processor returns whatever
value the "variable" references (points to). This is why computer
scientists and programmers sometimes call variables "pointers", as
variables are really tagged memory locations as far as the operating
system and the computer hardware is concerned.
Although different programming languages use different strategies
internally, generally when folks talk about variable names, they are
really talking about the memory location the variable points to.
Therefore, when we talk about Python variables, it is better to say
"the variable references this memory location that contains a specific
thing" rather than "something is assigned to a variable". But that's
at the advanced level - for convenience, when people teach
introductory programming, instructors say "something is assigned to a
variable".
Building on this, it is perfectly possible to "rename" a variable;
after all, a variable is a tag for a memory location, so all you are
doing is changing the "outside tag" without changing the memory
location the tag points to (or references). This is the reason why we
can name the event chaining function anything, but for convenience, we
call this "nextHandler"
- ultimately, what Python will look at is the address of the function
tagged "nextHandler".
Hope this helps - I understand what I described above is quite a geeky
explanation, but since you are studying computer science, I felt it is
time to introduce you to the actual internals of computer science
(math and computer science go hand in hand because computer science
began as a branch of mathematics; although Alan Turing and John von
Neumann popularized computer science in the 20th century, the
foundations were laid centuries earlier).
Cheers,
Joseph




-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:44 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear Joseph,

Thank you so much for the detailed and informative response! Based on
my understanding of your explanation, if I were to go back to my
questions, I have understood the following:
* Could you please explain the parameters for a general event method?
Response: The two event method signatures you noted.
* Here, it looks like self refers to the current class - what does
that mean practically?
Response: Self is just an instance of the class we began to define. It
doesn't mean anything unusual, but is what we will keep using to
define methods for that class of things.
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
Response: obj refers to the NVDA object that fired the event in question.
But in the example's code, how did we identify when we landed on an
object inside Notepad in the first place?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?
Response: Your (Joseph's) explanation of event handling sheds a lot of
light on how nextHandler works especially in the bigger picture. Just
to confirm then, is nextHandler provided by Python or part of one of
the NVDA moduels we imported?

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
The example you gave ultimately came from NVDA's own development
guide, which became the basis for the add-on dev guide.
To answer the first set of questions:
First, regarding event handler method parameters: generally, there
are two event handler method signatures:
# From the plugin class level:
def event_eventName(self, obj, nextHandler) # At the NVDA object
level:
def event_eventName(self)

Parameters:
* self: the instance of the class itself (plugin class or an NVDA
object class).
* obj: NVDA object that fired the event in question.
* nextHandler: a callable that will handle the given event at the
next level.

In NVDA, event handling goes through the following steps:
1. An object (UIA element, MSAA object, JAB object, etc.) fires an
event, and accessibility API's notifies NVDA of this fact.
2. After the events are filtered (such as not responding to duplicate
events), a chain of generators is called. This chain, called event
executor, calls event handlers defined in global plugins, app
modules, tree interceptors, and NVDA objects, in that order.
3. The event handler at the global plugin, app module, or tree
interceptor level can "cut" the event execution chain by NOT calling
nextHandler() function defined as the event handler parameter. To put
it differently, calling nextHandler() (a generator) causes NVDA to
move down the event execution chain.
Note that event handling and chaining is described in NVDA's event
handler source code module (eventHandler.py).
As for add-on development practice, I'm about to announce something
that might be of use for you.
Cheers,
Joseph


-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 5:49 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my
way through the incredible add-ons development guide. My hope is to,
in the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up
at irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In
case the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship.
I look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/










--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/


James Scholes
 

Hi Bhavya,

I have no problem with these types of questions being asked on the list, and I'm greatful to anyone who is able to provide helpful answers. I particularly think it was a good idea to create a thread for them, and ask people to not highjack it (e.g. by changing the subject line to talk about a different topic).

Having said that, a number of your questions so far have not been related specifically to NVDA, although you weren't to know that when you asked them. Default function/method arguments, instance variables when using classes, passing functions/methods around as arguments, and the difference between function/method arguments and variable assignments. These are all general software development topics and, in many cases, would be better understood from a course and/or book about a programming language you're interested in learning.

In this case, it seems to be Python. I don't believe the NVDA codebase to represent a particularly good resource for beginners, because of some of the more advanced techniques that it uses. Positive reinforcement is important, i.e. having some successes to validate your learning, and I speak from experience when I say that developing against NVDA can, at first and still at times, feel like bashing your head into a wall.

Hope you take this in the spirit it is intended. Please do continue to ask, but it would be helpful:

1. for others, to sometimes answer in more abstract /non-NVDA-related ways, perhaps with links to good resources on a software development topic; and
2. for you, to find a good resource from which to learn object-oriented Python.

In short, learn software development and Python, and use them to apply to NVDA, not the other way around. For the record, I originally learned Python from this book: https://learncodethehardway.org/python/

Regards,

James Scholes

On 10/01/2022 at 9:09 am, Bhavya shah wrote:
Dear Joseph,

I just installed your Event Tracker add-on and look forward to using
it as we go. In this case, you noted the gain focus event. My earlier
understanding was that event_gainFocus was just a random name for a
function wherein "event_" told Python that this method was an event
method and "gainFocus" was only to make it clear for humans. I tested
this hypothesis by modifying event_gainFocus to event_testing and the
app module stopped working which tells me that the "gainFocus" bit is
also significant for Python. I used to think function names only acted
as placeholders but clearly that is not the case. I learnt something
new.

Thanks.


On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi,
This depends on which event we wish to listen to (after all, GUI programs
rely on what's called an "event loop" to respond to things happening on
screen). Gain focus event is fired whenever system focus moves to a new
object on screen. This is prominent in Notepad when we switch to it from
other programs. Looking at which events are fired by which objects will
require observing and debugging accessible events, and one such tool is
AccEvent from Windows SDK (and it is one of the reasons for writing Event
Tracker add-on so this process can be done easily).
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 10:06 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear Joseph,

Much appreciated again! The exposition about what variables really are and
do was quite illuminating. I am taking a systems class this quarter, so will
be dealing with pointers much more extensively there.
I think I have one final question on the Notepad example then.
* What did we do in the code to produce the beep only when we first entered
Notepad as opposed to all of the time we spent doing things (and thus firing
events) in Notepad? I suspect nextHandler is to thank, but I thought
nextHandler was only to allow for the *current* event to continue to be
handled and would not affect any subsequent events.

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi,
In regards to how we know that NVDA object came from Notepad app: this
is because of the fact that event handler is defined for an app
module, which becomes active as long as the given app is in use
(focused). So when writing app modules, you can assume that the NVDA
object that fired the event is NVDA's representation of a control from
the app in question, which in this case, can be anything from Notepad.
Regarding where next handler come from: it is not defined in Python,
but rather it is a convention used to identify the next event handler
chain.
Think of it as a tagged function pointer (hope I'm using the term
correctly)
- as far as Python is concerned, functions are internally seen as
pointers to addresses, and you can name that "address" whatever you like.
To go a bit into computer science way of thinking about this (WARNING:
will get really geeky here), computers don't care about how things are
named as long as they can access whatever they are told to read from
specific locations. To explain:
Computer memory is a collection of integers known as "memory
addresses" (or "addresses" for short). Each address, in turn, consists
of bits, with eight bits making a byte (at the hardware level, they
are really boxes filled with transistors; you won't learn about how
that is possible until you take computer engineering or electrical
engineering courses). When a computer is powered on, memory is "empty"
- they are not really set to zero's, but are random things but
computers treat it as "empty". (or rather, not filled with recognizable
things).
When a program loads and wants to do something with variables, the
central processing unit (CPU) performs a complicated operation that
ultimately results in reading something from a memory location. This
involves:
1. The processor reads the instruction to read the value of a variable.
2. The processor first locates the location of the variable within the
program's working memory set (the amount of memory the program/process
is occupying at that moment).
3. Since the variable "points" to the memory location of whatever it
points to, a special component of the processor, called memory
management unit
(MMU) looks up the actual memory address the variable points to.
4. Once the memory location is fetched, the processor returns whatever
value the "variable" references (points to). This is why computer
scientists and programmers sometimes call variables "pointers", as
variables are really tagged memory locations as far as the operating
system and the computer hardware is concerned.
Although different programming languages use different strategies
internally, generally when folks talk about variable names, they are
really talking about the memory location the variable points to.
Therefore, when we talk about Python variables, it is better to say
"the variable references this memory location that contains a specific
thing" rather than "something is assigned to a variable". But that's
at the advanced level - for convenience, when people teach
introductory programming, instructors say "something is assigned to a
variable".
Building on this, it is perfectly possible to "rename" a variable;
after all, a variable is a tag for a memory location, so all you are
doing is changing the "outside tag" without changing the memory
location the tag points to (or references). This is the reason why we
can name the event chaining function anything, but for convenience, we
call this "nextHandler"
- ultimately, what Python will look at is the address of the function
tagged "nextHandler".
Hope this helps - I understand what I described above is quite a geeky
explanation, but since you are studying computer science, I felt it is
time to introduce you to the actual internals of computer science
(math and computer science go hand in hand because computer science
began as a branch of mathematics; although Alan Turing and John von
Neumann popularized computer science in the 20th century, the
foundations were laid centuries earlier).
Cheers,
Joseph




-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:44 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear Joseph,

Thank you so much for the detailed and informative response! Based on
my understanding of your explanation, if I were to go back to my
questions, I have understood the following:
* Could you please explain the parameters for a general event method?
Response: The two event method signatures you noted.
* Here, it looks like self refers to the current class - what does
that mean practically?
Response: Self is just an instance of the class we began to define. It
doesn't mean anything unusual, but is what we will keep using to
define methods for that class of things.
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
Response: obj refers to the NVDA object that fired the event in question.
But in the example's code, how did we identify when we landed on an
object inside Notepad in the first place?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In case
the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?
Response: Your (Joseph's) explanation of event handling sheds a lot of
light on how nextHandler works especially in the bigger picture. Just
to confirm then, is nextHandler provided by Python or part of one of
the NVDA moduels we imported?

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
The example you gave ultimately came from NVDA's own development
guide, which became the basis for the add-on dev guide.
To answer the first set of questions:
First, regarding event handler method parameters: generally, there
are two event handler method signatures:
# From the plugin class level:
def event_eventName(self, obj, nextHandler) # At the NVDA object
level:
def event_eventName(self)

Parameters:
* self: the instance of the class itself (plugin class or an NVDA
object class).
* obj: NVDA object that fired the event in question.
* nextHandler: a callable that will handle the given event at the
next level.

In NVDA, event handling goes through the following steps:
1. An object (UIA element, MSAA object, JAB object, etc.) fires an
event, and accessibility API's notifies NVDA of this fact.
2. After the events are filtered (such as not responding to duplicate
events), a chain of generators is called. This chain, called event
executor, calls event handlers defined in global plugins, app
modules, tree interceptors, and NVDA objects, in that order.
3. The event handler at the global plugin, app module, or tree
interceptor level can "cut" the event execution chain by NOT calling
nextHandler() function defined as the event handler parameter. To put
it differently, calling nextHandler() (a generator) causes NVDA to
move down the event execution chain.
Note that event handling and chaining is described in NVDA's event
handler source code module (eventHandler.py).
As for add-on development practice, I'm about to announce something
that might be of use for you.
Cheers,
Joseph


-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 5:49 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my
way through the incredible add-ons development guide. My hope is to,
in the near future, be able to meaningfully contribute code either to
NVDA core or add-ons. Since I may have multiple questions coming up
at irregular intervals, I thought it would be better to initiate a
unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In
case the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship.
I look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











 

Hi,
Like anything in programming internals, function names are really tags to memory locations where the function code begins.
As for gain focus event, that name comes from:
1. Abstract event names: NVDA's own NVDAObject abstract class comes with base definitions for events, including, believe it or not, event_gainFocus.
2. Accessibility API event map: each accessibility API (IAccessible, UIA, and others) include an events to NVDA events map where API specific events are mapped to NVDA events. For example, in UIA, tooltip open event is internally mapped to UIA_tooltipOpen event in NVDA.
3. Event names: after determining what event it is, NVDA's event handler (as part of event executor chain) will create an idealized method name such as event_gainFocus.

As James pointed out in another message and as I've been saying to new add-on authors for years, it is really helpful to work on something else before coming back to NVDA. This is so that you can get a general overview of concepts such as object-oriented programming, data structures and algorithms, and related things and use NVDA as an application of these concepts. To illustrate the knowledge you need to provide really effective NVDA pull requests, you must be able to describe in your own words the following:
* Inheritance
* Abstract classes
* Testing and debugging
* Version control system

Or, to summarize, you should have experience with object-oriented programming (OOP). I understand that it is really tempting to learn OOP using a tool we are most familiar with (a screen reader with available source code). I advise against this - or rather, I strongly encourage people to gain experience with something else BEFORE applying what they have learned through NVDA. This is another reason why I also advise against jumping to submitting NVDA pull requests write away if you are new to computer science or programming (as James also notes, NVDA source code is not really an easy source code to understand; even after ten years, I still don't understand browse mode internals fully); writing add-ons after doing something else is a gentler way to get into screen reader internals, in my opinion.
Hope this helps.
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io <nvda-addons@nvda-addons.groups.io> On Behalf Of Bhavya shah
Sent: Monday, January 10, 2022 7:10 AM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way Through The NVDA Add-ons Development Guide

Dear Joseph,

I just installed your Event Tracker add-on and look forward to using it as we go. In this case, you noted the gain focus event. My earlier understanding was that event_gainFocus was just a random name for a function wherein "event_" told Python that this method was an event method and "gainFocus" was only to make it clear for humans. I tested this hypothesis by modifying event_gainFocus to event_testing and the app module stopped working which tells me that the "gainFocus" bit is also significant for Python. I used to think function names only acted as placeholders but clearly that is not the case. I learnt something new.

Thanks.


On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi,
This depends on which event we wish to listen to (after all, GUI
programs rely on what's called an "event loop" to respond to things
happening on screen). Gain focus event is fired whenever system focus
moves to a new object on screen. This is prominent in Notepad when we
switch to it from other programs. Looking at which events are fired by
which objects will require observing and debugging accessible events,
and one such tool is AccEvent from Windows SDK (and it is one of the
reasons for writing Event Tracker add-on so this process can be done easily).
Cheers,
Joseph

-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 10:06 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear Joseph,

Much appreciated again! The exposition about what variables really are
and do was quite illuminating. I am taking a systems class this
quarter, so will be dealing with pointers much more extensively there.
I think I have one final question on the Notepad example then.
* What did we do in the code to produce the beep only when we first
entered Notepad as opposed to all of the time we spent doing things
(and thus firing
events) in Notepad? I suspect nextHandler is to thank, but I thought
nextHandler was only to allow for the *current* event to continue to
be handled and would not affect any subsequent events.

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi,
In regards to how we know that NVDA object came from Notepad app:
this is because of the fact that event handler is defined for an app
module, which becomes active as long as the given app is in use
(focused). So when writing app modules, you can assume that the NVDA
object that fired the event is NVDA's representation of a control
from the app in question, which in this case, can be anything from Notepad.
Regarding where next handler come from: it is not defined in Python,
but rather it is a convention used to identify the next event handler
chain.
Think of it as a tagged function pointer (hope I'm using the term
correctly)
- as far as Python is concerned, functions are internally seen as
pointers to addresses, and you can name that "address" whatever you like.
To go a bit into computer science way of thinking about this (WARNING:
will get really geeky here), computers don't care about how things
are named as long as they can access whatever they are told to read
from specific locations. To explain:
Computer memory is a collection of integers known as "memory
addresses" (or "addresses" for short). Each address, in turn,
consists of bits, with eight bits making a byte (at the hardware
level, they are really boxes filled with transistors; you won't learn
about how that is possible until you take computer engineering or
electrical engineering courses). When a computer is powered on, memory is "empty"
- they are not really set to zero's, but are random things but
computers treat it as "empty". (or rather, not filled with
recognizable things).
When a program loads and wants to do something with variables, the
central processing unit (CPU) performs a complicated operation that
ultimately results in reading something from a memory location. This
involves:
1. The processor reads the instruction to read the value of a variable.
2. The processor first locates the location of the variable within
the program's working memory set (the amount of memory the
program/process is occupying at that moment).
3. Since the variable "points" to the memory location of whatever it
points to, a special component of the processor, called memory
management unit
(MMU) looks up the actual memory address the variable points to.
4. Once the memory location is fetched, the processor returns
whatever value the "variable" references (points to). This is why
computer scientists and programmers sometimes call variables
"pointers", as variables are really tagged memory locations as far as
the operating system and the computer hardware is concerned.
Although different programming languages use different strategies
internally, generally when folks talk about variable names, they are
really talking about the memory location the variable points to.
Therefore, when we talk about Python variables, it is better to say
"the variable references this memory location that contains a
specific thing" rather than "something is assigned to a variable".
But that's at the advanced level - for convenience, when people teach
introductory programming, instructors say "something is assigned to a
variable".
Building on this, it is perfectly possible to "rename" a variable;
after all, a variable is a tag for a memory location, so all you are
doing is changing the "outside tag" without changing the memory
location the tag points to (or references). This is the reason why we
can name the event chaining function anything, but for convenience,
we call this "nextHandler"
- ultimately, what Python will look at is the address of the function
tagged "nextHandler".
Hope this helps - I understand what I described above is quite a
geeky explanation, but since you are studying computer science, I
felt it is time to introduce you to the actual internals of computer
science (math and computer science go hand in hand because computer
science began as a branch of mathematics; although Alan Turing and
John von Neumann popularized computer science in the 20th century,
the foundations were laid centuries earlier).
Cheers,
Joseph




-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 6:44 PM
To: nvda-addons@nvda-addons.groups.io
Subject: Re: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear Joseph,

Thank you so much for the detailed and informative response! Based on
my understanding of your explanation, if I were to go back to my
questions, I have understood the following:
* Could you please explain the parameters for a general event method?
Response: The two event method signatures you noted.
* Here, it looks like self refers to the current class - what does
that mean practically?
Response: Self is just an instance of the class we began to define.
It doesn't mean anything unusual, but is what we will keep using to
define methods for that class of things.
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
Response: obj refers to the NVDA object that fired the event in question.
But in the example's code, how did we identify when we landed on an
object inside Notepad in the first place?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In
case the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?
Response: Your (Joseph's) explanation of event handling sheds a lot
of light on how nextHandler works especially in the bigger picture.
Just to confirm then, is nextHandler provided by Python or part of
one of the NVDA moduels we imported?

Thanks.

On 1/9/22, Joseph Lee <joseph.lee22590@gmail.com> wrote:
Hi Bhavya,
The example you gave ultimately came from NVDA's own development
guide, which became the basis for the add-on dev guide.
To answer the first set of questions:
First, regarding event handler method parameters: generally, there
are two event handler method signatures:
# From the plugin class level:
def event_eventName(self, obj, nextHandler) # At the NVDA object
level:
def event_eventName(self)

Parameters:
* self: the instance of the class itself (plugin class or an NVDA
object class).
* obj: NVDA object that fired the event in question.
* nextHandler: a callable that will handle the given event at the
next level.

In NVDA, event handling goes through the following steps:
1. An object (UIA element, MSAA object, JAB object, etc.) fires an
event, and accessibility API's notifies NVDA of this fact.
2. After the events are filtered (such as not responding to
duplicate events), a chain of generators is called. This chain,
called event executor, calls event handlers defined in global
plugins, app modules, tree interceptors, and NVDA objects, in that order.
3. The event handler at the global plugin, app module, or tree
interceptor level can "cut" the event execution chain by NOT calling
nextHandler() function defined as the event handler parameter. To
put it differently, calling nextHandler() (a generator) causes NVDA
to move down the event execution chain.
Note that event handling and chaining is described in NVDA's event
handler source code module (eventHandler.py).
As for add-on development practice, I'm about to announce something
that might be of use for you.
Cheers,
Joseph


-----Original Message-----
From: nvda-addons@nvda-addons.groups.io
<nvda-addons@nvda-addons.groups.io>
On Behalf Of Bhavya shah
Sent: Sunday, January 9, 2022 5:49 PM
To: nvda-addons <nvda-addons@nvda-addons.groups.io>
Subject: [nvda-addons] Questions About Add-On Dev: Working My Way
Through The NVDA Add-ons Development Guide

Dear all,

My name is Bhavya Shah, and I am an undergraduate studying
Mathematical and Computational Science and am currently working my
way through the incredible add-ons development guide. My hope is to,
in the near future, be able to meaningfully contribute code either
to NVDA core or add-ons. Since I may have multiple questions coming
up at irregular intervals, I thought it would be better to initiate
a unified thread to house them all rather than spammily starting new
ones for each query. My first set of questions is under.
With respect to "Example 2: Generate a tone when switching to Notepad"
whose code is pasted below for convenient access:
import appModuleHandler
import tones
class AppModule(appModuleHandler.AppModule):
def event_gainFocus(self, obj, nextHandler):
tones.beep(256, 200)
nextHandler()
* Could you please explain the parameters for a general event method?
* Here, it looks like self refers to the current class - what does
that mean practically?
* What does obj refer to (the variable does not seem to have been
defined previously and I am not sure if this is a keyword)?
* Where are we getting the nextHandler method from? Is it built into
Python, or is it coming from either tones or appModuleHandler? In
case the latter, then why don't we need to do {module of
origin}.nextHandler like we had to do tones.beep?

I would be deeply, deeply grateful for your guidance and mentorship.
I look forward to learning loads and contributing thereafter.

Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/











--
Best Regards,
Bhavya Shah
Stanford University | Class of 2024
LinkedIn: https://www.linkedin.com/in/bhavyashah125/