Expand/Shrink

Callbacks

Callbacks are used by the application to receive notifications from the system that the user or the system itself has interacted with the user interface of the application.

On the other hand attributes are used by the application to communicate with the user interface system.

Even though callbacks have different purposes from attributes, they are also associated to an element by means of an name.

The OLD method to associate a function to a callback, the application must employ the IupSetAttribute function, linking the action to a name (passed as a string).
From this point on, this name will refer to a callback. By means of function IupSetFunction (follow that link for an explanation of why the following call to it is syntax-coloured red), the user connects this name to the callback. For example:
function myButton_action(Ihandle self)
...
IupSetAttribute(myButton, "ACTION", "my_button_action");
IupSetFunction("my_button_action", Icallback("myButton_action")
In the NEW method, the application does not needs a global name, it directly sets the callback using the attribute name using IupSetCallback. For example:
function myButton_action(Ihandle self)
...
IupSetCallback(myButton, "ACTION", Icallback("myButton_action"))
The new method is more efficient and more secure, because there is no risk of a name conflict.
Generally you should replace IupSetFunction by IupSetCallback.

Although enabled in old versions, callbacks do NOT have inheritance like attributes.

All callbacks receive at least the element which activated the action as a parameter (self).

The callbacks implemented in the application must return one of the following values:
  • IUP_DEFAULT: Proceeds normally with user interaction. In case other return values do not apply, the callback should return this value.
  • IUP_CLOSE: Call IupExitLoop after return. Depending on the state of the application it will close all windows and exit the application. Applies only to some actions.
  • IUP_IGNORE: Makes the native system ignore that callback action. Applies only to some actions.
  • IUP_CONTINUE: Makes the element to ignore the callback and pass the treatment of the execution to the parent element. Applies only to some actions.
NB: returning IUP_CLOSE does not automatically invoke CLOSE_CB callbacks.

Only some callbacks support the last 3 return values. Check each callback documentation. When nothing is documented then only IUP_DEFAULT is supported.

Note: Avoid using IUP_IGNORE (and IUP_CLOSE) unless it is specifically documented for that callback.
For example, it is and always was the documented behaviour for an IDLE_ACTION callback to be removed when it returns IUP_IGNORE.
It was not originally documented, but has since been noted, that if an IupButton ACTION callback returns IUP_IGNORE, it likewise removes the callback, and in that way effectively disables the button.

An important detail when using callbacks is that they are only called when the user actually executes an action over an element.
A callback is not called when the programmer sets a value via IupSetAttribute.
For instance: when the programmer changes a selected item on a list, no callback is invoked.

The order of callback calling is system dependent.
For instance, the RESIZE_CB and the SHOW_CB are called in different order in Win32 and in X-Windows when the dialog is shown for the first time.

As well as its normal duty of verifying parameters, the cbfunc type can be used to declare variables suitable for storing callbacks.
The C header file "iupcbs.h" lists some 50 different typedefs for callbacks (IFxxx/sIFxxx/dIFxxx).
In Phix you can always get by with "atom" for each parameter, if need be.

The following callbacks are common to several controls/interface elements:

ACTION+ While common to several elements, the callback parameters vary - see specific elements for details.

Affects: IupButton, IupMenuItem, IupList, IupText, IupMultiLine, IupCanvas, IupToggle
BUTTON_CB Action generated when any mouse button is pressed or released.

function button_cb(Ihandle ih, integer button, pressed, x, y, atom pStatus)
ih: identifies the element that activated the event.
button: identifies the activated mouse button:

IUP_BUTTON1 - left mouse button (button 1);
IUP_BUTTON2 - middle mouse button (button 2);
IUP_BUTTON3 - right mouse button (button 3).

pressed: indicates the state of the button:

0 - mouse button was released;
1 - mouse button was pressed.

x, y: position in the canvas where the event has occurred, in pixels.
pStatus: status of the mouse buttons and some keyboard keys at the moment the event is generated (a char*).

Use the following routines on pStatus:
iup_isshift(pStatus)
iup_iscontrol(pStatus)
iup_isbutton1(pStatus)
iup_isbutton2(pStatus)
iup_isbutton3(pStatus)
iup_isbutton4(pStatus)
iup_isbutton5(pStatus)
iup_isdouble(pStatus)
iup_isalt(pStatus)
iup_issys(pStatus)

They return 1 if the respective key or button is pressed, and 0 otherwise.

Returns: IUP_CLOSE will be processed.
On some controls if IUP_IGNORE is returned the action is ignored (this is system dependent).

Notes
This callback can be used to customize a button behavior. For a standard button behavior use the ACTION callback of the IupButton.

For a single click the callback is called twice, one for pressed=1 and one for pressed=0.
The ACTION callback is only invoked after both calls.
In Windows, if a dialog is shown or popup in any situation there could be unpredictable results because the native system still has processing to be done even after the callback is called.

A double click is preceded by two single clicks, one for pressed=1 and one for pressed=0, and followed by a pressed=0, all three without the double click flag set.
In GTK, it is preceded by an additional two single clicks sequence. For example, for one double click all the following calls are made:

BUTTON_CB(but=1 (1), x=154, y=83 [  1       ])
BUTTON_CB(but=1 (0), x=154, y=83 [  1       ])
    BUTTON_CB(but=1 (1), x=154, y=83 [  1       ])     (in GTK only)
    BUTTON_CB(but=1 (0), x=154, y=83 [  1       ])     (in GTK only)
BUTTON_CB(but=1 (1), x=154, y=83 [  1  D    ])
BUTTON_CB(but=1 (0), x=154, y=83 [  1       ])
 

Affects: IupCanvas, IupButton, IupText, IupList, IupGLCanvas
CLOSE_CB Called just before a dialog is closed when the user clicks the close button of the title bar or an equivalent action.
NB: other callbacks returning IUP_CLOSE, or any code invoking IupExitLoop(), does not invoke any CLOSE_CB callback, instead any required final processing, such as saving files or invoking IupConfigDialogClosed(), must be performed manually/explicitly, that is, just before returning IUP_CLOSE or when invoking IupExitLoop.
Penning (say) my_shutdown() and invoking it from several places, including close_cb, is probably a wise move.

function close_cb(Ihandle ih)
ih: identifies the element that activated the event.

Returns: if IUP_IGNORE, it prevents the dialog from being closed. If you destroy the dialog in this callback, you must return IUP_IGNORE.
IUP_CLOSE will be processed.

Affects: IupDialog
DESTROY_CB Called right before an element is destroyed.

function destroy_cb(Ihandle ih)
ih: identifier of the element that activated the event.

If the dialog is visible then it is hidden before it is destroyed. The callback will be called right after it is hidden.

The callback will be called before all other destroy procedures - for instance, if the element has children then it is called before the children are destroyed.

For language binding implementations use the callback name "LDESTROY_CB" to release memory allocated by the binding for the element. Also the callback will be called before the language callback.

Affects: All
ENTERWINDOW_CB Action generated when the mouse enters the native element.

function enterwindow_cb(Ihandle ih)
ih: identifier of the element that activated the event.

Notes
When the cursor is moved from one element to another, the call order in all platforms will be first the LEAVEWINDOW_CB callback of the old control followed by the ENTERWINDOW_CB callback of the new control.

Affects: All controls with user interaction.

See Also: LEAVEWINDOW_CB
GETFOCUS_CB Action generated when an element is given keyboard focus.
This callback is called after the KILLFOCUS_CB of the element that lost the focus.
The IupGetFocus function during the callback returns the element that lost the focus.
function getfocus_cb(Ihandle ih)

ih: identifier of the element that received keyboard focus.

Affects: All elements with user interaction, except menus.

See Also: KILLFOCUS_CB, IupGetFocus, IupSetFocus
HELP_CB Action generated when the user presses F1 at a control.
In Motif is also activated by the Help button in some workstations keyboard.

function help_cb(Ihandle ih)
ih: identifier of the element that activated the event.

Returns: IUP_CLOSE will be processed.

Affects: All elements with user interaction.
IDLE_ACTION Predefined IUP action, generated when there are no events or messages to be processed. Often used to perform background operations.

function idle_action()
Returns: if IUP_CLOSE is returned the current loop will be closed and the callback will be removed.
If IUP_IGNORE is returned the callback is removed and normal processing continues.

Notes
The Idle callback will be called whenever there are no messages left to be processed.
This may occur more frequently than expected, for example if you move the mouse over the application the idle callback will be called many times because the mouse move message is processed so fast that the Idle will be called before another mouse move message occurs.
[No mouse(/user) is likely to generate 100 messages/s, which on a GHz box means ten million clocks between each in which to perform some idle processing.]

So this callback changes the message loop to a more CPU consuming one.
It is important it be set NULL when not used, otherwise the application consumes CPU even if the callback is doing nothing.

It can only be set using (eg) IupSetGlobalFunction("IDLE_ACTION", Icallback("idle_action")).

Long Time Operations
If you create a loop or an operation that takes a long time to complete inside a callback of your application then the user interface message loop processing is interrupted until the callback returns, so the user can not click on any control of the application. But there are ways to handle that:
  • call IupLoopStep or IupFlush inside the application callback when it is performing long time operations.
    This will allow the user to click on a cancel button for instance, because the user interface message loop will be processed.
  • split the operation in several parts that are processed by the Idle function when no messages are left to be processed for the user interface message loop.
    This will make a heavy use of the CPU, even if the callback is doing nothing.
  • split the operation in several parts but use a Timer to process each part.
If you just want to do something simple as a background redraw of an IupCanvas, then a better idea is to handle the "idle" state yourself.
For example, register a timer for a small time like 500ms, and reset the timer in all the mouse and keyboard callbacks of the IupCanvas.
If the timer is trigged then you are in idle state. If the IupCanvas loses its focus then stop the timer.

pwa/p2js: Uses window.requestIdleCallback() which is marked on MDN as experimental, but that has not changed since 2015. Note that according to caniuse.com for this to work in Safari you (and/or you users) must enable requestIdleCallback in Experimental (Webkit) Features, and the same may be true for Chrome on macOS (not that desktop/Phix works on macOS, yet).
Also note I am not quite sure what "current loop will be closed" above means for IUP_CLOSE returns, so IUP_CLOSE and IUP_IGNORE do the same thing, which is in fact don’t re-apply requestIdleCallback.
If at all possible you should strive to return within 50ms/break up idle processing into chucks of work shorter than that, to avoid (otherwise fairly harmless) JavaScript violation messages being logged to the (hidden) console. A future version may incorporate a means to get (deadline.timeRemaining() > 0 || deadline.didTimeout) in pwa/p2js, with a matching mechanism to get true on desktop/Phix, should that ever be desired/requested.

See Also: IupSetGlobalFunction, IupTimer.
GLOBALCTRLFUNC_CB Global callback for a restricted set of keys. (since 3.20)
Called only when the Ctrl+F? key combinations are pressed.
It was designed to be used for internal application debugging porpoises only.
Do not use it for release code.

function ctrl_func(integer c)
c: identifier of typed key. Please refer to K_ANY/KEY_CB below for a list of possible values.

It can only be set using (eg) IupSetGlobalFunction("GLOBALCTRLFUNC_CB", Icallback("ctrl_func")).

See Also: IupSetGlobalFunction.
ENTRY_POINT (since 3.28) Global callback for an entry point. Used when main is not possible, such as in iOS and Android systems (which Phix does not currently support).

It is called only once, when the main loop is processed, but after IupOpen().
For regular systems is called right before the actual event loop is started.
It can only be set using (eg) IupSetGlobalFunction("ENTRY_POINT", Icallback("entry_func")).

See also EXIT_CB (next), IupMainLoopLevel
EXIT_CB (since 3.28) Global callback for an exit. Used when main is not possible, such as in iOS and Android systems (which Phix does not currently support).

It is called every time the last main loop is ended.
For regular systems is called right after the actual event loop is ended, every time when the main loop level returns to 0.

It can only be set using (eg) IupSetGlobalFunction("EXIT_CB", Icallback("exit_func")).
K_ANY+
 or
KEY_CB+
Action generated when a keyboard event occurs. Note that KEY_CB is a phix-only mapping to K_ANY (for consistency, in other words IupSetCallback() and IupGetCallback() [and nowhere else] replace "KEY_CB" with "K_ANY" before invoking the C routine).

function key_cb(Ihandle ih, atom c)

ih: the element that activated the event.
c: the typed key. Possible values are listed below.

TIP: This is the pGUI documentation, should you be using xpGUI and the help system has landed you here when you are trying to figure out why xpGUI does not define some K_x, they have become VK_x, as further detailed here.

In previous versions of pGUI.e defining c as type integer would work, until an alt or sys key was entered, at which point they would fail with a run-time typecheck. Newer versions of pGUI.e now check for such a "time-bomb" signature and raise an error much earlier in the process, which significantly helps to avoid shipping code with that problem.

IUP defines several hundred key constants, most of which are available in pGUI:
K_ESC, K_CR (or '\r'), K_LF (or '\n'), K_BS (or '\b'), K_TAB (or '\t'), K_INS, K_DEL, K_HOME, K_UP, K_PGUP, K_LEFT, K_MIDDLE, K_RIGHT, K_END, K_DOWN, K_PGDN, K_PAUSE, K_Print, K_Menu, K_F1, K_F2, K_F3, K_F4, K_F5, K_F6, K_F7, K_F8, K_F9, K_F10, K_F11, K_F12, K_LSHIFT, K_RSHIFT, K_LCTRL, K_RCTRL, K_LALT, K_RALT, K_SCROLL, K_NUM, and K_CAPS.

Other standard key identifiers include (aside: full lists rather than say "K_A, K_B, .. K_Z" permit search/index):
K_SP (' '), K_exclam ('!'), K_quotedbl ('\"'), K_numbersign ('#'), K_dollar ('$'), K_percent ('%'), K_ampersand ('&'), K_apostrophe '\'', K_parentleft ('('), K_parentright (')'), K_asterisk ('*'), K_plus ('+'), K_comma (','), K_minus ('-'), K_period ('.'), K_slash ('/'), K_0, K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9 ('0'..'9'), K_colon (':'), K_semicolon (';'), K_less ('<'), K_equal ('='), K_greater ('>'), K_question ('?'), K_at ('@'), K_A, K_B, K_C, K_D, K_E, K_F, K_G, K_H, K_I, K_J, K_K, K_L, K_M, K_N, K_O, K_P, K_Q, K_R, K_S, K_T, K_U, K_V, K_W, K_X, K_Y, K_Z ('A'..'Z'), K_a, K_b, K_c, K_d, K_e, K_f, K_g, K_h, K_i, K_j, K_k, K_l, K_m, K_n, K_o, K_p, K_q, K_r, K_s, K_t, K_u, K_v, K_w, K_x, K_y, K_z ('a'..'z'), K_bracketleft ('['), K_backslash ('\\'), K_bracketright (']'), K_circum ('^'), K_underscore ('_'), K_grave ('`'), K_braceleft ('{'), K_bar ('|'), K_braceright ('}'), and K_tilde ('~'). My preference and recommendation is to use the literal values instead of the constant names for 'plain' keystrokes, since for example I cannot get '!' wrong, however I could very easily mis-spell K_exclam as K_exclaim, or K_parentleft as K_parenthleft or K_leftparenth, K_period as K_dot, K_greater as K_gt, ... sure the syntax colouring/compiler would catch it, but there is little benefit in you or me sitting there going "OK, how do you spell it then?". In contrast, the modified keystrokes as listed below are usually much easier, for instance using K_cA beats iup_XkeyCtrl('A') hands down.

The following are deprecated/untested:
K_acute ('´', #B4), K_ccedilla ('ç', #E7), and K_diaeresis ('¨', #A8). While those are valid for UTF-32, Windows-1252, and ISO 8859-1, the same cannot be said for UTF-8, and quite possibly several legacy 8-bit code pages, hence the exclusion. pGUI/IUP would probably understand them, but your app probably won’t. Obviously not having those constants only affects what is valid source code and in no way prevents a user keying such characters into your finished application.

Special note: When using Edix, and therefore similar pGUI applications, you may notice that it will not let you type a pound sign (£) into an ansi file [not even using the old Alt-0163 trick]. Quite a shock, I know, but when you think about it, also quite correct. It will of course let you type that sort of thing into a UTF-8 file. The critical thing is that a call to IupSetGlobal("UTF8MODE+","YES") exists somewhere.

For some keys, change the prefix to K_c*, K_m*, K_s*, and K_y* to add the respective modifier (Control, Alt, Shift, and Sys).
Sys in Windows is the Windows key and in Mac is the Apple key.
Modifier prefixes are always applied in the above order, for instance <Ctrl Shift C> is K_csC, not K_scC.

Note that some keys have not yet made it into pGUI. Only keys that make sense and I get round to testing will (ever) be added: for instance K_sexclam (heh) makes no sense because you cannot (on my keyboard anyhow) get a '!' without the shift key being down, and the same for K_sPrint, K_sSCROLL, and K_sPAUSE. (Apart from a general reluctance to add rafts of untested things, I am also trying to keep the documentation in step with the implementation.)
The following keys (ditto re full lists) do however exist:

Ctrl:
K_cSP, K_cPlus, K_cMinus, K_cEqual, K_cA, K_cB, K_cC, K_cD, K_cE, K_cF, K_cG, K_cH, K_cI, K_cJ, K_cK, K_cL, K_cM, K_cN, K_cO, K_cP, K_cQ, K_cR, K_cS, K_cT, K_cU, K_cV, K_cW, K_cX, K_cY, K_cZ, K_cPGUP, K_cPGDN, K_cHOME, K_cEND, K_cF1, K_cF2, K_cF3, K_cF4, K_cF5, K_cF6, K_cF7, K_cF8, K_cF9, K_cF10, K_cF11, K_cF12

Alt:
K_mA, K_mB, K_mC, K_mD, K_mE, K_mF, K_mG, K_mH, K_mI, K_mJ, K_mK, K_mL, K_mM, K_mN, K_mO, K_mP, K_mQ, K_mR, K_mS, K_mT, K_mU, K_mV, K_mW, K_mX, K_mY, K_mZ

Shift:
K_sSP

Ctrl Shift:
K_csSP, K_csA, K_csB, K_csC, K_csD, K_csE, K_csF, K_csG, K_csH, K_csI, K_csJ, K_csK, K_csL, K_csM, K_csN, K_csO, K_csP, K_csQ, K_csR, K_csS, K_csT, K_csU, K_csV, K_csW, K_csX, K_csY, K_csZ,

Alt Shift:
K_msA, K_msB, K_msC, K_msD, K_msE, K_msF, K_msG, K_msH, K_msI, K_msJ, K_msK, K_msL, K_msM, K_msN, K_msO, K_msP, K_msQ, K_msR, K_msS, K_msT, K_msU, K_msV, K_msW, K_msX, K_msY, K_msZ

Further keys will be added as needed and when time allows for adequate testing. In the short term, it should not prove difficult to add any missing ones that you need to pGUI.e, where you will find several potential but untested candidates commented out, maybe including the one you are after.

To obtain a key code for a generic combination you can also start with a base key and combine it repeated times using iup_XkeyCtrl(key), iup_XkeyAlt(key), iup_XkeyShift(key), and iup_XkeySys(key). For instance constant control_shift_c = iup_XkeyCtrl(iup_XkeyShift('C')). Note that, depending on the driver/firmware for your particular keyboard, iup_XkeyShift('c') might have use when caps lock is on, (now there’s a way to confuse your users) but you are unlikely to get very far with iup_XkeyCtrl(iup_XkeyShift('c')). In general, pGUI/IUP cannot guarantee the behaviour of various combinations of Caps Lock, Shift, and other key modifiers with regard to the case/capitalisation of alphabetic base keys, since that is system/driver/hardware dependent, instead the prudent programmer will ensure that eg 'c' and 'C' are both tested for.
The function integer ch = iup_XkeyBase(atom c) can be used to obtain the raw keystroke less any modifiers, and you can use the global attributes SHIFTKEY and CONTROLKEY instead of disecting the c parameter.
Also, the global attribute MODKEYSTATE can be used to detect the combination of two or more modifiers.

Literal string versions of these names may be used to assign callbacks, eg "K_cC", for <Ctrl C>, with the quotes, see below.

The above keys are also used in KEYPRESS_CB callbacks.

The iup_isprint(key) function returns true if a key can be directly used as a printable character.
The iup_isShiftXkey(key) function returns true if a given key is an extended code using the Shift modifier.
The iup_isCtrlXkey(key) function returns true for the Ctrl modifier.
The iup_isAltXkey(key) function returns true for the Alt modifier.
The iup_isSysXkey(key) function returns true for the Sys modifier.
string name = iupKeyCodeToName(key) returns a human-readable version of the key.

Note: GTK in Windows does not generate the Win modifier key, the K_Print and the K_Pause keys (up to GTK version 2.8.18).

Returns:
If IUP_IGNORE is returned the key is ignored and not processed by the control and not propagated.
If IUP_CONTINUE is returned the key is processed and the event propagated to the parent of the element receiving it. (default behavior)
If IUP_DEFAULT is returned the key is processed but it is not propagated.
IUP_CLOSE will be processed.

Notes
Keyboard callbacks depend on the keyboard usage of the control with the focus.
So if you return IUP_IGNORE the control will usually not process the key.
But be aware that sometimes the control processes the key in another event so even when returning IUP_IGNORE the key can still get processed, although it will not be propagated.

IMPORTANT: The callbacks "K_*" of the dialog or native containers depend on the IUP_CONTINUE return value to work while the control is in focus.

If the callback does not exist it is automatically propagated to the parent of the element.

K_* callbacks
All defined keys are also callbacks of any element, called when the respective key is activated.
For example: "K_cC" is also a callback activated when the user press Ctrl+C, when the focus is at the element or at a children with focus.
This is the way an application can create shortcut keys, also called hot keys.

Affects: All elements with keyboard interaction.
KEYPRESS_CB Action generated when a key is pressed or released.
If the key is pressed and held several calls will occur.
It is called after the callback K_ANY/KEY_CB is processed.

function keypress_cb(Ihandle ih, integer c, bool press)

ih: identifier of the element that activated the event.
c: identifier of typed key. See K_ANY/KEY_CB above for possible values.
press: true(1) when the key is pressed, false(0) when the key is released.

Returns: If IUP_IGNORE is returned the key is ignored by the system.
IUP_CLOSE will be processed.

Affects: IupCanvas
KILLFOCUS_CB Action generated when an element loses keyboard focus.
This callback is called before the GETFOCUS_CB of the element that gets the focus.

function killfocus_cb(Ihandle ih)

ih: identifier of the element that activated the event.

Affects: All elements with user interaction, except menus.

In Windows, there are restrictions when using this callback.
From MSDN on WM_KILLFOCUS:
“While processing this message, do not make any function calls that display or activate a window.
 This causes the thread to yield control and can cause the application to stop responding to messages.”

See Also: GETFOCUS_CB, IupGetFocus, IupSetFocus
LEAVEWINDOW_CB Action generated when the mouse leaves the native element.

function leavewindow_cb(Ihandle ih)
ih: identifier of the element that activated the event.

Notes
When the cursor is moved from one element to another, the call order in all platforms will be first the LEAVEWINDOW_CB callback of the old control followed by the ENTERWINDOW_CB callback of the new control.

Affects: All controls with user interaction.

See Also: ENTERWINDOW_CB
MAP_CB Called right after an element is mapped and its attributes updated in IupMap().

When the element is a dialog, it is called after the layout is updated. For all other elements it is called before the layout is updated, so the element current size will still be 0x0 during MAP_CB (since 3.14).

function map_cb(Ihandle ih)
ih: identifier of the element that activated the event.

Affects: All elements that have a native representation.
MOTION_CB Action generated when the mouse moves.

function motion_cb(Ihandle ih, integer x, y, atom pStatus)
ih: identifier of the element that activated the event.
x, y: position in the canvas where the event has occurred, in pixels.
pStatus: status of mouse buttons and certain keyboard keys at the moment the event was generated (a char*).

Use the same routines for pStatus as BUTTON_CB.

Affects: IupCanvas, IupGLCanvas, IupList, IupMatrix, IupText, IupTree
RESIZE_CB Action generated when the canvas or dialog size is changed.

function resize_cb(Ihandle ih, integer width, height)

ih: identifier of the element that activated the event.
width: the width of the internal element size in pixels not considering the decorations (client size)
height: the height of the internal element size in pixels not considering the decorations (client size)

For the dialog, this action is also generated when the dialog is mapped, after the map and before the show.

When XAUTOHIDE=Yes or YAUTOHIDE=Yes, if the canvas scrollbar is hidden/shown after changing the DX or DY attributes from inside the callback, the size of the drawing area will immediately change, so the parameters with and height will be invalid.
To update the parameters consult the DRAWSIZE attribute. Also activate the drawing toolkit only after updating the DX or DY attributes.

Affects: IupCanvas, IupGLCanvas, IupDialog
SCROLL_CB Called when some manipulation is made to the scrollbar.
The canvas is automatically redrawn only if this callback is NOT defined.

(GTK 2.8) Also the POSX and POSY values will not be correctly updated for older GTK versions.

In Ubuntu, when liboverlay-scrollbar is enabled (the new tiny auto-hide scrollbar) only the IUP_SBPOSV and IUP_SBPOSH codes are used.

Callback
function scroll_cb(Ihandle ih, integer op)
ih: identifier of the element that activated the event.
op: indicates the operation performed on the scrollbar:

If the manipulation was made on the vertical scrollbar, it can have the following values:

IUP_SBUP - line up
IUP_SBDN - line down
IUP_SBPGUP - page up
IUP_SBPGDN - page down
IUP_SBPOSV - vertical positioning
IUP_SBDRAGV - vertical drag

If it was on the horizontal scrollbar, the following values are valid:

IUP_SBLEFT - column left
IUP_SBRIGHT - column right
IUP_SBPGLEFT - page left
IUP_SBPGRIGHT - page right
IUP_SBPOSH - horizontal positioning
IUP_SBDRAGH - horizontal drag

Notes
IUP_SBDRAGH and IUP_SBDRAGV are not supported in GTK.
(atom posx, posy quietly removed in 1.0.2, as per IupCanvas/ACTION)

Affects: IupCanvas, IupGLCanvas, SCROLLBAR
UNMAP_CB Called right before an element is unmapped.

function unmap_cb(Ihandle ih)
ih: identifier of the element that activated the event.

Affects: All elements that have a native representation.
WHEEL_CB Action generated when the mouse wheel is rotated.
If this callback is not defined the wheel will automatically scroll the canvas in the vertical direction by some lines, the SCROLL_CB callback if defined will be called with the IUP_SBDRAGV operation.

function wheel_cb(Ihandle ih, atom delta, integer x, y, atom pStatus)
ih: identifier of the element that activated the event.
delta: the amount the wheel was rotated in notches (nb dodgy, see call_back).
x, y: position in the canvas where the event has occurred, in pixels.
pStatus: status of mouse buttons and certain keyboard keys at the moment the event was generated (a char*).

Use the same routines for pStatus as BUTTON_CB.

Notes: In Motif and GTK delta is always 1 or -1. In Windows is some situations delta can reach the value of two. In the future with more precise wheels this increment can be changed.

Affects: IupCanvas, IupGLCanvas