## guiboss-popup-junk.pkg
#
# A support library for
#
#
src/lib/x-kit/widget/gui/guiboss-imp.pkg#
# Random code related to maintaining guiboss popups, moved here
# because guiboss-imp.pkg was getting way too big for comfort.
# 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# package tbi = textmill; # textmill is from
src/lib/x-kit/widget/edit/textmill.pkg tracefile = "widget-unit-test.trace.log";
nb = log::note_on_stderr; # log is from
src/lib/std/src/log.pkgherein
package guiboss_popup_junk
: Guiboss_Popup_Junk # Guiboss_Popup_Junk is from
src/lib/x-kit/widget/gui/guiboss-popup-junk.api {
Dummy = Int;
fun clear_box_in_pixmap # Clear a box to black, mostly to avoid undefined values etc.
(
pixmap: gt::Subwindow_Or_View, # pixmap holding the scrollport.
box: g2d::Box # Box in view coordinates.
)
=
case pixmap
#
gt::SUBWINDOW_INFO { pixmap: Ref(g2p::Gadget_To_Rw_Pixmap), ... } => (*pixmap).draw_displaylist [ gd::COLOR (r64::black, [ gd::FILLED_BOXES [ box ]]) ];
gt::SCROLLABLE_INFO { pixmap: g2p::Gadget_To_Rw_Pixmap, ... } => pixmap.draw_displaylist [ gd::COLOR (r64::black, [ gd::FILLED_BOXES [ box ]]) ];
gt::TABBABLE_INFO { pixmap: g2p::Gadget_To_Rw_Pixmap, ... } => pixmap.draw_displaylist [ gd::COLOR (r64::black, [ gd::FILLED_BOXES [ box ]]) ];
esac;
# The high-level architectural ideas here are:
# o Every running gui has an associated offscreen subwindow_or_view containing a complete image of its window.
# We have one running gui for the main visible window plus one for each visible popup.
# (Popups do not have separate X windows; they are implemented entirely client-side, drawing into the main window.)
# The popups cover less screen space than the main visible window, so they have smaller offscreen subwindow_or_views.
# o Gadgets always draw to the offscreen subwindow_or_view for the running gui with which they are associated.
# o We update the visible window by copying rectangles from the subwindow_or_views to the visible window.
# These copies need to respect the popup hierarchy, e.g. the main guipane must not write over screenspace belonging to any popup.
# We never do text drawing ops or such directly onto the visible window.
# o Scrollable views introduce an additional level of indirection:
# * Each scrollable view has its own offscreen subwindow_or_view.
# * Widgets located on a scrollable view draw to its subwindow_or_view.
# * We copy rectangles from the scrollable-view subwindow_or_view to its parent subwindow_or_view.
# (We never copy directly from the scrollable-view subwindow_or_view to the visible window.)
# * Scrollable-view stuff then becomes visible when the parent subwindow_or_view is copied to the visible window.
# * It is reasonable for a scrollable view to contain another scrollable view, so the above should be understood recursively.
#
# Nomenclature: "blit" is from "BitBLT" == "bit-boundary block transfer" -- originally a Xerox Alto graphics op, now informal jargon term. For more info: http://en.wikipedia.org/wiki/Bit_blit
# Because we allow nested scrollable subwindows of main hostwindow for app,
# it is nontrivial to figure out where on the hostwindow a given gadget is
# visible -- if it is visible at all! -- and how much is visible, and what
# pixel rectangle to copy from where to where to update the gadget's on-
# screen image. That's our job here.
fun update_offscreen_parent_pixmaps_and_then_hostwindow
(
pixmap: gt::Subwindow_Or_View,
from_box: g2d::Box, # From-box in source pixmap coordinates.
hostwindow_for_gui: gtg::Guiboss_To_Hostwindow
)
=
{
propagate_frombox_changes_to_all_parents_in_which_they_are_visible
#
(pixmap, from_box); # Copy visible part of gadget to the backing pixmap for the scrollport containing it, the backing pixmap for the scrollport containing that scrollport etc and finally the visible hostwindow itself.
} # Typically there will be no scrollports involved, so this will be just a blit to the hostwindow.
where
fun find_frombox_parts_not_hidden_by_popups
(
subwindow_or_view: gt::Subwindow_Or_View,
from_box: g2d::Box # We assume this is in local subwindow_or_view coordinates (not basewindow coordinates).
)
=
{
# The redraw logic expects the from_box info to be in 'subwindow_or_view' coordinates, not basewindow coords.
# But to compare from_box with the possibly shading running-gui pixmaps, they must all be in the samme coordinate system.
# Consequently we transform the possibly_shading_pixmaps into our local 'subwindow_or_view' coordinates.
# Now we figure out which parts of 'from_box'
# are not hidden by popup windows:
bp = gtj::subwindow_info_of_subwindow_or_view subwindow_or_view; # This returns 'r' from subwindow_or_view as (SUBWINDOW_INFO r). "bp" == "subwindow_or_view".
possibly_shadowing_pixmaps # Get the popup windows which are maybe shadowing us (that is, which we might clobber if we drew all of from_box)
=
gtj::find_all_subwindow_infos_above_given_subwindow_or_view_in_stacking_order
#
subwindow_or_view;
possibly_shadowing_sites # Convert the possibly_shadowing_pixmaps to boxes in basewindow coordinates.
=
(map gtj::subwindow_info_site_in_basewindow_coordinates # This adds in the 'upperleft' fields of all our parents.
#
possibly_shadowing_pixmaps
)
: List( g2d::Box );
bp_upperleft_in_basewindow_coordinates
=
g2d::box::upperleft
(
gtj::subwindow_info_site_in_basewindow_coordinates bp
);
possibly_shadowing_sites # Convert shadowing sites from basewindow coords to 'subwindow_or_view' coords.
=
(map translate_site_to_our_coordinate_system
#
possibly_shadowing_sites #
)
where
fun translate_site_to_our_coordinate_system (box: g2d::Box)
=
{ (g2d::box::upperleft_and_size box)
->
(box_upperleft, size);
g2d::box::make (box_upperleft - bp_upperleft_in_basewindow_coordinates, size);
};
end;
visible_parts_of_frombox # Subtract the boxes from from_box to see what parts of from_box it is actually safe to draw (if any).
=
g2d::box::subtract_boxes_b_from_boxes_a
{
a => [ from_box ],
b => possibly_shadowing_sites
};
visible_parts_of_frombox; #
}; # fun find_frombox_parts_not_hidden_by_popups
fun propagate_frombox_changes_to_all_parents_in_which_they_are_visible # Caller has just changed contents of from_box in subwindow_or_view: We need to propagate these changes to all parents in which it is visible.
(
subwindow_or_view # A gt::SUBWINDOW_INFO contains the complete offscreen image of one running gui, either the main window one or a popup.
as # Consequently in the gt::SUBWINDOW_INFO case we are always copying from the offscreen subwindow_or_view to the visible screen,
gt::SUBWINDOW_INFO bp, # never from one offscreen subwindow_or_view to another. When copying to the visible screen we do need to be careful not to
# overwrite screen space belonging to any popup which is above us in the stacking order.
from_box: g2d::Box # From-box in source pixmap coordinates.
)
=>
{
frombox_fragments_to_draw # These are in local pixmap coordinates (not basewindow coordinates).
=
find_frombox_parts_not_hidden_by_popups (subwindow_or_view, from_box);
pixmap_site
=
gtj::subwindow_info_site_in_basewindow_coordinates bp;
pixmap_upperleft = g2d::box::upperleft pixmap_site;
from_id = gtj::subwindow_or_view_id_of subwindow_or_view; # This is the pixmap holding the source pixels for the blit.
#
apply draw_fragment frombox_fragments_to_draw # For each part of from_box which is not hidden by overlying popups....
where
fun draw_fragment (from_box: g2d::Box)
=
{
to_point = (g2d::box::upperleft from_box) + pixmap_upperleft; # Where should we copy pixels to, on the visible hostwindow? If we are a popup, we need to add in the popup upperleft (pixmap_upperleft) in basewindow coordinates.
hostwindow_for_gui.draw_displaylist # ... blit that part to on-screen window for user to see.
[
gd::COPY_FROM_RW_PIXMAP { from_box, to_point, from_id }
];
};
end;
};
propagate_frombox_changes_to_all_parents_in_which_they_are_visible # This gt::SCROLLABLE_INFO case will happen when we have a scrollport located on a scrollport.
(
subwindow_or_view # A gt::SCROLLABLE_INFO contains the offscreen image of one scrollable scrollport embedded within a parent subwindow_or_view.
as # Consequently in the gt::SCROLLABLE_INFO case we are always copying from one offscreen subwindow_or_view to another.
gt::SCROLLABLE_INFO { id: Id,
upperleft: Ref(g2d::Point), # Upperleft of view's subwindow_or_view in scrollport coordinates, used for scrolling pixmap in scrollport.
scroller: Ref(gt::Scroller), # Client-code interface for controlling view_upperleft.
callback: gt::Scroller_Callback, # This is how we pass our Scroller to app client code, which basically lets it set 'pixmap_upperleft' above.
site: Ref(g2d::Box), # Current assigned site on pixmap. Set by assign_sites_to_all_widgets() in
src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg rg_widget: Ref( gt::Rg_Widget_Type ),
pixmap: g2p::Gadget_To_Rw_Pixmap,
parent_subwindow_or_view: gt::Subwindow_Or_View # This can be a SCROLLABLE_INFO if we have a scrollport located on a scrollport.
},
from_box: g2d::Box # From-box in source pixmap.
)
=>
{
from_id = gtj::subwindow_or_view_id_of subwindow_or_view; # The Id for the source pixmap for the copy.
scrollport_upperleft_in_view # If the from_box is not entirely visible in the scrollport
= # then we need to clip it to the scrollport. Since we want
g2d::point::zero - *upperleft; # the clipped from_box to be in the gadget's home pixmap,
# the most straightforward approach is to transform the
# scrollport into home pixmap space. If *upperleft is
scrollport' = g2d::box::clone_box_at (*site, scrollport_upperleft_in_view); # 0,0 then scrollport is at (0,0) in home pixmap, otherwise
# it is offset by -*upperleft, so in general we want
# the port cloned at -*upperleft.
to_point = g2d::box::upperleft from_box; # Where should we copy pixels to, on our parent pixmap? We initialize this to the null transform -- we'll add in appropriate offsets to this momentarily.
case (g2d::box::intersection (scrollport', from_box))
#
NULL => (); # No intersection between from_box and scrollport' means no part of gadget is visible, so just return NULL.
#
THE from_box'
=>
{
my (to_point, from_box) # Update to_point and from_box to account for clipping due
= # to intersection between scrollport and old from_box value.
if (g2d::box::eq (from_box', from_box))
#
(to_point, from_box); # No actual clipping (from_box must be completely visible in scrollport) so nothing to do here.
elif (g2d::point::eq ( g2d::box::upperleft( from_box' ), # Is upperleft of from_box' different from upperleft of from_box?
g2d::box::upperleft( from_box )
) )
(to_point, from_box'); # No, so to_point stays the same, we just replace from_box with from_box'.
else
# Yes, so we need to move to_point to reflect displacement between from_box and from_box'.
frombox_displacement
=
g2d::point::subtract( g2d::box::upperleft( from_box' ), # Compute that displacement.
g2d::box::upperleft( from_box )
);
to_point' = g2d::point::add (to_point, frombox_displacement); # Apply it.
(to_point', from_box'); # Done.
fi;
# Now we just need to compute where from_box should be drawn in
# current sub/window, then update to_point and continue recursively.
to_point = g2d::point::add (to_point, *upperleft); # Account for location of view relative to scrollport.
to_point = g2d::point::add (to_point, g2d::box::upperleft(*site)); # Account for location of scrollport relative to parent pixmap.
parent_pixmap' = gtj::gadget_to_rw_pixmap__of parent_subwindow_or_view; # Find off-screen backing pixmap containing scrollport onto us.
from_id = pixmap.id; # Pixmap to copy rectangle from (as Id).
gui_displayop = gd::COPY_FROM_RW_PIXMAP { from_box, to_point, from_id }; # The actual copy from our pixmap to scrollport area in parent pixmap.
# #
parent_pixmap'.draw_displaylist [ gui_displayop ]; # Draw updated gadget appearance into its off-screen backing-pixmap home site.
from_box = g2d::box::clone_box_at (from_box, to_point); # Our to-box is from_box for the next level of recursion.
propagate_frombox_changes_to_all_parents_in_which_they_are_visible # Continue recursively to next level of scrollport nesting.
#
(parent_subwindow_or_view, from_box);
};
esac;
};
propagate_frombox_changes_to_all_parents_in_which_they_are_visible #
(
subwindow_or_view #
as #
gt::TABBABLE_INFO {
rg_widget: gt::Rg_Widget_Type,
pixmap: g2p::Gadget_To_Rw_Pixmap,
parent_subwindow_or_view: gt::Subwindow_Or_View, # This can be a SCROLLABLE_INFO if we have a tabport located on a scrollport, for example.
site: Ref(g2d::Box), # Size and location of subwindow tabport in parent Subwindow_Or_View coordinates.
#
is_visible: Ref( Bool ) # We do not have to worry about popups blocking our copies, since they are entirely internal to one guipane.
},
from_box: g2d::Box # From-box in source pixmap.
)
=>
if (*is_visible) # Do not propagate if we are one of multiple TABPORT and we are not visible.
#
from_id = gtj::subwindow_or_view_id_of subwindow_or_view; # The Id for the source pixmap for the copy.
tabport_upperleft_in_view # Tabports do not support scrolling, so upperleft is always at zero.
= #
g2d::point::zero; #
tabport' = g2d::box::clone_box_at (*site, tabport_upperleft_in_view); #
#
#
to_point = g2d::box::upperleft from_box; # Where should we copy pixels to, on our parent pixmap? We initialize this to the null transform -- we'll add in appropriate offsets to this momentarily.
case (g2d::box::intersection (tabport', from_box))
#
NULL => (); # No intersection between from_box and tabport' means no part of gadget is visible, so just return NULL.
#
THE from_box'
=>
{
my (to_point, from_box) # Update to_point and from_box to account for clipping due
= # to intersection between tabport and old from_box value.
if (g2d::box::eq (from_box', from_box))
#
(to_point, from_box); # No actual clipping (from_box must be completely visible in tabport) so nothing to do here.
elif (g2d::point::eq ( g2d::box::upperleft( from_box' ), # Is upperleft of from_box' different from upperleft of from_box?
g2d::box::upperleft( from_box )
) )
(to_point, from_box'); # No, so to_point stays the same, we just replace from_box with from_box'.
else
# Yes, so we need to move to_point to reflect displacement between from_box and from_box'.
frombox_displacement
=
g2d::point::subtract( g2d::box::upperleft( from_box' ), # Compute that displacement.
g2d::box::upperleft( from_box )
);
to_point' = g2d::point::add (to_point, frombox_displacement); # Apply it.
(to_point', from_box'); # Done.
fi;
# Now we just need to compute where from_box should be drawn in
# current sub/window, then update to_point and continue recursively.
to_point = g2d::point::add (to_point, g2d::box::upperleft(*site)); # Account for location of tabport relative to parent pixmap.
parent_pixmap' = gtj::gadget_to_rw_pixmap__of parent_subwindow_or_view; # Find off-screen backing pixmap containing tabport onto us.
from_id = pixmap.id; # Pixmap to copy rectangle from (as Id).
gui_displayop = gd::COPY_FROM_RW_PIXMAP { from_box, to_point, from_id }; # The actual copy from our pixmap to tabport area in parent pixmap.
# #
parent_pixmap'.draw_displaylist [ gui_displayop ]; # Draw updated gadget appearance into its off-screen backing-pixmap home site.
from_box = g2d::box::clone_box_at (from_box, to_point); # Our to-box is from_box for the next level of recursion.
propagate_frombox_changes_to_all_parents_in_which_they_are_visible # Continue recursively to next level of tabport nesting.
#
(parent_subwindow_or_view, from_box);
};
esac;
fi;
end;
end;
fun refresh_hostwindow_rectangle
(
hostwindow_info: gt::Hostwindow_Info,
from_box: g2d::Box # From-box in base window coordinates.
)
=
gtj::all_guipanes_on_hostwindow_apply hostwindow_info
#
(\\ (guipane: gt::Guipane) = {
#
subwindow_info
=
gtj::subwindow_info_of_subwindow_data
#
guipane.subwindow_info;
guipane_upperleft
=
gtj::subwindow_info_upperleft_in_base_window_coordinates
#
subwindow_info;
guipane_size = (*subwindow_info.pixmap).size;
guipane_site = g2d::box::make (guipane_upperleft, guipane_size);
case (g2d::box::intersection (from_box, guipane_site))
#
THE intersection # They do intersect. Intersection is in base-window coordinates.
=>
{ (g2d::box::upperleft_and_size intersection)
->
( intersection_upperleft_in_basewindow_coordinates,
intersection_size
);
intersection_upperleft_in_guipane_coordinates
=
intersection_upperleft_in_basewindow_coordinates
-
guipane_upperleft;
intersection_site_in_guipane_coordinates
=
g2d::box::make (intersection_upperleft_in_guipane_coordinates, intersection_size);
update_offscreen_parent_pixmaps_and_then_hostwindow
(
gt::SUBWINDOW_INFO subwindow_info,
intersection_site_in_guipane_coordinates,
guipane.hostwindow
);
};
NULL => ();
esac;
();
});
#
fun kill__guipane__imps
(
guipane: gt::Guipane,
me: gt::Guiboss_State # This arg is not actually currently used.
)
=
{
gtj::guipane_apply
(
guipane,
[
gtj::RG_WIDGET_FN kill__rg_widget__imp,
gtj::RG_SPRITE_FN kill__rg_sprite__imp,
gtj::RG_OBJECT_FN kill__rg_object__imp,
#
gtj::RG_OBJECTSPACE_FN kill__rg_objectspace__imp,
gtj::RG_SPRITESPACE_FN kill__rg_spritespace__imp,
gtj::RG_WIDGETSPACE_FN kill__rg_widgetspace__imp
]
)
where
fun kill__rg_widget__imp (rg_widget: gt::Rg_Widget) = rg_widget.guiboss_to_widget.g.die ();
fun kill__rg_sprite__imp (rg_sprite: gt::Rg_Sprite) = rg_sprite.guiboss_to_gadget.die ();
fun kill__rg_object__imp (rg_object: gt::Rg_Object) = rg_object.guiboss_to_gadget.die ();
#
fun kill__rg_objectspace__imp (rg_objectspace: gt::Rg_Objectspace) = rg_objectspace.guiboss_to_objectspace.die ();
fun kill__rg_spritespace__imp (rg_spritespace: gt::Rg_Spritespace) = rg_spritespace.guiboss_to_spritespace.die ();
fun kill__rg_widgetspace__imp (rg_widgetspace: gt::Rg_Widgetspace) = rg_widgetspace.guiboss_to_widgetspace.die ();
end;
};
#
fun free__guipane__resources
(
guipane: gt::Guipane,
me: gt::Guiboss_State
)
=
{ # Release all X-server pixmaps owned by gadgets in this guipane:
#
gtj::guipane_apply
(
guipane,
[
gtj::RG_WIDGET_FN free__rg_widget__pixmaps,
gtj::RG_SPRITE_FN free__rg_sprite__pixmaps,
gtj::RG_OBJECT_FN free__rg_object__pixmaps
]
)
where
fun free_gadget_pixmaps (gadget_imp_info: gt::Gadget_Imp_Info)
=
apply release_pixmap (im::vals_list *gadget_imp_info.pixmaps)
where
fun release_pixmap (rw_pixmap: g2p::Gadget_To_Rw_Pixmap)
=
rw_pixmap.free_rw_pixmap (); # This is a no-op if the widget already freed the rw_pixmap.
end;
fun free__rg_widget__pixmaps (rg_widget: gt::Rg_Widget) = case (idm::get (*me.gadget_imps, rg_widget.guiboss_to_widget.id)) THE g => free_gadget_pixmaps g; NULL => (); esac; # We don't expect the NULL cases to happen; possibly we should log errors if they do.
fun free__rg_sprite__pixmaps (rg_sprite: gt::Rg_Sprite) = case (idm::get (*me.gadget_imps, rg_sprite.guiboss_to_gadget.id)) THE g => free_gadget_pixmaps g; NULL => (); esac;
fun free__rg_object__pixmaps (rg_object: gt::Rg_Object) = case (idm::get (*me.gadget_imps, rg_object.guiboss_to_gadget.id)) THE g => free_gadget_pixmaps g; NULL => (); esac;
end;
# Release all X-server pixmaps owned by scrollports and tabports in this guipane:
#
gtj::guipane_apply
(
guipane,
[
gtj::RG_SCROLLPORT_FN free__rg_scrollport__pixmap,
gtj::RG_TABPORT_FN free__rg_tabport__pixmaps
]
)
where
fun free__rg_scrollport__pixmap (rg_scrollport: gt::Rg_Scrollport)
=
rg_scrollport.pixmap.free_rw_pixmap (); # This is a no-op if someone already freed the rw_pixmap.
fun free__rg_tabport__pixmaps (rg_tabport: gt::Rg_Tabport)
=
apply do_tab rg_tabport.tabs
where
fun do_tab (tab: gt::Tabbable_Info)
=
tab.pixmap.free_rw_pixmap (); # This is a no-op if someone already freed the rw_pixmap.
end;
end;
# Release backing pixmap for this guipane:
#
case guipane.subwindow_info
#
gt::SUBWINDOW_DATA (subwindow_info: gt::Subwindow_Info)
=>
(*subwindow_info.pixmap).free_rw_pixmap (); # This is a no-op if someone already freed the rw_pixmap.
esac;
# Drop all imps for this guipane from our global imp indices:
#
gtj::guipane_apply
(
guipane,
[
gtj::RG_WIDGET_FN drop__rg_widget__imp,
gtj::RG_SPRITE_FN drop__rg_sprite__imp,
gtj::RG_OBJECT_FN drop__rg_object__imp,
#
gtj::RG_OBJECTSPACE_FN drop__rg_objectspace__imp,
gtj::RG_SPRITESPACE_FN drop__rg_spritespace__imp,
gtj::RG_WIDGETSPACE_FN drop__rg_widgetspace__imp
]
)
where
fun drop__rg_widget__imp (rg_widget: gt::Rg_Widget) = me.gadget_imps := idm::drop (*me.gadget_imps, rg_widget.guiboss_to_widget.id);
fun drop__rg_sprite__imp (rg_sprite: gt::Rg_Sprite) = me.gadget_imps := idm::drop (*me.gadget_imps, rg_sprite.guiboss_to_gadget.id);
fun drop__rg_object__imp (rg_object: gt::Rg_Object) = me.gadget_imps := idm::drop (*me.gadget_imps, rg_object.guiboss_to_gadget.id);
#
fun drop__rg_objectspace__imp (rg_objectspace: gt::Rg_Objectspace) = me.objectspace_imps := idm::drop (*me.objectspace_imps, rg_objectspace.guiboss_to_objectspace.id);
fun drop__rg_spritespace__imp (rg_spritespace: gt::Rg_Spritespace) = me.spritespace_imps := idm::drop (*me.spritespace_imps, rg_spritespace.guiboss_to_spritespace.id);
fun drop__rg_widgetspace__imp (rg_widgetspace: gt::Rg_Widgetspace) = me.widgetspace_imps := idm::drop (*me.widgetspace_imps, rg_widgetspace.guiboss_to_widgetspace.id);
end;
};
fun popup_nesting_depth_of_gadget
( id: Id,
me: gt::Guiboss_State
)
: Int # Result will be 0 for gadgets on base window, 1 for those on first-level popups, 2 for those on popups on popups, etc.
=
{
i = gtj::get_gadget_imp_info (me.gadget_imps, id);
#
s = gtj::subwindow_info_of_subwindow_or_view *i.subwindow_or_view;
nesting_depth_of (s, 0)
where
fun nesting_depth_of
(
s: gt::Subwindow_Info,
depth: Int
)
=
case s.parent
#
NULL => depth;
THE (gt::SUBWINDOW_DATA s) => nesting_depth_of (s, depth+1);
esac;
end;
};
};
end;