Module: gtk-duim Synopsis: GTK port implementation Author: Andy Armstrong, Scott McKay Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND /// Some magic GTK constants define constant $caret-width :: = 2; /// GTK ports define sealed class () sealed slot %app-context = #f; sealed slot %app-shell = #f; sealed slot %modifier-map :: = #[]; // Cache for image cursors sealed slot %cursor-cache :: = make(); keyword focus-policy: = #"sheet-under-pointer"; end class ; define sealed method initialize (_port :: , #key server-path) => () next-method(); initialize-gtk(); /*---*** What to do here? let type = head(server-path); let display = get-property(tail(server-path), #"display", default: environment-variable("DISPLAY")); ignore(type); let (shell, context, unused-args) = construct-application("DUIM port", // class name -- defines resources display-name: display, app-context-name: format-to-string("DUIM port on %s", display), fallback-resources: $primitive-resources); ignore(unused-args); _port.%display := xt/XtDisplay(shell); _port.%app-shell := shell; _port.%app-context := context; _port.%modifier-map := initialize-modifier-map(_port.%display); install-default-palette(_port); install-default-text-style-mappings(_port); */ end method initialize; register-port-class(#"gtk", , default?: #t); define sideways method class-for-make-port (type == #"gtk", #rest initargs, #key) => (class :: , initargs :: false-or()) values(, concatenate(initargs, #(event-processor-type:, #"n"))) end method class-for-make-port; define sealed method port-type (_port :: ) => (type :: ) #"gtk" end method port-type; define sealed method port-name (_port :: ) => (name :: false-or()) "No Port Name" end method port-name; define sealed method destroy-port (_port :: ) => () next-method(); // release-default-text-style-mappings(_port); ignoring("destroy-port") end method destroy-port; define function shutdown-gtk-duim () let ports :: = make(); do-ports(method (_port) when (instance?(_port, )) add!(ports, _port) end end method); do(destroy-port, ports) end function shutdown-gtk-duim; /// Beeping, etc define sealed method beep (_port :: ) => () gdk-beep() end method beep; /// Pointer position hacking define sealed method do-pointer-position (_port :: , pointer :: , sheet :: ) => (x :: , y :: ) ignoring("do-pointer-position"); values(0, 0) end method do-pointer-position; define sealed method do-pointer-position (_port :: , pointer :: , sheet :: ) => (x :: , y :: ) ignoring("do-pointer-position"); values(0, 0) end method do-pointer-position; define sealed method do-set-pointer-position (_port :: , pointer :: , sheet :: , x :: , y :: ) => () ignoring("do-set-pointer-position") end method do-set-pointer-position; define sealed method do-set-pointer-position (_port :: , pointer :: , sheet :: , x :: , y :: ) => () ignoring("do-set-pointer-position") end method do-set-pointer-position; /// Pointer cursor hacking /*---*** Need a GTK version of this... define table $cursor-table :: = { #"default" => x/$XC-TOP-LEFT-ARROW, #"busy" => x/$XC-WATCH, #"vertical-scroll" => x/$XC-SB-V-DOUBLE-ARROW, #"horizontal-scroll" => x/$XC-SB-H-DOUBLE-ARROW, #"scroll-up" => x/$XC-SB-UP-ARROW, #"scroll-down" => x/$XC-SB-DOWN-ARROW, #"scroll-left" => x/$XC-SB-LEFT-ARROW, #"scroll-right" => x/$XC-SB-RIGHT-ARROW, #"upper-left" => x/$XC-TOP-LEFT-CORNER, #"upper-right" => x/$XC-TOP-RIGHT-CORNER, #"lower-left" => x/$XC-BOTTOM-LEFT-CORNER, #"lower-right" => x/$XC-BOTTOM-RIGHT-CORNER, #"vertical-thumb" => x/$XC-SB-RIGHT-ARROW, #"horizontal-thumb" => x/$XC-SB-UP-ARROW, #"button" => x/$XC-TOP-LEFT-ARROW, #"prompt" => x/$XC-QUESTION-ARROW, #"move" => x/$XC-FLEUR, #"position" => x/$XC-CROSSHAIR, #"i-beam" => x/$XC-SB-UP-ARROW, #"cross" => x/$XC-CROSSHAIR, #"starting" => x/$XC-CLOCK, #"hand" => x/$XC-I-BEAM }; */ define sealed method do-set-pointer-cursor (_port :: , pointer :: , cursor :: ) => () ignoring("do-set-pointer-cursor") end method do-set-pointer-cursor; define sealed method do-set-sheet-cursor (_port :: , sheet :: , cursor :: ) => () ignoring("do-set-sheet-cursor") end method do-set-sheet-cursor; define method grab-pointer (_port :: , pointer :: , sheet :: ) => (success? :: ) let mirror = sheet-mirror(sheet); let widget = mirror & mirror-widget(mirror); let result :: = 0; when (widget) //---*** Get real current time... let current-time = 0; result := gdk-pointer-grab(widget, 0, // owner events logior($GDK-POINTER-MOTION-MASK, $GDK-BUTTON-PRESS-MASK, $GDK-BUTTON-RELEASE-MASK), null-pointer(), // confine to null-pointer(), // cursor current-time); end; result ~= 0 end method grab-pointer; define method ungrab-pointer (_port :: , pointer :: ) => (success? :: ) let sheet = pointer-grabbed?(pointer); let mirror = sheet-mirror(sheet); let widget = mirror & mirror-widget(mirror); let result = #f; if (widget) //---*** How do we get the current time? let current-time = 0; gdk-pointer-ungrab(current-time); #t end end method ungrab-pointer; define sealed method realize-cursor (_port :: , cursor :: ) => (gtk-cursor) ignoring("realize-cursor") end method realize-cursor; define sealed method realize-cursor (_port :: , cursor :: ) => (gtk-cursor) gethash(_port.%cursor-cache, cursor) | begin ignoring("realize-cursor") end end method realize-cursor; /// Focus and carets define sealed class () end class ; define sealed method make-caret (_port :: , sheet :: , #key x, y, width, height) => (caret :: ) make(, port: _port, sheet: sheet, x: x | 0, y: y | 0, width: width | $caret-width, height: height | (sheet-line-height(sheet) + sheet-line-spacing(sheet))) end method make-caret; define sealed method do-set-caret-position (caret :: , x :: , y :: ) => () let transform = sheet-device-transform(caret-sheet(caret)); with-device-coordinates (transform, x, y) ignoring("do-set-caret-position") end end method do-set-caret-position; define sealed method do-set-caret-size (caret :: , width :: , height :: ) => () ignoring("do-set-caret-size") end method do-set-caret-size; define sealed method do-show-caret (caret :: , #key tooltip?) => () ignore(tooltip?); let sheet = caret-sheet(caret); let widget = sheet & mirror-widget(sheet-mirror(sheet)); when (widget) ignoring("do-show-caret") end end method do-show-caret; define sealed method do-hide-caret (caret :: , #key tooltip?) => () ignore(tooltip?); let sheet = caret-sheet(caret); let widget = sheet & mirror-widget(sheet-mirror(sheet)); when (widget) ignoring("do-hide-caret") end end method do-hide-caret; /// Input focus handling define sealed method note-focus-in (_port :: , sheet :: ) => () next-method(); ignoring("note-focus-in") end method note-focus-in; define sealed method note-focus-out (_port :: , sheet :: ) => () next-method(); ignoring("note-focus-out") end method note-focus-out; /// Port defaults define method port-default-foreground (_port :: , sheet :: ) => (foreground :: false-or()) query-widget-for-color(sheet, #"foreground") end method port-default-foreground; // Most sheets should show up with the standard 3d gray background... define method port-default-background (_port :: , sheet :: ) => (background :: false-or()); query-widget-for-color(sheet, #"background") end method port-default-background; // ...but drawing panes should defaultly have a white background define method port-default-background (_port :: , sheet :: ) => (background :: false-or()); $white end method port-default-background; define method query-widget-for-color (sheet :: , key :: one-of(#"foreground", #"background")) => (color :: false-or()) ignoring("query-widget-for-color"); let mirror = sheet-mirror(sheet); let widget = mirror & mirror-widget(mirror); when (widget) #f // query-pixel-for-color(xt/XtGetValues(widget, key), port-default-palette(_port)) end end method query-widget-for-color; //---*** WHAT TO DO ABOUT THIS? // FYI, the normal size on GTK is 8-points // We arrange to map this to something close to ANSI_VAR_FONT define constant $gtk-default-text-style = make(, family: #"sans-serif", weight: #"normal", slant: #"roman", size: #"normal"); // Note that this "default default" text style is _not_ the one that we use // for gadgets. There's another method for that on . define method port-default-text-style (_port :: , sheet :: ) => (text-style :: false-or()) $gtk-default-text-style end method port-default-text-style;