## guiboss-event-dispatch.pkg
#
# A support library for
#
#
src/lib/x-kit/widget/gui/guiboss-imp.pkg#
# This code used to live in it, but guiboss-imp.pkg was getting too big,
# so event-dispatch moved into this dedicated support package.
#
# Our primary responsibilities here are:
#
# * Dispatching incoming X events to the appropriate gadget,
# determined primarily by which visible gadget is positioned
# under the click coordinate.
#
# * Tracking which gadget has the mouse focus and synthesizing
# enter/leave events when the focus moves from one gadget to
# another gadget.
# Compiled by:
#
src/lib/x-kit/widget/xkit-widget.sublibstipulate
include package threadkit; # threadkit is from
src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg #
# package ap = client_to_atom; # client_to_atom is from
src/lib/x-kit/xclient/src/iccc/client-to-atom.pkg# package au = authentication; # authentication is from
src/lib/x-kit/xclient/src/stuff/authentication.pkg# package cpm = cs_pixmap; # cs_pixmap is from
src/lib/x-kit/xclient/src/window/cs-pixmap.pkg# package cpt = cs_pixmat; # cs_pixmat is from
src/lib/x-kit/xclient/src/window/cs-pixmat.pkg# package dy = display; # display is from
src/lib/x-kit/xclient/src/wire/display.pkg# package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg# package fti = font_index; # font_index is from
src/lib/x-kit/xclient/src/window/font-index.pkg# package r2k = xevent_router_to_keymap; # xevent_router_to_keymap is from
src/lib/x-kit/xclient/src/window/xevent-router-to-keymap.pkg# package mtx = rw_matrix; # rw_matrix is from
src/lib/std/src/rw-matrix.pkg# package rop = ro_pixmap; # ro_pixmap is from
src/lib/x-kit/xclient/src/window/ro-pixmap.pkg# package rw = root_window; # root_window is from
src/lib/x-kit/widget/lib/root-window.pkg# package rwv = rw_vector; # rw_vector is from
src/lib/std/src/rw-vector.pkg# package sep = client_to_selection; # client_to_selection is from
src/lib/x-kit/xclient/src/window/client-to-selection.pkg# package shp = shade; # shade is from
src/lib/x-kit/widget/lib/shade.pkg# package sj = socket_junk; # socket_junk is from
src/lib/internet/socket-junk.pkg# package x2s = xclient_to_sequencer; # xclient_to_sequencer is from
src/lib/x-kit/xclient/src/wire/xclient-to-sequencer.pkg# package tr = logger; # logger is from
src/lib/src/lib/thread-kit/src/lib/logger.pkg# package tsr = thread_scheduler_is_running; # thread_scheduler_is_running is from
src/lib/src/lib/thread-kit/src/core-thread-kit/thread-scheduler-is-running.pkg# package u1 = one_byte_unt; # one_byte_unt is from
src/lib/std/one-byte-unt.pkg# package v1u = vector_of_one_byte_unts; # vector_of_one_byte_unts is from
src/lib/std/src/vector-of-one-byte-unts.pkg# package v2w = value_to_wire; # value_to_wire is from
src/lib/x-kit/xclient/src/wire/value-to-wire.pkg# package wg = widget; # widget is from
src/lib/x-kit/widget/old/basic/widget.pkg# package wi = window; # window is from
src/lib/x-kit/xclient/src/window/window.pkg# package wme = window_map_event_sink; # window_map_event_sink is from
src/lib/x-kit/xclient/src/window/window-map-event-sink.pkg# package wpp = client_to_window_watcher; # client_to_window_watcher is from
src/lib/x-kit/xclient/src/window/client-to-window-watcher.pkg# package wy = widget_style; # widget_style is from
src/lib/x-kit/widget/lib/widget-style.pkg# package xc = xclient; # xclient is from
src/lib/x-kit/xclient/xclient.pkg# package xj = xsession_junk; # xsession_junk is from
src/lib/x-kit/xclient/src/window/xsession-junk.pkg# package xtr = xlogger; # xlogger is from
src/lib/x-kit/xclient/src/stuff/xlogger.pkg #
#
package evt = gui_event_types; # gui_event_types is from
src/lib/x-kit/widget/gui/gui-event-types.pkg package gts = gui_event_to_string; # gui_event_to_string is from
src/lib/x-kit/widget/gui/gui-event-to-string.pkg package gt = guiboss_types; # guiboss_types is from
src/lib/x-kit/widget/gui/guiboss-types.pkg package gtj = guiboss_types_junk; # guiboss_types_junk is from
src/lib/x-kit/widget/gui/guiboss-types-junk.pkg package a2r = windowsystem_to_xevent_router; # windowsystem_to_xevent_router is from
src/lib/x-kit/xclient/src/window/windowsystem-to-xevent-router.pkg package gd = gui_displaylist; # gui_displaylist is from
src/lib/x-kit/widget/theme/gui-displaylist.pkg package pp = standard_prettyprinter; # standard_prettyprinter is from
src/lib/prettyprint/big/src/standard-prettyprinter.pkg package err = compiler::error_message; # compiler is from
src/lib/core/compiler/compiler.pkg # error_message is from
src/lib/compiler/front/basics/errormsg/error-message.pkg package bt = gui_to_sprite_theme; # gui_to_sprite_theme is from
src/lib/x-kit/widget/theme/sprite/gui-to-sprite-theme.pkg package ct = gui_to_object_theme; # gui_to_object_theme is from
src/lib/x-kit/widget/theme/object/gui-to-object-theme.pkg package wt = widget_theme; # widget_theme is from
src/lib/x-kit/widget/theme/widget/widget-theme.pkg package boi = spritespace_imp; # spritespace_imp is from
src/lib/x-kit/widget/space/sprite/spritespace-imp.pkg package cai = objectspace_imp; # objectspace_imp is from
src/lib/x-kit/widget/space/object/objectspace-imp.pkg package pai = widgetspace_imp; # widgetspace_imp is from
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg #
package gtg = guiboss_to_guishim; # guiboss_to_guishim is from
src/lib/x-kit/widget/theme/guiboss-to-guishim.pkg package b2s = spritespace_to_sprite; # spritespace_to_sprite is from
src/lib/x-kit/widget/space/sprite/spritespace-to-sprite.pkg package c2o = objectspace_to_object; # objectspace_to_object is from
src/lib/x-kit/widget/space/object/objectspace-to-object.pkg package s2s = sprite_to_spritespace; # sprite_to_spritespace is from
src/lib/x-kit/widget/space/sprite/sprite-to-spritespace.pkg package o2o = object_to_objectspace; # object_to_objectspace is from
src/lib/x-kit/widget/space/object/object-to-objectspace.pkg package g2p = gadget_to_pixmap; # gadget_to_pixmap is from
src/lib/x-kit/widget/theme/gadget-to-pixmap.pkg# package frm = frame; # frame is from
src/lib/x-kit/widget/leaf/frame.pkg package idm = id_map; # id_map is from
src/lib/src/id-map.pkg package im = int_red_black_map; # int_red_black_map is from
src/lib/src/int-red-black-map.pkg# package is = int_red_black_set; # int_red_black_set is from
src/lib/src/int-red-black-set.pkg package r8 = rgb8; # rgb8 is from
src/lib/x-kit/xclient/src/color/rgb8.pkg package r64 = rgb; # rgb is from
src/lib/x-kit/xclient/src/color/rgb.pkg package g2d = geometry2d; # geometry2d is from
src/lib/std/2d/geometry2d.pkg package g2j = geometry2d_junk; # geometry2d_junk is from
src/lib/std/2d/geometry2d-junk.pkg package ebi = millboss_imp; # millboss_imp is from
src/lib/x-kit/widget/edit/millboss-imp.pkg package e2g = millboss_to_guiboss; # millboss_to_guiboss is from
src/lib/x-kit/widget/edit/millboss-to-guiboss.pkg tracefile = "widget-unit-test.trace.log";
nb = log::note_on_stderr; # log is from
src/lib/std/src/log.pkgDummy1 = ebi::Millboss_Option; # XXX SUCKO DELETEME. This is a quick hack to make sure the package compiles during early development of it.
herein
package guiboss_event_dispatch
: Guiboss_Event_Dispatch # Guiboss_Event_Dispatch is from
src/lib/x-kit/widget/gui/guiboss-event-dispatch.api {
Dummy = Int;
#################################################################################
# guiboss interface fns::
#
#
stipulate
Appropriate_Gadget_Imp_Info # Return value type for find_appropriate_gadget_imp_info().
#
= APPROPRIATE_GADGET (gt::Gadget_Imp_Info, g2d::Point) # The g2d::Point is the query point transformed into the appropriate local coordinate system for the gadget.
| NO_APPROPRIATE_GADGET g2d::Point
;
fun find_appropriate_gadget_imp_info # Which widget did the user click on? This is usually easy but it might be in a scrollable view in a tabbed view in another scrollable view, say.
(
me: gt::Guiboss_State, #
hostwindow_info: gt::Hostwindow_Info,
event_point
)
=
{
subwindow_infos #
=
gtj::return_all_subwindow_infos_in_descending_stacking_order
#
*hostwindow_info.subwindow_info;
search_subwindow_infos_in_descending_stacking_order subwindow_infos
where
fun search_subwindow_infos_in_descending_stacking_order []
=>
NO_APPROPRIATE_GADGET event_point; # Tried everything, no hits, give up.
search_subwindow_infos_in_descending_stacking_order (subwindow_info ! rest) # Try topmost remaining popup first.
=>
{ site = gtj::subwindow_info_site_in_basewindow_coordinates subwindow_info;
#
if (g2d::box::point_in_box (event_point, site))
#
find_appropriate_gadget_imp_info_for_guipane subwindow_info; # Found the right popup (or base) running gui, see if we hit any widgets within it.
else
search_subwindow_infos_in_descending_stacking_order rest; # event_point is not within this running gui, so try next one.
fi;
};
end;
end;
}
where
fun find_appropriate_gadget_imp_info_for_guipane # Which widget did the user click on? This is usually easy but it might be in a scrollable view in a tabbed view in another scrollable view, say.
(
subwindow_info: gt::Subwindow_Info # This will be the subwindow_info for either the topllevel running gui on the hostwindow, or else the running gui for one of its popups.
)
=
case (*subwindow_info.guipane)
#
THE (guipane: gt::Guipane)
=>
{ event_point
=
event_point
-
(gtj::subwindow_info_upperleft_in_base_window_coordinates subwindow_info); #
#
find_gadget_imp_info (guipane.rg_widget, event_point);
}
where
fun try_all_widgets ([]: List(gt::Rg_Widget_Type), point: g2d::Point)
=>
NO_APPROPRIATE_GADGET point;
try_all_widgets (row_or_col_widget ! rest, point)
=>
case (find_gadget_imp_info (row_or_col_widget, point))
#
NO_APPROPRIATE_GADGET _ => try_all_widgets (rest, point); # Try the remaining widgets in ROW/COL/FRAME/whatever.
info => info; # Got it.
esac;
end
also
fun try_all_rows ([]: List(List(gt::Rg_Widget_Type)), point: g2d::Point)
=>
NO_APPROPRIATE_GADGET point;
try_all_rows (row ! rest, point)
=>
case (try_all_widgets (row, point))
#
NO_APPROPRIATE_GADGET _ => try_all_rows (rest, point); # Try the remaining widgets in ROW/COL/FRAME/whatever.
info => info; # Got it.
esac;
end
also
fun find_gadget_imp_info
(
rg_widget: gt::Rg_Widget_Type,
point: g2d::Point
)
=
if (g2d::box::point_in_box (point, gtj::rg_widget_site rg_widget))
#
case rg_widget
#
gt::RG_ROW r => try_all_widgets ( r.widgets, point);
gt::RG_COL r => try_all_widgets ( r.widgets, point);
gt::RG_GRID r => try_all_rows ( r.widgets, point);
gt::RG_MARK r => try_all_widgets ([r.widget], point);
gt::RG_SCROLLPORT r
=>
{ point = point - g2d::box::upperleft(*r.site); # Transform mouseclick point into view coordinate system.
point = point - *r.upperleft; # Transform mouseclick point into scrolled view coordinate system.
#
find_gadget_imp_info (*r.rg_widget, point); # Recursively search for target widget of mouseclick among widgets in scrollable view.
};
gt::RG_TABPORT r
=>
{ point = point - g2d::box::upperleft(*r.site); # Transform mouseclick point into view coordinate system.
#
this_tab = list::nth (r.tabs, *r.visible_tab);
find_gadget_imp_info (this_tab.rg_widget, point); # Recursively search for target widget of mouseclick among widgets on visible tab.
};
gt::RG_FRAME r
=>
try_all_widgets ([ r.widget, r.frame_widget ], point);
gt::RG_WIDGET (r as { guiboss_to_widget, ... })
=>
{ imps = *me.gadget_imps;
#
id = guiboss_to_widget.id;
case (idm::get (imps, id))
#
NULL => NO_APPROPRIATE_GADGET point ;
#
THE gadget_imp_info # Return 'point' transformed into correct coordinate system for widget.
=>
case (*gadget_imp_info.point_in_gadget)
#
NULL => APPROPRIATE_GADGET (gadget_imp_info, point); # No point_in_gadget fn supplied by gadget, so count mouseclick as having hit the gadget.
THE fn => if (fn point) APPROPRIATE_GADGET (gadget_imp_info, point); # Have point_in_gadget fn supplied by the gadget decide whether the mouseclick was close enough to count.
else NO_APPROPRIATE_GADGET ( point);
fi;
esac;
esac;
};
gt::RG_OBJECTSPACE r
=>
NO_APPROPRIATE_GADGET point; # TBD
gt::RG_SPRITESPACE r
=>
NO_APPROPRIATE_GADGET point; # TBD
gt::RG_NULL_WIDGET
=>
NO_APPROPRIATE_GADGET point;
esac;
else
NO_APPROPRIATE_GADGET point;
fi;
end;
#
NULL => NO_APPROPRIATE_GADGET event_point; # Maybe we should do: log::fatal "find_appropriate_gadget_imp_info' called while gui not running!";
esac;
end;
herein #
fun do_motion_notify # Mouse has moved. Inform any relevant gadgets.
(
me: gt::Guiboss_State,
theme: wt::Widget_Theme,
hostwindow_info: gt::Hostwindow_Info,
motion_xevtinfo: evt::Motion_Xevtinfo
)
=
{ mouse_is = me.mouse_is;
#
case *mouse_is
#
gt::CROSSING_NONGADGET # Here the mouse is crossing from non-gadget pixels into gadget pixels.
=>
case (find_appropriate_gadget_imp_info (me, hostwindow_info, motion_xevtinfo.event_point))
#
APPROPRIATE_GADGET (gadget_imp_info, event_point) # 'event_point' is button_xevtinfo.event_point transformed into correct coordinate system for gadget (null transform if no scrollports or popups are involved).
=>
{ gadget_imp_info -> { guiboss_to_gadget,
gadget_mode,
...
};
# Remember gadget now has mouse focus:
#
(*gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_mode := { has_mouse_focus => TRUE, is_active, has_keyboard_focus };
guiboss_to_gadget.note_mouse_transit # Notify gadget that mouse has entered its space.
{
transit => gt::CAME,
modifier_keys_state => motion_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
guiboss_to_gadget.note_mouse_transit # Notify gadget that mouse has entered its space.
{
transit => gt::MOVE, # We send a MOVE after every CAME, for the convenience of handlers interested only in coordinates -- they can process all MOVE events and ignore CAME and LEFT events.
modifier_keys_state => motion_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::CROSSING_GADGET { gadget_imp_info }; # Remember which widget mouse is in.
};
NO_APPROPRIATE_GADGET event_point
=>
(); # Nothing to do in this case.
esac;
gt::CROSSING_GADGET { gadget_imp_info => (last_gadget_imp_info as { guiboss_to_gadget => last_guiboss_to_gadget, ... }) }
=>
case (find_appropriate_gadget_imp_info (me, hostwindow_info, motion_xevtinfo.event_point))
#
APPROPRIATE_GADGET (gadget_imp_info, event_point) # 'event_point' is button_xevtinfo.event_point transformed into correct coordinate system for gadget (null transform if no scrollports or popups are involved).
=>
{ gadget_imp_info -> { guiboss_to_gadget,
gadget_mode,
...
};
if (gtj::same_gadget_imp_info (gadget_imp_info, last_gadget_imp_info))
# # Here mouse is continuing to move on same gadget it was on at last report.
guiboss_to_gadget.note_mouse_transit # Notify gadget that mouse has entered its space.
{
transit => gt::MOVE, #
modifier_keys_state => motion_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
else # Here mouse has crossed from one gadget to another.
# Remember that last gadget no longer has mousefocus:
#
(*last_gadget_imp_info.gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
last_gadget_imp_info.gadget_mode := { has_mouse_focus => FALSE, is_active, has_keyboard_focus };
# Remember that new gadget now has mousefocus:
#
(*gadget_imp_info.gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_imp_info.gadget_mode := { has_mouse_focus => TRUE, is_active, has_keyboard_focus };
last_guiboss_to_gadget.note_mouse_transit # Notify last gadget that mouse has left its space.
{
transit => gt::LEFT,
modifier_keys_state => motion_xevtinfo.modifier_keys_state,
event_point,
site => *last_gadget_imp_info.site,
theme
};
mouse_is := gt::CROSSING_GADGET { gadget_imp_info }; # Remember that we're now on the new gadget.
#
guiboss_to_gadget.note_mouse_transit # Notify new gadget that mouse has entered its space.
{
transit => gt::CAME,
modifier_keys_state => motion_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
guiboss_to_gadget.note_mouse_transit # Notify gadget that mouse has entered its space.
{
transit => gt::MOVE, # We send a MOVE after every CAME, for the convenience of handlers interested only in coordinates -- they can process all MOVE events and ignore CAME and LEFT events.
modifier_keys_state => motion_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
fi;
};
NO_APPROPRIATE_GADGET event_point
=>
{ last_gadget_imp_info -> { guiboss_to_gadget,
gadget_mode,
...
};
# Remember gadget no longer has mousefocus:
#
(*gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_mode := { has_mouse_focus => FALSE, is_active, has_keyboard_focus };
guiboss_to_gadget.note_mouse_transit # Notify the gadget that we were on that mouse has left its space.
{
transit => gt::LEFT,
modifier_keys_state => motion_xevtinfo.modifier_keys_state,
event_point,
site => *last_gadget_imp_info.site,
theme
};
mouse_is := gt::CROSSING_NONGADGET;
};
esac;
gt::DRAGGING # Mouse is being dragged -- drag started on this gadget.
{
gadget_imp_info, # This is the gadget on which the drag started. It gets all the MOVE events until drag terminates, even if mouse leaves the window area owned by the gadget. (But we only send DRAGs while cursor is in the dragged gadget.)
start_point, # This is the window coordinate of the downclick which started this drag.
last_point, # This is the window coordinate of the last motion event for this drag.
guipane_offset # Add this to points in basewindow coordinate system to convert them to guipane coordinate system that the gadget expects.
}
=>
{ event_point = motion_xevtinfo.event_point + guipane_offset;
#
gadget_imp_info -> { guiboss_to_gadget,
...
};
guiboss_to_gadget.note_mouse_drag_event #
{ #
phase => gt::DRAG,
button => *me.last_button_changed,
modifier_keys_state => motion_xevtinfo.modifier_keys_state,
mousebuttons_state => motion_xevtinfo.mousebuttons_state,
event_point,
start_point,
last_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::DRAGGING # Remember location of last DRAG event.
{
gadget_imp_info, # This is the gadget on which the drag started. It gets all the motion events until drag terminates, even if mouse leaves the window area owned by the gadget.
start_point, # This is the window coordinate of the downclick which started this drag.
last_point => event_point, # This is the window coordinate of the last DRAG event for this drag.
guipane_offset # Add this to points in basewindow coordinate system to convert them to guipane coordinate system that the gadget expects.
};
};
# This is the old code, which only generates DRAG events when the mouse
# is within the gadget in which the drag started. I'm keeping it for now
# in case we turn out to have a need for it.
#
# case (find_appropriate_gadget_imp_info (me, hostwindow_info, motion_xevtinfo.event_point))
# #
# APPROPRIATE_GADGET (gadget_imp_info, event_point) # 'event_point' is button_xevtinfo.event_point transformed into correct coordinate system for gadget (null transform if no scrollports or popups are involved).
# =>
# { gadget_imp_info -> { guiboss_to_gadget,
# gadget_mode,
# ...
# };
#
# if (gtj::same_gadget_imp_info (gadget_imp_info, dragged_gadget_imp_info)) # If cursor is outside gadget in which drag started, we do absolutely nothing.
# #
# guiboss_to_gadget.note_mouse_drag_event #
# { #
# phase => gt::DRAG,
# button => *me.last_button_changed,
# modifier_keys_state => motion_xevtinfo.modifier_keys_state,
# mousebuttons_state => motion_xevtinfo.mousebuttons_state,
# event_point,
# start_point,
# last_point,
# site => *gadget_imp_info.site,
# theme
# };
#
# mouse_is := gt::DRAGGING # Remember location of last DRAG event.
# {
# gadget_imp_info, # This is the gadget on which the drag started. It gets all the motion events until drag terminates, even if mouse leaves the window area owned by the gadget.
# start_point, # This is the window coordinate of the downclick which started this drag.
# last_point => event_point, # This is the window coordinate of the last DRAG event for this drag.
# guipane_offset # Add this to points in basewindow coordinate system to convert them to guipane coordinate system that the gadget expects.
# };
# fi;
# };
#
# NO_APPROPRIATE_GADGET event_point
# =>
# (); # Mouse is not in the gadget that was downclicked so we completely ignore the motion event.
# esac;
esac;
};
fun do_button_press #
(
me: gt::Guiboss_State,
theme: wt::Widget_Theme,
hostwindow_info: gt::Hostwindow_Info,
button_xevtinfo: evt::Button_Xevtinfo
)
=
{ me.last_button_changed := button_xevtinfo.mouse_button; # Remember this for drag_fn client functions.
#
case (find_appropriate_gadget_imp_info (me, hostwindow_info, button_xevtinfo.event_point))
#
APPROPRIATE_GADGET (gadget_imp_info, event_point) # 'event_point' is button_xevtinfo.event_point transformed into correct coordinate system for gadget (null transform if no scrollports or popups are involved).
=>
{
mouse_is = me.mouse_is;
#
gadget_imp_info -> { guiboss_to_gadget,
gadget_mode,
...
};
case *mouse_is
#
gt::CROSSING_NONGADGET
=>
{
# Remember gadget now has mousefocus:
#
(*gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_mode := { has_mouse_focus => TRUE, is_active, has_keyboard_focus };
guiboss_to_gadget.note_mouse_transit # Tell gadget that mouse has entered its space.
{
transit => gt::CAME,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
guiboss_to_gadget.note_mouse_drag_event # Tell gadget that user just started a drag operation on it.
{ #
phase => gt::OPEN,
button => *me.last_button_changed,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
start_point => event_point,
last_point => event_point,
site => *gadget_imp_info.site,
theme
};
guiboss_to_gadget.note_mouse_drag_event # We send a DRAG after every OPEN, for the convenience of handlers interested only in coordinates -- they can process all DRAG events and ignore OPEN and DONE events.
{ #
phase => gt::DRAG,
button => *me.last_button_changed,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
start_point => event_point,
last_point => event_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::DRAGGING # Remember which widget mouse is in. SHOULD GENERATE AN 'ENTER' HERE.
{
gadget_imp_info,
start_point => event_point,
last_point => event_point,
guipane_offset => event_point - button_xevtinfo.event_point
};
#
};
gt::CROSSING_GADGET { gadget_imp_info => (last_gadget_imp_info as { guiboss_to_gadget => last_guiboss_to_gadget, ... }) }
=>
{
if (not (gtj::same_gadget_imp_info (gadget_imp_info, last_gadget_imp_info))) # If we just left a gadget, tell it so.
#
# Remember that last gadget no longer has mousefocus:
#
(*last_gadget_imp_info.gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
last_gadget_imp_info.gadget_mode := { has_mouse_focus => FALSE, is_active, has_keyboard_focus };
# Remember that new gadget now has mousefocus:
#
(*gadget_imp_info.gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_imp_info.gadget_mode := { has_mouse_focus => TRUE, is_active, has_keyboard_focus };
last_guiboss_to_gadget.note_mouse_transit # Notify last gadget that we were on that mouse has left its space.
{
transit => gt::LEFT,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *last_gadget_imp_info.site,
theme
};
guiboss_to_gadget.note_mouse_transit # Notify new gadget that mouse has entered its space.
{
transit => gt::CAME,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
fi;
guiboss_to_gadget.note_mouse_drag_event # Tell gadget that user just started a drag operation on it.
{ #
phase => gt::OPEN,
button => *me.last_button_changed,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
start_point => event_point,
last_point => event_point,
site => *gadget_imp_info.site,
theme
};
guiboss_to_gadget.note_mouse_drag_event # We send a DRAG after every OPEN, for the convenience of handlers interested only in coordinates -- they can process all DRAG events and ignore OPEN and DONE events.
{ #
phase => gt::DRAG,
button => *me.last_button_changed,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
start_point => event_point,
last_point => event_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::DRAGGING # Remember which widget mouse is in.
{
gadget_imp_info,
start_point => event_point,
last_point => event_point,
guipane_offset => event_point - button_xevtinfo.event_point
};
#
};
gt::DRAGGING # Mouse is being dragged -- drag started on this gadget.
{
gadget_imp_info => draggee, # This is the gadget on which the drag started. It gets all the motion events until drag terminates, even if mouse leaves the window area owned by the gadget.
start_point, # This is the window coordinate of the downclick which started this drag.
last_point, # This is the window coordinate of the last motion event for this drag.
guipane_offset # Add this to points in basewindow coordinate system to convert them to guipane coordinate system that the gadget expects.
}
=>
if (gtj::same_gadget_imp_info (gadget_imp_info, draggee)) # If we are still on the gadget being dragged...
#
guiboss_to_gadget.note_mouse_drag_event # Tell the gadget where the mouse now is.
{ #
phase => gt::DRAG,
button => *me.last_button_changed,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
start_point,
last_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::DRAGGING # Remember new 'last_point' for dragged gadget.
{
gadget_imp_info,
start_point,
last_point => event_point,
guipane_offset
};
fi;
esac;
#
# Following note_mousebutton_event stuff is completely independent of drag/motion stuff.
guiboss_to_gadget.note_mousebutton_event
{
mousebutton_event => gt::MOUSEBUTTON_PRESS,
mouse_button => button_xevtinfo.mouse_button,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
site => *gadget_imp_info.site,
theme
};
};
NO_APPROPRIATE_GADGET event_point
=>
{
mouse_is = me.mouse_is;
#
case *mouse_is
#
gt::CROSSING_NONGADGET
=>
();
gt::CROSSING_GADGET { gadget_imp_info }
=>
{ gadget_imp_info -> { guiboss_to_gadget, gadget_mode, ... };
#
# Remember that gadget no longer has mousefocus:
#
(*gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_mode := { has_mouse_focus => FALSE, is_active, has_keyboard_focus };
guiboss_to_gadget.note_mouse_transit # Notify last gadget that we were on that mouse has left its space.
{
transit => gt::LEFT,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::CROSSING_NONGADGET;
};
gt::DRAGGING # Mouse is being dragged on this gadget.
{
gadget_imp_info => dragged_gadget_imp_info, # This is the gadget on which the drag started. It gets all the motion events until drag terminates, even if mouse leaves the window area owned by the gadget.
start_point, # This is the window coordinate of the downclick which started this drag.
last_point, # This is the window coordinate of the last motion event for this drag.
guipane_offset # Add this to points in basewindow coordinate system to convert them to guipane coordinate system that the gadget expects.
}
=>
(); # When a drag is in progress, we do nothing if we are not on the dragged gadget.
esac;
};
esac;
};
fun do_button_release # Private.
(
me: gt::Guiboss_State,
theme: wt::Widget_Theme,
hostwindow_info: gt::Hostwindow_Info,
button_xevtinfo: evt::Button_Xevtinfo
)
=
{ me.last_button_changed := button_xevtinfo.mouse_button; # Remember this for drag_fn client functions.
#
case (find_appropriate_gadget_imp_info (me, hostwindow_info, button_xevtinfo.event_point))
#
APPROPRIATE_GADGET (gadget_imp_info, event_point) # 'event_point' is button_xevtinfo.event_point transformed into correct coordinate system for gadget (null transform if no scrollports or popups are involved).
=>
{ gadget_imp_info -> { guiboss_to_gadget, ... };
#
mouse_is = me.mouse_is;
case *mouse_is
#
gt::CROSSING_NONGADGET
=>
{ gadget_imp_info -> { guiboss_to_gadget,
gadget_mode,
...
};
#
# Remember gadget now has mousefocus:
#
(*gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_mode := { has_mouse_focus => TRUE, is_active, has_keyboard_focus };
guiboss_to_gadget.note_mouse_transit # Notify new gadget that mouse has entered its space.
{
transit => gt::CAME,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::CROSSING_GADGET { gadget_imp_info };
#
};
gt::CROSSING_GADGET { gadget_imp_info => gadget_imp_info2 } # This case should not actually be possible...? How can we be in gt::CROSSING_GADGET mode with a mousebutton down?
=>
if (not (gtj::same_gadget_imp_info (gadget_imp_info, gadget_imp_info2))) # If we just left a gadget, tell it so.
#
gadget_imp_info2 -> { guiboss_to_gadget => guiboss_to_gadget2, ... };
# Remember that last gadget no longer has mousefocus:
#
(*gadget_imp_info2.gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_imp_info2.gadget_mode := { has_mouse_focus => FALSE, is_active, has_keyboard_focus };
# Remember that new gadget now has mousefocus:
#
(*gadget_imp_info.gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_imp_info.gadget_mode := { has_mouse_focus => TRUE, is_active, has_keyboard_focus };
guiboss_to_gadget2.note_mouse_transit # Notify last gadget that we were on that mouse has left its space.
{
transit => gt::LEFT,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info2.site,
theme
};
guiboss_to_gadget.note_mouse_transit # Notify new gadget that mouse has entered its space.
{
transit => gt::CAME,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::CROSSING_GADGET { gadget_imp_info };
fi;
gt::DRAGGING # Mouse is being dragged -- drag started on this gadget.
{
gadget_imp_info => gadget_imp_info2, # This is the gadget on which the drag started. It gets all the motion events until drag terminates, even if mouse leaves the window area owned by the gadget.
start_point, # This is the window coordinate of the downclick which started this drag.
last_point, # This is the window coordinate of the last motion event for this drag.
guipane_offset # Add this to points in basewindow coordinate system to convert them to guipane coordinate system that the gadget expects.
}
=>
{
buttons = button_xevtinfo.mousebuttons_state;
#
if (evt::pressed_mousebutton_count buttons == 1) # 'buttons' is state BEFORE the release, so if pressed-button count is 1, all buttons are now released.
# # All mouse buttons are now released, so drag operation is over
gadget_imp_info2 -> { guiboss_to_gadget => guiboss_to_gadget2, ... };
guiboss_to_gadget2.note_mouse_drag_event # Tell the drag gadget that drag operation is complete.
{ #
phase => gt::DONE,
button => *me.last_button_changed,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
start_point,
last_point,
site => *gadget_imp_info2.site,
theme
};
if (not (gtj::same_gadget_imp_info (gadget_imp_info, gadget_imp_info2))) # If we just left a gadget, tell it so.
#
# Remember that last gadget no longer has mousefocus:
#
(*gadget_imp_info2.gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_imp_info2.gadget_mode := { has_mouse_focus => FALSE, is_active, has_keyboard_focus };
# Remember that new gadget now has mousefocus:
#
(*gadget_imp_info.gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_imp_info.gadget_mode := { has_mouse_focus => TRUE, is_active, has_keyboard_focus };
guiboss_to_gadget2.note_mouse_transit # Notify drag gadget that we were on that mouse has left its space.
{
transit => gt::LEFT,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info2.site,
theme
};
guiboss_to_gadget.note_mouse_transit # Notify new gadget that mouse has entered its space.
{
transit => gt::CAME,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
fi;
mouse_is := gt::CROSSING_GADGET { gadget_imp_info }; # Remember that drag operation is complete.
else # We still have some mouse buttons down.
if (gtj::same_gadget_imp_info (gadget_imp_info, gadget_imp_info2)) # If we are still on the drag gadget
#
guiboss_to_gadget.note_mouse_drag_event # Update the drag gadget with mouse location and buttonstate.
{ #
phase => gt::DRAG,
button => *me.last_button_changed,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
start_point,
last_point,
site => *gadget_imp_info.site,
theme
};
fi;
mouse_is := gt::DRAGGING # Remember new 'last_point' for dragged gadget.
{
gadget_imp_info,
start_point,
last_point => event_point,
guipane_offset
};
fi;
};
esac;
#
guiboss_to_gadget.note_mousebutton_event # note_mousebutton_event is completely independent of drag/motion stuff.
{
mousebutton_event => gt::MOUSEBUTTON_RELEASE,
mouse_button => button_xevtinfo.mouse_button,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point,
site => *gadget_imp_info.site,
theme
};
};
NO_APPROPRIATE_GADGET event_point
=>
{
mouse_is = me.mouse_is;
#
case *mouse_is
#
gt::CROSSING_NONGADGET
=>
();
gt::CROSSING_GADGET { gadget_imp_info }
=>
{ gadget_imp_info -> { guiboss_to_gadget, gadget_mode, ... };
#
# Remember that gadget no longer has mousefocus:
#
(*gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_mode := { has_mouse_focus => FALSE, is_active, has_keyboard_focus };
guiboss_to_gadget.note_mouse_transit # Notify last gadget that we were on that mouse has left its space.
{
transit => gt::LEFT,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::CROSSING_NONGADGET;
};
gt::DRAGGING # Mouse is being dragged on this gadget.
{
gadget_imp_info, # This is the gadget on which the drag started. It gets all the motion events until drag terminates, even if mouse leaves the window area owned by the gadget.
start_point, # This is the window coordinate of the downclick which started this drag.
last_point, # This is the window coordinate of the last motion event for this drag.
guipane_offset # Add this to points in basewindow coordinate system to convert them to guipane coordinate system that the gadget expects.
}
=>
{ buttons = button_xevtinfo.mousebuttons_state;
#
gadget_imp_info -> { guiboss_to_gadget, gadget_mode, ... };
if (evt::pressed_mousebutton_count buttons == 1) # Tell the drag gadget that drag operation is complete.
#
# Remember that gadget no longer has mousefocus:
#
(*gadget_mode) -> { has_mouse_focus => _, is_active, has_keyboard_focus };
gadget_mode := { has_mouse_focus => FALSE, is_active, has_keyboard_focus };
guiboss_to_gadget.note_mouse_drag_event # Notify the drag gadget that the drag operation is now complete.
{ #
phase => gt::DONE,
button => *me.last_button_changed,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
mousebuttons_state => button_xevtinfo.mousebuttons_state,
event_point => last_point, # event_point is not within drag gadget, so re-use old point here. Apps probably should not use this value, but some will likely ignore the OPEN/DRAG/DONE flag and blindly process all event_points.
start_point,
last_point,
site => *gadget_imp_info.site,
theme
};
guiboss_to_gadget.note_mouse_transit # Notify drag gadget that mouse has left its space.
{
transit => gt::LEFT,
modifier_keys_state => button_xevtinfo.modifier_keys_state,
event_point,
site => *gadget_imp_info.site,
theme
};
mouse_is := gt::CROSSING_NONGADGET;
fi; # No 'else' here because as long as we're dragging we generate no Gadget_Transit events.
};
esac;
}; # NO_APPROPRIATE_GADGET case._
esac;
};
fun do_key_press # Private.
(
me: gt::Guiboss_State,
theme: wt::Widget_Theme,
hostwindow_info: gt::Hostwindow_Info,
key_xevtinfo: evt::Key_Xevtinfo
)
=
{
if TRUE
case *me.keyboard_focus # This code implements click-to-type keystroke handling. Click-to-type works much better with the emacs tradition of using 'C-x o' etc to move keyboard focus around,
# # since it removes the presumption that keystrokes always go to the widget under the mouse cursor.
THE gadget_imp_info
=>
{
gadget_imp_info -> { guiboss_to_gadget, ... };
#
keychar = (string::length_in_bytes key_xevtinfo.ascii == 1)
?? string::get_byte_as_char(key_xevtinfo.ascii, 0)
:: '\0';
guiboss_to_gadget.note_key_event
{
keystroke
=>
{ key_event => gt::KEY_PRESS,
keycode => key_xevtinfo.keycode,
keysym => key_xevtinfo.keysym,
keystring => key_xevtinfo.ascii,
keychar,
modifier_keys_state => key_xevtinfo.modifier_keys_state,
mousebuttons_state => key_xevtinfo.mousebuttons_state
},
site => *gadget_imp_info.site,
theme
};
};
NULL => ();
esac;
else # Using 'if TRUE' is better than commenting the following out because it helps prevent bitrot -- the below code gets typechecked before being removed as dead code.
case (find_appropriate_gadget_imp_info (me, hostwindow_info, key_xevtinfo.event_point)) # This code implements keyboard-focus-follows-mouse keystroke handling, which was phased out in favor of the above.
# # I'm leaving this code in place because we may want to make this optionally selectable behavior at some point.
APPROPRIATE_GADGET (gadget_imp_info, event_point) # 'event_point' is button_xevtinfo.event_point transformed into correct coordinate system for gadget (null transform if no scrollports or popups are involved).
=>
{
gadget_imp_info -> { guiboss_to_gadget, ... };
#
keychar = (string::length_in_bytes key_xevtinfo.ascii == 1)
?? string::get_byte_as_char(key_xevtinfo.ascii, 0)
:: '\0';
guiboss_to_gadget.note_key_event
{
keystroke
=>
{ key_event => gt::KEY_PRESS,
keycode => key_xevtinfo.keycode,
keysym => key_xevtinfo.keysym,
keystring => key_xevtinfo.ascii,
keychar,
modifier_keys_state => key_xevtinfo.modifier_keys_state,
mousebuttons_state => key_xevtinfo.mousebuttons_state
},
site => *gadget_imp_info.site,
theme
};
};
NO_APPROPRIATE_GADGET _
=>
{
};
esac;
fi;
};
fun do_key_release # Private.
(
me: gt::Guiboss_State,
theme: wt::Widget_Theme,
hostwindow_info: gt::Hostwindow_Info,
key_xevtinfo: evt::Key_Xevtinfo
)
=
{
if TRUE
case *me.keyboard_focus # This code implements click-to-type keystroke handling. Click-to-type works much better with the emacs tradition of using 'C-x o' etc to move keyboard focus around,
# # since it removes the presumption that keystrokes always go to the widget under the mouse cursor.
THE gadget_imp_info # I'm leaving this code in place because we may want to make this optionally selectable behavior at some point.
=>
{
gadget_imp_info -> { guiboss_to_gadget, ... };
#
keychar = (string::length_in_bytes key_xevtinfo.ascii == 1)
?? string::get_byte_as_char(key_xevtinfo.ascii, 0)
:: '\0';
guiboss_to_gadget.note_key_event
{
keystroke
=>
{ key_event => gt::KEY_RELEASE,
keycode => key_xevtinfo.keycode,
keysym => key_xevtinfo.keysym,
keystring => key_xevtinfo.ascii,
keychar,
modifier_keys_state => key_xevtinfo.modifier_keys_state,
mousebuttons_state => key_xevtinfo.mousebuttons_state
},
site => *gadget_imp_info.site,
theme
};
};
NULL => ();
esac;
else # Using 'if TRUE' is better than commenting the following out because it helps prevent bitrot -- the below code gets typechecked before being removed as dead code.
case (find_appropriate_gadget_imp_info (me, hostwindow_info, key_xevtinfo.event_point)) # This code implements keyboard-focus-follows-mouse keystroke handling, which was phased out in favor of the above.
#
APPROPRIATE_GADGET (gadget_imp_info, event_point) # 'event_point' is button_xevtinfo.event_point transformed into correct coordinate system for gadget (null transform if no scrollports or popups are involved).
=>
{ gadget_imp_info -> { guiboss_to_gadget, ... };
#
keychar = (string::length_in_bytes key_xevtinfo.ascii == 1)
?? string::get_byte_as_char(key_xevtinfo.ascii, 0)
:: '\0';
guiboss_to_gadget.note_key_event
{
keystroke
=>
{ key_event => gt::KEY_RELEASE,
keycode => key_xevtinfo.keycode,
keysym => key_xevtinfo.keysym,
keystring => key_xevtinfo.ascii,
keychar,
modifier_keys_state => key_xevtinfo.modifier_keys_state,
mousebuttons_state => key_xevtinfo.mousebuttons_state
},
site => *gadget_imp_info.site,
theme
};
};
NO_APPROPRIATE_GADGET _
=>
{
};
esac;
fi;
};
end;
fun dispatch_event
(
arg
as
( route: a2r::Envelope_Route,
event: evt::x::Event
),
me: gt::Guiboss_State,
theme: wt::Widget_Theme,
hostwindow_info: gt::Hostwindow_Info
)
=
case event
#
evt::x::KEY_PRESS (key_xevtinfo: evt::Key_Xevtinfo ) => do_key_press (me, theme, hostwindow_info, key_xevtinfo );
evt::x::KEY_RELEASE (key_xevtinfo: evt::Key_Xevtinfo ) => do_key_release (me, theme, hostwindow_info, key_xevtinfo );
evt::x::BUTTON_PRESS (button_xevtinfo: evt::Button_Xevtinfo) => do_button_press (me, theme, hostwindow_info, button_xevtinfo);
evt::x::BUTTON_RELEASE (button_xevtinfo: evt::Button_Xevtinfo) => do_button_release (me, theme, hostwindow_info, button_xevtinfo);
evt::x::MOTION_NOTIFY (motion_xevtinfo: evt::Motion_Xevtinfo) => do_motion_notify (me, theme, hostwindow_info, motion_xevtinfo);
evt::x::ENTER_NOTIFY (inout_xevtinfo: evt::Inout_Xevtinfo )
=>
{
# printf "guievent_sink()/ENTER_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
};
evt::x::LEAVE_NOTIFY (inout_xevtinfo: evt::Inout_Xevtinfo)
=>
{
# printf "guievent_sink()/LEAVE_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
};
evt::x::FOCUS_IN (focus_xevtinfo: evt::Focus_Xevtinfo)
=>
printf "guievent_sink()/FOCUS_IN: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::FOCUS_OUT (focus_xevtinfo: evt::Focus_Xevtinfo)
=>
printf "guievent_sink()/FOCUS_OUT: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::KEYMAP_NOTIFY { }
=>
printf "guievent_sink()/KEYMAP_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::EXPOSE (expose_record: evt::x::Expose_Record)
=>
printf "guievent_sink()/EXPOSE: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::GRAPHICS_EXPOSE (graphics_expose_record: evt::x::Graphics_Expose_Record)
=>
printf "guievent_sink()/GRAPHICS_EXPOSE: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::NO_EXPOSE
{ drawable: evt::Drawable_Id,
major_opcode: Unt, # The graphics operation code.
minor_opcode: Unt # Always 0 for core protocol.
}
=>
printf "guievent_sink()/NO_EXPOSE: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::VISIBILITY_NOTIFY
{ changed_window_id: evt::Window_Id, # The window with changed visibility state.
state: evt::Visibility # The new visibility state.
}
=>
printf "guievent_sink()/VISIBILITY_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::CREATE_NOTIFY
{ parent_window_id: evt::Window_Id, # The created window's parent.
created_window_id: evt::Window_Id, # The created window.
box: g2d::Box, # The window's rectangle.
border_wid: Int, # The width of the border.
override_redirect: Bool #
}
=>
printf "guievent_sink()/CREATE_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::DESTROY_NOTIFY
{ event_window_id: evt::Window_Id, # The window on which this was generated.
destroyed_window_id: evt::Window_Id # The destroyed window.
}
=>
printf "guievent_sink()/DESTROY_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::UNMAP_NOTIFY
{ event_window_id: evt::Window_Id, # The window on which this was generated.
unmapped_window_id: evt::Window_Id, # The window being unmapped.
from_config: Bool # TRUE if parent was resized.
}
=>
printf "guievent_sink()/UNMAP_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::MAP_NOTIFY
{ event_window_id: evt::Window_Id, # The window on which this was generated.
mapped_window_id: evt::Window_Id, # The window being mapped.
override_redirect: Bool #
}
=>
printf "guievent_sink()/MAP_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::MAP_REQUEST
{ parent_window_id: evt::Window_Id, # The parent.
mapped_window_id: evt::Window_Id # The mapped window.
}
=>
printf "guievent_sink()/MAP_REQUEST: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::REPARENT_NOTIFY
{ event_window_id: evt::Window_Id, # The window on which this was generated.
parent_window_id: evt::Window_Id, # The new parent.
rerooted_window_id: evt::Window_Id, # The re-rooted window.
upperleft_corner: g2d::Point, # The upper-left corner.
override_redirect: Bool #
}
=>
printf "guievent_sink()/REPARENT_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::CONFIGURE_NOTIFY
{ event_window_id: evt::Window_Id, # The window on which this was generated.
configured_window_id: evt::Window_Id, # The reconfigured window.
sibling_window_id: Null_Or(evt::Window_Id), # The sibling that window is above (if any).
box: g2d::Box, # The window's rectangle.
border_wid: Int, # The width of the border.
override_redirect: Bool #
}
=>
{
printf "guievent_sink()/CONFIGURE_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
};
evt::x::CONFIGURE_REQUEST
{ parent_window_id: evt::Window_Id, # The parent.
configure_window_id: evt::Window_Id, # The window to reconfigure.
sibling_window_id: Null_Or(evt::Window_Id), # The new sibling (if any).
x: Null_Or(Int), # The window's rectangle.
y: Null_Or(Int),
wide: Null_Or(Int),
high: Null_Or(Int),
border_wid: Null_Or(Int), # The width of the border.
stack_mode: Null_Or(evt::Stack_Mode) # The mode for stacking windows.
}
=>
printf "guievent_sink()/CONFIGURE_REQUEST: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::GRAVITY_NOTIFY
{
event_window_id: evt::Window_Id, # The window on which this was generated.
moved_window_id: evt::Window_Id, # The window being moved.
upperleft_corner: g2d::Point # Upper-left corner of window.
}
=>
printf "guievent_sink()/GRAVITY_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::RESIZE_REQUEST
{
resize_window_id: evt::Window_Id, # The window to resize.
req_size: g2d::Size # The requested new size.
}
=>
printf "guievent_sink()/RESIZE_REQUEST: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::CIRCULATE_NOTIFY
{
event_window_id: evt::Window_Id, # The window on which this was generated.
circulated_window_id: evt::Window_Id, # The window being circulated.
parent_window_id: evt::Window_Id, # The parent.
place: evt::Stack_Pos # The new place.
}
=>
printf "guievent_sink()/CIRCULATE_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::CIRCULATE_REQUEST
{
parent_window_id: evt::Window_Id, # The parent.
circulate_window_id: evt::Window_Id, # The window to circulate.
place: evt::Stack_Pos # The place to circulate the window to.
}
=>
printf "guievent_sink()/CIRCULATE_REQUEST: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::PROPERTY_NOTIFY
{
changed_window_id: evt::Window_Id, # The window with the changed property.
atom: evt::Atom, # The affected property.
timestamp: evt::t::Xserver_Timestamp, # When the property was changed.
deleted: Bool # TRUE if the property was deleted.
}
=>
printf "guievent_sink()/PROPERTY_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::SELECTION_CLEAR
{
owning_window_id: evt::Window_Id, # The current owner of the selection.
selection: evt::Atom, # The selection.
timestamp: evt::t::Xserver_Timestamp # The last-change time.
}
=>
printf "guievent_sink()/SELECTION_CLEAR: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::SELECTION_REQUEST
{
owning_window_id: evt::Window_Id, # The owner of the selection.
selection: evt::Atom, # The selection.
target: evt::Atom, # The requested type for the selection.
requesting_window_id: evt::Window_Id, # The requesting window.
property: Null_Or( evt::Atom ), # The property to store the selection in.
timestamp: evt::Timestamp #
}
=>
printf "guievent_sink()/SELECTION_REQUEST: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::SELECTION_NOTIFY
{
requesting_window_id: evt::Window_Id, # The requestor of the selection.
selection: evt::Atom, # The selection.
target: evt::Atom, # The requested type of the selection.
property: Null_Or( evt::Atom ), # The property to store the selection in.
timestamp: evt::Timestamp #
}
=>
printf "guievent_sink()/SELECTION_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::COLORMAP_NOTIFY
{
window_id: evt::Window_Id, # The affected window.
cmap: Null_Or( evt::Colormap_Id ), # The colormap.
new: Bool, # TRUE, if the colormap attribute is changed.
installed: Bool # TRUE, if the colormap is installed.
}
=>
printf "guievent_sink()/COLORMAP_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::CLIENT_MESSAGE
{
window_id: evt::Window_Id, #
type: evt::Atom, # The type of the message.
value: evt::Raw_Data # The message value.
}
=>
printf "guievent_sink()/CLIENT_MESSAGE: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::MODIFIER_MAPPING_NOTIFY # Really a MappingNotify event.
=>
printf "guievent_sink()/MODIFIER_MAPPING_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::KEYBOARD_MAPPING_NOTIFY # Really a MappingNotify event.
{
first_keycode: evt::Keycode,
count: Int
}
=>
printf "guievent_sink()/KEYBOARD_MAPPING_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
evt::x::POINTER_MAPPING_NOTIFY # Really a MappingNotify event.
=>
printf "guievent_sink()/POINTER_MAPPING_NOTIFY: ignoring '%s' Gui_Event -- guiboss-imp.pkg\n" (gts::gui_event_to_string event);
esac; # NB: We avoid a '_' case here because if an event is added to evt::x::Event we want a compile error as a reminder to handle it.
};
end;