summaryrefslogtreecommitdiff
path: root/Source/SaWMan/src
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SaWMan/src')
-rwxr-xr-xSource/SaWMan/src/Makefile.am62
-rwxr-xr-xSource/SaWMan/src/Makefile.in538
-rwxr-xr-xSource/SaWMan/src/isawman.c343
-rwxr-xr-xSource/SaWMan/src/isawman.h61
-rwxr-xr-xSource/SaWMan/src/isawmanmanager.c718
-rwxr-xr-xSource/SaWMan/src/isawmanmanager.h48
-rwxr-xr-xSource/SaWMan/src/sawman.c3522
-rwxr-xr-xSource/SaWMan/src/sawman_config.c512
-rwxr-xr-xSource/SaWMan/src/sawman_config.h76
-rwxr-xr-xSource/SaWMan/src/sawman_draw.c677
-rwxr-xr-xSource/SaWMan/src/sawman_draw.h55
-rwxr-xr-xSource/SaWMan/src/sawman_internal.h573
12 files changed, 7185 insertions, 0 deletions
diff --git a/Source/SaWMan/src/Makefile.am b/Source/SaWMan/src/Makefile.am
new file mode 100755
index 0000000..7cdfd29
--- /dev/null
+++ b/Source/SaWMan/src/Makefile.am
@@ -0,0 +1,62 @@
+## Makefile.am for SaWMan/src
+
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/src \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src \
+ $(DFB_CFLAGS)
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \
+ -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\" \
+ -DSYSCONFDIR=\"@sysconfdir@\"
+
+
+lib_LTLIBRARIES = libsawman.la
+
+libsawman_la_SOURCES = \
+ isawman.c \
+ isawman.h \
+ isawmanmanager.c \
+ isawmanmanager.h \
+ sawman.c \
+ sawman_internal.h \
+ sawman_draw.c \
+ sawman_draw.h \
+ sawman_config.c \
+ sawman_config.h
+
+libsawman_la_LIBADD = \
+ $(DFB_LIBS)
+
+libsawman_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE)
+
+
+#
+## and now rebuild the static version with the *correct* object files
+#
+if BUILD_STATIC
+
+clean-local:
+ rm -f libsawman_fixed.a
+
+all-local: libsawman_fixed.a
+
+libsawman_fixed.a: .libs/libsawman.a
+ rm -f libsawman_fixed.a
+ ${AR} cru libsawman_fixed.a `find . -name "*.o" | grep -v '.libs'`
+ ${RANLIB} libsawman_fixed.a
+ cp -pf libsawman_fixed.a .libs/libsawman.a
+
+.libs/libsawman.a: libsawman.la
+
+else
+
+clean-local:
+
+all-local:
+
+endif
diff --git a/Source/SaWMan/src/Makefile.in b/Source/SaWMan/src/Makefile.in
new file mode 100755
index 0000000..d03bc58
--- /dev/null
+++ b/Source/SaWMan/src/Makefile.in
@@ -0,0 +1,538 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libsawman_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_libsawman_la_OBJECTS = isawman.lo isawmanmanager.lo sawman.lo \
+ sawman_draw.lo sawman_config.lo
+libsawman_la_OBJECTS = $(am_libsawman_la_OBJECTS)
+libsawman_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libsawman_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libsawman_la_SOURCES)
+DIST_SOURCES = $(libsawman_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DFB_CFLAGS = @DFB_CFLAGS@
+DFB_LIBS = @DFB_LIBS@
+DSYMUTIL = @DSYMUTIL@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+INCLUDEDIR = @INCLUDEDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MODULEDIR = @MODULEDIR@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+RANLIB = @RANLIB@
+SAWMAN_BINARY_AGE = @SAWMAN_BINARY_AGE@
+SAWMAN_INTERFACE_AGE = @SAWMAN_INTERFACE_AGE@
+SAWMAN_MAJOR_VERSION = @SAWMAN_MAJOR_VERSION@
+SAWMAN_MICRO_VERSION = @SAWMAN_MICRO_VERSION@
+SAWMAN_MINOR_VERSION = @SAWMAN_MINOR_VERSION@
+SAWMAN_VERSION = @SAWMAN_VERSION@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/src \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src \
+ $(DFB_CFLAGS)
+
+AM_CPPFLAGS = \
+ -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \
+ -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\" \
+ -DSYSCONFDIR=\"@sysconfdir@\"
+
+lib_LTLIBRARIES = libsawman.la
+libsawman_la_SOURCES = \
+ isawman.c \
+ isawman.h \
+ isawmanmanager.c \
+ isawmanmanager.h \
+ sawman.c \
+ sawman_internal.h \
+ sawman_draw.c \
+ sawman_draw.h \
+ sawman_config.c \
+ sawman_config.h
+
+libsawman_la_LIBADD = \
+ $(DFB_LIBS)
+
+libsawman_la_LDFLAGS = \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libsawman.la: $(libsawman_la_OBJECTS) $(libsawman_la_DEPENDENCIES)
+ $(libsawman_la_LINK) -rpath $(libdir) $(libsawman_la_OBJECTS) $(libsawman_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isawman.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isawmanmanager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sawman.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sawman_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sawman_draw.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) all-local
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am all-local check check-am clean \
+ clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-libLTLIBRARIES
+
+
+#
+#
+
+@BUILD_STATIC_TRUE@clean-local:
+@BUILD_STATIC_TRUE@ rm -f libsawman_fixed.a
+
+@BUILD_STATIC_TRUE@all-local: libsawman_fixed.a
+
+@BUILD_STATIC_TRUE@libsawman_fixed.a: .libs/libsawman.a
+@BUILD_STATIC_TRUE@ rm -f libsawman_fixed.a
+@BUILD_STATIC_TRUE@ ${AR} cru libsawman_fixed.a `find . -name "*.o" | grep -v '.libs'`
+@BUILD_STATIC_TRUE@ ${RANLIB} libsawman_fixed.a
+@BUILD_STATIC_TRUE@ cp -pf libsawman_fixed.a .libs/libsawman.a
+
+@BUILD_STATIC_TRUE@.libs/libsawman.a: libsawman.la
+
+@BUILD_STATIC_FALSE@clean-local:
+
+@BUILD_STATIC_FALSE@all-local:
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/SaWMan/src/isawman.c b/Source/SaWMan/src/isawman.c
new file mode 100755
index 0000000..f241023
--- /dev/null
+++ b/Source/SaWMan/src/isawman.c
@@ -0,0 +1,343 @@
+/*
+ (c) Copyright 2006-2007 directfb.org
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <direct/interface.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include <fusion/fusion.h>
+#include <fusion/shmalloc.h>
+
+#include <sawman.h>
+#include <sawman_internal.h>
+
+#include "isawman.h"
+#include "isawmanmanager.h"
+
+
+static ReactionResult ISaWMan_Tier_Update( const void *msg_data,
+ void *ctx );
+
+/**********************************************************************************************************************/
+
+static void
+ISaWMan_Destruct( ISaWMan *thiz )
+{
+ ISaWMan_data *data = thiz->priv;
+
+ fusion_reactor_detach( ((SaWManTier*) data->sawman->tiers)->reactor, &data->reaction );
+
+ pthread_mutex_destroy( &data->lock );
+ pthread_cond_destroy( &data->cond );
+
+ dfb_updates_deinit( &data->updates );
+
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+}
+
+/**********************************************************************************************************************/
+
+static DirectResult
+ISaWMan_AddRef( ISaWMan *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA( ISaWMan )
+
+ data->ref++;
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWMan_Release( ISaWMan *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA( ISaWMan )
+
+ if (--data->ref == 0)
+ ISaWMan_Destruct( thiz );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+static DirectResult
+ISaWMan_Start( ISaWMan *thiz,
+ const char *name,
+ pid_t *ret_pid )
+{
+ int ret;
+ char *tmp = NULL;
+ SaWMan *sawman;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWMan )
+
+ if (!name)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ ret = sawman_lock( sawman );
+ if (ret)
+ goto out;
+
+ tmp = SHSTRDUP( sawman->shmpool, name );
+ if (!tmp) {
+ ret = D_OOSHM();
+ goto out;
+ }
+
+ ret = sawman_call( sawman, SWMCID_START, tmp );
+ if (ret < 0) {
+ if (ret_pid)
+ *ret_pid = -ret;
+ ret = DFB_OK;
+ }
+
+out:
+ if (tmp)
+ SHFREE( sawman->shmpool, tmp );
+
+ sawman_unlock( sawman );
+
+ return ret;
+}
+
+static DirectResult
+ISaWMan_Stop( ISaWMan *thiz,
+ pid_t pid )
+{
+ DirectResult ret;
+ SaWMan *sawman;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWMan )
+
+ sawman = data->sawman;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ ret = sawman_lock( sawman );
+ if (ret)
+ return ret;
+
+ ret = sawman_call( sawman, SWMCID_STOP, (void*)(long) pid );
+
+ sawman_unlock( sawman );
+
+ return ret;
+}
+
+static DirectResult
+ISaWMan_ReturnKeyEvent( ISaWMan *thiz,
+ DFBWindowEvent *event )
+{
+ DirectResult ret;
+ SaWMan *sawman;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!event)
+ return DFB_INVARG;
+
+ /* Only key events! */
+ if (event->type != DWET_KEYDOWN && event->type != DWET_KEYUP)
+ return DFB_UNSUPPORTED;
+
+ /* Don't return same event twice! 'flags' is only valid for KEY events. */
+ if (event->flags & DWEF_RETURNED)
+ return DFB_LIMITEXCEEDED;
+
+ event->flags |= DWEF_RETURNED;
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ ret = sawman_lock( sawman );
+ if (ret)
+ return ret;
+
+ if (sawman->unselkeys_window)
+ ret = sawman_post_event( sawman, sawman->unselkeys_window, event );
+
+ sawman_unlock( sawman );
+
+ return ret;
+}
+
+static DirectResult
+ISaWMan_CreateManager( ISaWMan *thiz,
+ const SaWManCallbacks *callbacks,
+ void *context,
+ ISaWManManager **ret_manager )
+{
+ DirectResult ret;
+ ISaWManManager *manager;
+ SaWMan *sawman;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWMan )
+
+ if (!callbacks || !ret_manager)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ ret = sawman_lock( sawman );
+ if (ret)
+ return ret;
+
+ ret = sawman_register( sawman, callbacks, context );
+ if (ret)
+ goto out;
+
+ DIRECT_ALLOCATE_INTERFACE( manager, ISaWManManager );
+
+ ret = ISaWManManager_Construct( manager, data->sawman, data->process );
+ if (ret) {
+ /* FIXME: sawman_unregister! */
+ goto out;
+ }
+
+ *ret_manager = manager;
+
+ /*
+ * Attach to existing entities.
+ */
+ if (callbacks->ProcessAdded) {
+ SaWManProcess *process;
+
+ direct_list_foreach (process, sawman->processes) {
+ D_MAGIC_ASSERT( process, SaWManProcess );
+
+ callbacks->ProcessAdded( context, process );
+ }
+ }
+
+ if (callbacks->WindowAdded) {
+ SaWManWindow *window;
+ SaWManWindowInfo *info;
+
+ info = &sawman->callback.info;
+ direct_list_foreach (window, sawman->windows) {
+ D_MAGIC_ASSERT( window, SaWManWindow );
+ info->handle = (SaWManWindowHandle)window;
+ info->caps = window->caps;
+ SAWMANWINDOWCONFIG_COPY( &info->config, &window->window->config )
+
+ callbacks->WindowAdded( context, info );
+ }
+ }
+
+
+out:
+ sawman_unlock( sawman );
+
+ return ret;
+}
+
+static DirectResult
+ISaWMan_GetUpdates( ISaWMan *thiz,
+ DFBWindowStackingClass stacking_class,
+ DFBRegion *ret_updates,
+ unsigned int *ret_num )
+{
+ DIRECT_INTERFACE_GET_DATA( ISaWMan )
+
+ if (!ret_updates || !ret_num)
+ return DFB_INVARG;
+
+ pthread_mutex_lock( &data->lock );
+
+ while (!data->updates.num_regions) {
+ pthread_cond_wait( &data->cond, &data->lock );
+ }
+
+ direct_memcpy( ret_updates, data->updates.regions, sizeof(DFBRegion) * data->updates.num_regions );
+
+ *ret_num = data->updates.num_regions;
+
+ dfb_updates_reset( &data->updates );
+
+ pthread_mutex_unlock( &data->lock );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+ISaWMan_Construct( ISaWMan *thiz,
+ SaWMan *sawman,
+ SaWManProcess *process )
+{
+ DIRECT_ALLOCATE_INTERFACE_DATA( thiz, ISaWMan )
+
+ data->ref = 1;
+ data->sawman = sawman;
+ data->process = process;
+
+ pthread_mutex_init( &data->lock, NULL );
+ pthread_cond_init( &data->cond, NULL );
+
+ dfb_updates_init( &data->updates, data->updates_regions, D_ARRAY_SIZE(data->updates_regions) );
+
+// fusion_reactor_attach_channel( ((SaWManTier*) sawman->tiers->next)->reactor,
+// SAWMAN_TIER_UPDATE, ISaWMan_Tier_Update, data, &data->reaction );
+
+ thiz->AddRef = ISaWMan_AddRef;
+ thiz->Release = ISaWMan_Release;
+ thiz->Start = ISaWMan_Start;
+ thiz->Stop = ISaWMan_Stop;
+ thiz->ReturnKeyEvent = ISaWMan_ReturnKeyEvent;
+ thiz->CreateManager = ISaWMan_CreateManager;
+ thiz->GetUpdates = ISaWMan_GetUpdates;
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+static ReactionResult
+ISaWMan_Tier_Update( const void *msg_data,
+ void *ctx )
+{
+ int i;
+ const SaWManTierUpdate *update = msg_data;
+ ISaWMan_data *data = ctx;
+
+ pthread_mutex_lock( &data->lock );
+
+ for (i=0; i<update->num_regions; i++) {
+ dfb_updates_add( &data->updates, &update->regions[i] );
+ }
+
+ pthread_mutex_unlock( &data->lock );
+
+ pthread_cond_broadcast( &data->cond );
+
+ return RS_OK;
+}
diff --git a/Source/SaWMan/src/isawman.h b/Source/SaWMan/src/isawman.h
new file mode 100755
index 0000000..bf09038
--- /dev/null
+++ b/Source/SaWMan/src/isawman.h
@@ -0,0 +1,61 @@
+/*
+ (c) Copyright 2006-2007 directfb.org
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __ISAWMAN_H__
+#define __ISAWMAN_H__
+
+
+#include <sawman_types.h>
+#include <sawman_internal.h>
+
+#include <directfb_util.h>
+
+#include <pthread.h>
+
+
+/*
+ * private data struct of ISaWMan
+ */
+typedef struct {
+ int ref; /* reference counter */
+ SaWMan *sawman;
+ SaWManProcess *process;
+
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+
+ DFBUpdates updates;
+ DFBRegion updates_regions[SAWMAN_MAX_UPDATE_REGIONS];
+
+ Reaction reaction;
+} ISaWMan_data;
+
+/*
+ * ISaWMan constructor
+ */
+DirectResult ISaWMan_Construct( ISaWMan *thiz,
+ SaWMan *sawman,
+ SaWManProcess *process );
+
+#endif
+
diff --git a/Source/SaWMan/src/isawmanmanager.c b/Source/SaWMan/src/isawmanmanager.c
new file mode 100755
index 0000000..29779d1
--- /dev/null
+++ b/Source/SaWMan/src/isawmanmanager.c
@@ -0,0 +1,718 @@
+/*
+ (c) Copyright 2006-2007 directfb.org
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <directfb_util.h>
+
+#include <direct/interface.h>
+#include <direct/messages.h>
+
+#include <fusion/fusion.h>
+#include <fusion/shmalloc.h>
+
+#include <core/wm.h>
+
+#include <sawman.h>
+#include <sawman_internal.h>
+
+#include "isawmanmanager.h"
+
+
+
+D_DEBUG_DOMAIN( SaWMan_Manager, "SaWMan/Manager", "SaWMan Manager Interface" );
+
+
+static void
+ISaWManManager_Destruct( ISaWManManager *thiz )
+{
+ ISaWManManager_data *data = thiz->priv;
+
+ (void) data;
+
+ DIRECT_DEALLOCATE_INTERFACE( thiz );
+}
+
+
+static DirectResult
+ISaWManManager_AddRef( ISaWManManager *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ data->ref++;
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWManManager_Release( ISaWManManager *thiz )
+{
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (--data->ref == 0)
+ ISaWManManager_Destruct( thiz );
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWManManager_QueueUpdate( ISaWManManager *thiz,
+ DFBWindowStackingClass stacking,
+ const DFBRegion *region )
+{
+ SaWMan *sawman;
+ SaWManTier *tier;
+ DFBRegion update;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!DFB_REGION_CHECK_IF( region ))
+ return DFB_INVAREA;
+
+ switch (stacking) {
+ case DWSC_LOWER:
+ case DWSC_MIDDLE:
+ case DWSC_UPPER:
+ break;
+
+ default:
+ return DFB_INVARG;
+ }
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ tier = sawman_tier_by_class( sawman, stacking );
+
+ update = DFB_REGION_INIT_FROM_DIMENSION( &tier->size );
+
+ if (region && !dfb_region_region_intersect( &update, region ))
+ return DFB_OK;
+
+ dfb_updates_add( &tier->updates, &update );
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWManManager_ProcessUpdates( ISaWManManager *thiz,
+ DFBSurfaceFlipFlags flags )
+{
+ SaWMan *sawman;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ return sawman_process_updates( sawman, flags );
+}
+
+static DirectResult
+ISaWManManager_CloseWindow( ISaWManManager *thiz,
+ SaWManWindowHandle handle )
+{
+ SaWMan *sawman;
+ DFBWindowEvent event;
+ SaWManWindow *window = (SaWManWindow*)handle;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!window)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( window, SaWManWindow );
+
+ event.type = DWET_CLOSE;
+
+ dfb_window_post_event( window->window, &event );
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWManManager_SetVisible( ISaWManManager *thiz,
+ SaWManWindowHandle handle,
+ DFBBoolean visible )
+{
+ SaWMan *sawman;
+ SaWManWindow *window = (SaWManWindow*)handle;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!window)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( window, SaWManWindow );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ D_UNIMPLEMENTED();
+
+ return DFB_UNIMPLEMENTED;// sawman_set_visible( sawman, window );
+}
+
+static DirectResult
+ISaWManManager_SwitchFocus( ISaWManManager *thiz,
+ SaWManWindowHandle handle )
+{
+ SaWMan *sawman;
+ SaWManWindow *window = (SaWManWindow*)handle;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!window)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( window, SaWManWindow );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ return sawman_switch_focus( sawman, window );
+}
+
+static DirectResult
+ISaWManManager_GetSize( ISaWManManager *thiz,
+ DFBWindowStackingClass stacking,
+ DFBDimension *ret_size )
+{
+ SaWMan *sawman;
+ SaWManTier *tier;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ switch (stacking) {
+ case DWSC_LOWER:
+ case DWSC_MIDDLE:
+ case DWSC_UPPER:
+ break;
+
+ default:
+ return DFB_INVARG;
+ }
+
+ if (!ret_size)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ tier = sawman_tier_by_class( sawman, stacking );
+
+ *ret_size = tier->size;
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWManManager_InsertWindow( ISaWManManager *thiz,
+ SaWManWindowHandle handle,
+ SaWManWindowHandle relative,
+ SaWManWindowRelation relation )
+{
+ SaWMan *sawman;
+ SaWManWindow *window = (SaWManWindow*)handle;
+ SaWManWindow *sawrel = (SaWManWindow*)relative;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!window)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( window, SaWManWindow );
+ D_MAGIC_ASSERT_IF( sawrel, SaWManWindow );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ return sawman_insert_window( sawman, window, sawrel,
+ (relation == SWMWR_TOP) ? DFB_TRUE : DFB_FALSE );
+}
+
+static DirectResult
+ISaWManManager_RemoveWindow( ISaWManManager *thiz,
+ SaWManWindowHandle handle )
+{
+ SaWMan *sawman;
+ SaWManWindow *window = (SaWManWindow*)handle;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!window)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( window, SaWManWindow );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ return sawman_remove_window( sawman, window );
+}
+
+static DirectResult
+ISaWManManager_SetScalingMode( ISaWManManager *thiz,
+ SaWManScalingMode mode )
+{
+ SaWMan *sawman;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (mode != SWMSM_STANDARD && mode != SWMSM_SMOOTH_SW)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ if (sawman->scaling_mode != mode) {
+ SaWManTier *tier;
+
+ sawman->scaling_mode = mode;
+
+ direct_list_foreach (tier, sawman->tiers) {
+ DFBRegion update = DFB_REGION_INIT_FROM_DIMENSION( &tier->size );
+
+ dfb_updates_add( &tier->updates, &update );
+ }
+ }
+
+ return DFB_OK;
+}
+
+static void
+reset_geometry_to_nonfollow( SaWManWindow *window )
+{
+ if (window->window->config.dst_geometry.mode == DWGM_FOLLOW)
+ window->window->config.dst_geometry.mode = DWGM_DEFAULT;
+
+ if (window->window->config.src_geometry.mode == DWGM_FOLLOW)
+ window->window->config.src_geometry.mode = DWGM_DEFAULT;
+}
+
+
+static DirectResult
+ISaWManManager_SetWindowConfig ( ISaWManManager *thiz,
+ SaWManWindowHandle handle,
+ SaWManWindowConfigFlags flags,
+ SaWManWindowConfig *config )
+{
+ DFBResult ret;
+ SaWMan *sawman;
+ SaWManWindow *sawwin = (SaWManWindow*)handle;
+ CoreWindow *window;
+
+ /*
+ not yet implemented:
+ SWMCF_KEY_SELECTION
+ */
+
+ if (flags & ~(SWMCF_ALL - SWMCF_KEY_SELECTION))
+ return DFB_INVARG;
+
+ if( config == NULL )
+ return DFB_INVARG;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ window = sawwin->window;
+ D_ASSERT( window != NULL );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ if (flags & CWCF_OPTIONS) {
+ if ((window->config.options & DWOP_SCALE) && !(config->options & DWOP_SCALE) && window->surface) {
+ /* scaling turned off - see if we need to reallocate the surface */
+ if (window->config.bounds.w != window->surface->config.size.w ||
+ window->config.bounds.h != window->surface->config.size.h)
+ {
+ ret = dfb_surface_reformat( window->surface,
+ window->config.bounds.w,
+ window->config.bounds.h,
+ window->surface->config.format );
+ if (ret) {
+ D_DERROR( ret, "WM/SaWMan: Could not resize surface "
+ "(%dx%d -> %dx%d) to remove DWOP_SCALE!\n",
+ window->surface->config.size.w,
+ window->surface->config.size.h,
+ window->config.bounds.w,
+ window->config.bounds.h );
+ return ret;
+ }
+ }
+ }
+
+ if (config->options & (DWOP_KEEP_ABOVE | DWOP_KEEP_UNDER)) {
+ D_ASSERT( sawwin->parent );
+
+ if (config->options & DWOP_KEEP_ABOVE) {
+ D_ASSERT( sawman_window_priority(sawwin->parent) <= sawman_window_priority(sawwin) );
+
+ sawman_insert_window( sawman, sawwin, sawwin->parent, true );
+ }
+ else {
+ D_ASSERT( sawman_window_priority(sawwin->parent) >= sawman_window_priority(sawwin) );
+
+ sawman_insert_window( sawman, sawwin, sawwin->parent, false );
+ }
+
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER | SWMUF_FORCE_COMPLETE );
+ }
+
+ window->config.options = config->options;
+ }
+
+ if (flags & CWCF_EVENTS)
+ window->config.events = config->events;
+
+ if (flags & CWCF_COLOR)
+ window->config.color = config->color;
+
+ if (flags & CWCF_COLOR_KEY)
+ window->config.color_key = config->color_key;
+
+ if (flags & CWCF_OPAQUE)
+ window->config.opaque = config->opaque;
+
+ if (flags & CWCF_STACKING)
+ sawman_restack_window( sawman, sawwin, sawwin, 0, config->stacking );
+
+ if (flags & CWCF_OPACITY)
+ sawman_set_opacity( sawman, sawwin, config->opacity );
+
+ if( flags & (SWMCF_POSITION | SWMCF_SIZE) ) {
+ if( flags == SWMCF_POSITION ) {
+ window->config.bounds.x = config->bounds.x;
+ window->config.bounds.y = config->bounds.y;
+ }
+ else if( flags == SWMCF_SIZE ) {
+ window->config.bounds.w = config->bounds.w;
+ window->config.bounds.h = config->bounds.h;
+ }
+ else
+ window->config.bounds = config->bounds;
+ }
+
+ if (flags & CWCF_SRC_GEOMETRY)
+ window->config.src_geometry = config->src_geometry;
+
+ if (flags & CWCF_DST_GEOMETRY)
+ window->config.dst_geometry = config->dst_geometry;
+
+ if (flags & SWMCF_ASSOCIATION && window->config.association != config->association) {
+ SaWManWindow *parent = sawwin->parent;
+
+ /* Dissociate first */
+ if (sawwin->parent_window) {
+ int index;
+
+ dfb_window_unlink( &sawwin->parent_window );
+
+ index = fusion_vector_index_of( &parent->children, sawwin );
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index < parent->children.count );
+
+ fusion_vector_remove( &parent->children, index );
+
+ sawwin->parent = NULL;
+
+ window->config.association = 0;
+ }
+
+
+
+ /* Lookup new parent window. */
+ if (config->association) {
+ D_DEBUG_AT( SaWMan_Manager, " -> new parent win id %u\n", config->association );
+
+ direct_list_foreach (parent, sawman->windows) {
+ D_MAGIC_ASSERT( parent, SaWManWindow );
+ D_ASSERT( parent->window != NULL );
+
+ if (parent->id == config->association)
+ break;
+ }
+
+ if (!parent) {
+ D_ERROR( "SaWMan/WM: Can't find parent window with ID %d!\n", config->association );
+ reset_geometry_to_nonfollow( sawwin );
+ return DFB_IDNOTFOUND;
+ }
+
+ D_MAGIC_ASSERT( parent, SaWManWindow );
+ D_ASSERT( parent->window != NULL );
+
+ if (parent->window->toplevel != window->toplevel) {
+ D_ERROR( "SaWMan/WM: Can't associate windows with different toplevel!\n" );
+ reset_geometry_to_nonfollow( sawwin );
+ return DFB_INVARG;
+ }
+
+ D_DEBUG_AT( SaWMan_Manager, " -> parent window %p\n", parent );
+
+
+ ret = dfb_window_link( &sawwin->parent_window, parent->window );
+ if (ret) {
+ D_DERROR( ret, "SaWMan/WM: Can't link parent window with ID %d!\n", config->association );
+ reset_geometry_to_nonfollow( sawwin );
+ return ret;
+ }
+
+ ret = fusion_vector_add( &parent->children, sawwin );
+ if (ret) {
+ dfb_window_unlink( &sawwin->parent_window );
+ reset_geometry_to_nonfollow( sawwin );
+ return ret;
+ }
+
+
+ sawwin->parent = parent;
+
+ /* Write back new association */
+ window->config.association = config->association;
+ }
+ else
+ reset_geometry_to_nonfollow( sawwin );
+ }
+
+ if (flags & (CWCF_POSITION | CWCF_SIZE | CWCF_SRC_GEOMETRY | CWCF_DST_GEOMETRY | SWMCF_ASSOCIATION))
+ sawman_update_geometry( sawwin );
+
+ /* Send notification to windows watchers */
+ CoreLayer *layer = dfb_layer_at( sawwin->stack->context->layer_id );
+ dfb_wm_dispatch_WindowConfig( layer->core, window, flags );
+
+ return DFB_OK;
+}
+
+
+
+static DirectResult
+ISaWManManager_SendWindowEvent( ISaWManManager *thiz,
+ SaWManWindowHandle handle,
+ const DFBWindowEvent *event )
+{
+ SaWMan *sawman;
+ SaWManWindow *window = (SaWManWindow*)handle;
+ DFBWindowEvent evt;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!event || (handle == SAWMAN_WINDOW_NONE))
+ return DFB_INVARG;
+
+ /* Only key events! */
+ if (event->type != DWET_KEYDOWN && event->type != DWET_KEYUP)
+ return DFB_UNSUPPORTED;
+
+ /* Don't return same event twice! */
+ if (event->flags & DWEF_RETURNED)
+ return DFB_LIMITEXCEEDED;
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( window, SaWManWindow );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ evt = *event;
+ sawman_post_event( sawman, window, &evt );
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWManManager_Lock( ISaWManManager *thiz )
+{
+ SaWMan *sawman;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ return sawman_lock( sawman );
+}
+
+static DirectResult
+ISaWManManager_Unlock( ISaWManManager *thiz )
+{
+ SaWMan *sawman;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ return sawman_unlock( sawman );
+}
+
+static DirectResult
+ISaWManManager_GetWindowInfo( ISaWManManager *thiz,
+ SaWManWindowHandle handle,
+ SaWManWindowInfo *info )
+{
+ SaWMan *sawman;
+ SaWManWindow *sawwin = (SaWManWindow*)handle;
+ CoreWindow *window;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!info || (handle == SAWMAN_WINDOW_NONE))
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ window = sawwin->window;
+ D_ASSERT( window != NULL );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ info->handle = handle;
+ info->caps = sawwin->caps;
+ SAWMANWINDOWCONFIG_COPY( &info->config, &window->config )
+ info->config.key_selection = window->config.key_selection;
+ info->config.keys = window->config.keys;
+ info->config.num_keys = window->config.num_keys;
+ info->resource_id = window->resource_id;
+ info->win_id = window->id;
+ info->flags = sawwin->flags
+ | (window->flags & CWF_FOCUSED ? SWMWF_FOCUSED : 0)
+ | (window->flags & CWF_ENTERED ? SWMWF_ENTERED : 0);
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWManManager_GetProcessInfo( ISaWManManager *thiz,
+ SaWManWindowHandle handle,
+ SaWManProcess *process )
+{
+ SaWMan *sawman;
+ SaWManWindow *sawwin = (SaWManWindow*)handle;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!process || (handle == SAWMAN_WINDOW_NONE))
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ *process = *sawwin->process;
+
+ return DFB_OK;
+}
+
+static DirectResult
+ISaWManManager_IsWindowShowing( ISaWManManager *thiz,
+ SaWManWindowHandle handle,
+ DFBBoolean *ret_showing )
+{
+ DFBResult ret;
+ bool showing;
+ SaWMan *sawman;
+ SaWManWindow *sawwin = (SaWManWindow*)handle;
+
+ DIRECT_INTERFACE_GET_DATA( ISaWManManager )
+
+ if (!ret_showing)
+ return DFB_INVARG;
+
+ sawman = data->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ ret = sawman_showing_window( sawman, sawwin, &showing );
+ if (ret)
+ return ret;
+
+ *ret_showing = showing ? DFB_TRUE : DFB_FALSE;
+
+ return DFB_OK;
+}
+
+DirectResult
+ISaWManManager_Construct( ISaWManManager *thiz,
+ SaWMan *sawman,
+ SaWManProcess *process )
+{
+ DIRECT_ALLOCATE_INTERFACE_DATA( thiz, ISaWManManager )
+
+ data->ref = 1;
+ data->sawman = sawman;
+ data->process = process;
+
+ thiz->AddRef = ISaWManManager_AddRef;
+ thiz->Release = ISaWManManager_Release;
+ thiz->QueueUpdate = ISaWManManager_QueueUpdate;
+ thiz->ProcessUpdates = ISaWManManager_ProcessUpdates;
+ thiz->CloseWindow = ISaWManManager_CloseWindow;
+ thiz->SetVisible = ISaWManManager_SetVisible;
+ thiz->SwitchFocus = ISaWManManager_SwitchFocus;
+ thiz->GetSize = ISaWManManager_GetSize;
+ thiz->InsertWindow = ISaWManManager_InsertWindow;
+ thiz->RemoveWindow = ISaWManManager_RemoveWindow;
+ thiz->SetScalingMode = ISaWManManager_SetScalingMode;
+ thiz->SetWindowConfig = ISaWManManager_SetWindowConfig;
+ thiz->SendWindowEvent = ISaWManManager_SendWindowEvent;
+ thiz->Lock = ISaWManManager_Lock;
+ thiz->Unlock = ISaWManManager_Unlock;
+ thiz->GetWindowInfo = ISaWManManager_GetWindowInfo;
+ thiz->GetProcessInfo = ISaWManManager_GetProcessInfo;
+ thiz->IsWindowShowing = ISaWManManager_IsWindowShowing;
+
+ return DFB_OK;
+}
diff --git a/Source/SaWMan/src/isawmanmanager.h b/Source/SaWMan/src/isawmanmanager.h
new file mode 100755
index 0000000..67233ec
--- /dev/null
+++ b/Source/SaWMan/src/isawmanmanager.h
@@ -0,0 +1,48 @@
+/*
+ (c) Copyright 2006-2007 directfb.org
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __ISAWMANMANAGER_H__
+#define __ISAWMANMANAGER_H__
+
+
+#include <sawman_types.h>
+
+
+/*
+ * private data struct of ISaWManManager
+ */
+typedef struct {
+ int ref; /* reference counter */
+ SaWMan *sawman;
+ SaWManProcess *process;
+} ISaWManManager_data;
+
+/*
+ * ISaWManManager constructor
+ */
+DirectResult ISaWManManager_Construct( ISaWManManager *thiz,
+ SaWMan *sawman,
+ SaWManProcess *process );
+
+#endif
+
diff --git a/Source/SaWMan/src/sawman.c b/Source/SaWMan/src/sawman.c
new file mode 100755
index 0000000..d2510a7
--- /dev/null
+++ b/Source/SaWMan/src/sawman.c
@@ -0,0 +1,3522 @@
+/*
+ (c) Copyright 2006-2007 directfb.org
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <direct/debug.h>
+#include <direct/direct.h>
+#include <direct/list.h>
+
+#include <fusion/conf.h>
+#include <fusion/fusion.h>
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/layer_context.h>
+#include <core/layer_control.h>
+#include <core/layer_region.h>
+#include <core/palette.h>
+#include <core/screen.h>
+#include <core/windowstack.h>
+#include <core/windows_internal.h>
+#include <core/wm.h>
+
+#include <gfx/clip.h>
+#include <gfx/convert.h>
+#include <gfx/util.h>
+
+#include <misc/conf.h>
+
+#include <sawman.h>
+#include <sawman_internal.h>
+
+#include "sawman_config.h"
+#include "sawman_draw.h"
+
+#include "isawman.h"
+
+
+#ifndef DIRECTFB_PURE_VOODOO
+
+D_DEBUG_DOMAIN( SaWMan_Auto, "SaWMan/Auto", "SaWMan auto configuration" );
+D_DEBUG_DOMAIN( SaWMan_Update, "SaWMan/Update", "SaWMan window manager updates" );
+D_DEBUG_DOMAIN( SaWMan_Geometry, "SaWMan/Geometry", "SaWMan window manager geometry" );
+D_DEBUG_DOMAIN( SaWMan_Stacking, "SaWMan/Stacking", "SaWMan window manager stacking" );
+D_DEBUG_DOMAIN( SaWMan_FlipOnce, "SaWMan/FlipOnce", "SaWMan window manager flip once" );
+D_DEBUG_DOMAIN( SaWMan_Cursor, "SaWMan/Cursor", "SaWMan window manager cursor" );
+D_DEBUG_DOMAIN( SaWMan_Focus, "SaWMan/Focus", "SaWMan window manager focus" );
+
+
+/* FIXME: avoid globals */
+static SaWMan *m_sawman;
+static SaWManProcess *m_process;
+static FusionWorld *m_world;
+
+/**********************************************************************************************************************/
+
+static void wind_of_change ( SaWMan *sawman,
+ SaWManTier *tier,
+ DFBRegion *update,
+ DFBSurfaceFlipFlags flags,
+ int current,
+ int changed );
+
+static void wind_of_showing( SaWMan *sawman,
+ SaWManTier *tier,
+ DFBRegion *update,
+ int current,
+ int changed,
+ bool *ret_showing );
+
+#endif // !DIRECTFB_PURE_VOODOO
+
+/**********************************************************************************************************************/
+
+static DFBResult CreateRemote( const char *host, int session, ISaWMan **ret_sawman );
+
+/**********************************************************************************************************************/
+
+DirectResult
+SaWManInit( int *argc,
+ char ***argv )
+{
+#ifndef DIRECTFB_PURE_VOODOO
+ return sawman_config_init( argc, argv );
+#else
+ return DR_OK;
+#endif
+}
+
+DirectResult
+SaWManCreate( ISaWMan **ret_sawman )
+{
+#ifndef DIRECTFB_PURE_VOODOO
+ DirectResult ret;
+ ISaWMan *sawman;
+#endif
+
+ if (!ret_sawman)
+ return DFB_INVARG;
+
+ direct_initialize();
+
+#ifndef DIRECTFB_PURE_VOODOO
+ if (dfb_config->remote.host)
+ return CreateRemote( dfb_config->remote.host, dfb_config->remote.session, ret_sawman );
+
+ CoreDFB *core;
+
+ dfb_core_create( &core );
+
+ if (!m_sawman) {
+ D_ERROR( "SaWManCreate: No running SaWMan detected! Did you use the 'wm=sawman' option?\n" );
+ return DFB_NOIMPL;
+ }
+
+ D_MAGIC_ASSERT( m_sawman, SaWMan );
+ D_MAGIC_ASSERT( m_process, SaWManProcess );
+
+ DIRECT_ALLOCATE_INTERFACE( sawman, ISaWMan );
+
+ ret = ISaWMan_Construct( sawman, m_sawman, m_process );
+ if (ret)
+ return ret;
+
+ *ret_sawman = sawman;
+
+ return DFB_OK;
+#else
+ return CreateRemote( dfb_config->remote.host ?: "", dfb_config->remote.session, ret_sawman );
+#endif
+}
+
+/**********************************************************************************************************************/
+
+static DFBResult
+CreateRemote( const char *host, int session, ISaWMan **ret_sawman )
+{
+ DFBResult ret;
+ DirectInterfaceFuncs *funcs;
+ void *interface;
+
+ D_ASSERT( host != NULL );
+ D_ASSERT( ret_sawman != NULL );
+
+ ret = DirectGetInterface( &funcs, "ISaWMan", "Requestor", NULL, NULL );
+ if (ret)
+ return ret;
+
+ ret = funcs->Allocate( &interface );
+ if (ret)
+ return ret;
+
+ ret = funcs->Construct( interface, host, session );
+ if (ret)
+ return ret;
+
+ *ret_sawman = interface;
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+#ifndef DIRECTFB_PURE_VOODOO
+
+static DirectResult
+register_process( SaWMan *sawman,
+ SaWManProcessFlags flags,
+ FusionWorld *world )
+{
+ DirectResult ret;
+ SaWManProcess *process;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ /* Allocate process data. */
+ process = SHCALLOC( sawman->shmpool, 1, sizeof(SaWManProcess) );
+ if (!process)
+ return D_OOSHM();
+
+ /* Initialize process data. */
+ process->pid = getpid();
+ process->fusion_id = fusion_id( world );
+ process->flags = flags;
+
+ /* Initialize reference counter. */
+ ret = fusion_ref_init( &process->ref, "SaWMan Process", world );
+ if (ret) {
+ D_DERROR( ret, "SaWMan/Register: fusion_ref_init() failed!\n" );
+ goto error_ref;
+ }
+
+ /* Add a local reference. */
+ ret = fusion_ref_up( &process->ref, false );
+ if (ret) {
+ D_DERROR( ret, "SaWMan/Register: fusion_ref_up() failed!\n" );
+ goto error;
+ }
+
+ /* Set the process watcher on this. */
+ ret = fusion_ref_watch( &process->ref, &sawman->process_watch, process->pid );
+ if (ret) {
+ D_DERROR( ret, "SaWMan/Register: fusion_ref_watch() failed!\n" );
+ goto error;
+ }
+
+ D_MAGIC_SET( process, SaWManProcess );
+
+ /* Add process to list. */
+ direct_list_append( &sawman->processes, &process->link );
+
+ /* Call application manager executable. */
+ sawman_call( sawman, SWMCID_PROCESS_ADDED, process );
+
+ /* Set global singleton. */
+ m_process = process;
+
+ return DFB_OK;
+
+
+error:
+ fusion_ref_destroy( &process->ref );
+
+error_ref:
+ SHFREE( sawman->shmpool, process );
+
+ return ret;
+}
+
+static DirectResult
+unregister_process( SaWMan *sawman,
+ SaWManProcess *process )
+{
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( process, SaWManProcess );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ /* Destroy reference counter. */
+ fusion_ref_destroy( &process->ref );
+
+ /* Remove process from list. */
+ direct_list_remove( &sawman->processes, &process->link );
+
+ /* Unregister manager process? */
+ if (process->flags & SWMPF_MANAGER) {
+ D_ASSERT( sawman->manager.present );
+
+ /* Destroy manager call, unless it was another process. */
+ if (m_process == process)
+ fusion_call_destroy( &sawman->manager.call );
+ else
+ sawman->manager.call.handler = NULL; /* FIXME: avoid failing assertion in fusion_call_init() */
+
+ /* Ready for new manager. */
+ sawman->manager.present = false;
+ }
+ else {
+ /* Call application manager executable. */
+ sawman_call( sawman, SWMCID_PROCESS_REMOVED, process );
+ }
+
+ D_MAGIC_CLEAR( process );
+
+ /* Deallocate process data. */
+ SHFREE( sawman->shmpool, process );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+static FusionCallHandlerResult
+process_watcher( int caller,
+ int call_arg,
+ void *call_ptr,
+ void *ctx,
+ unsigned int serial,
+ int *ret_val )
+{
+ DFBResult ret;
+ SaWMan *sawman = ctx;
+ SaWManProcess *process;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ /* Lookup process by pid. */
+ direct_list_foreach (process, sawman->processes) {
+ D_MAGIC_ASSERT( process, SaWManProcess );
+
+ if (process->pid == call_arg)
+ break;
+ }
+
+ if (!process) {
+ D_BUG( "process with pid %d not found", call_arg );
+ *ret_val = DFB_BUG;
+ return FCHR_RETURN;
+ }
+
+ D_INFO( "SaWMan/Watcher: Process %d [%lu] has exited%s\n", process->pid,
+ process->fusion_id, (process->flags & SWMPF_EXITING) ? "." : " ABNORMALLY!" );
+
+ ret = sawman_lock( sawman );
+ if (ret)
+ D_DERROR( ret, "SaWMan/%s(): sawman_lock() failed!\n", __FUNCTION__ );
+ else {
+ unregister_process( sawman, process );
+
+ sawman_unlock( sawman );
+ }
+
+ return FCHR_RETURN;
+}
+
+static FusionCallHandlerResult
+manager_call_handler( int caller,
+ int call_arg,
+ void *call_ptr,
+ void *ctx,
+ unsigned int serial,
+ int *ret_val )
+{
+ DirectResult ret;
+ SaWMan *sawman = ctx;
+ SaWManCallID call = call_arg;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ /* Last mile of dispatch. */
+ switch (call) {
+ case SWMCID_START:
+ if (sawman->manager.callbacks.Start) {
+ pid_t pid;
+
+ ret = sawman->manager.callbacks.Start( sawman->manager.context, call_ptr, &pid );
+ if (ret)
+ *ret_val = ret;
+ else
+ *ret_val = -pid;
+ }
+ break;
+
+ case SWMCID_STOP:
+ if (sawman->manager.callbacks.Stop)
+ *ret_val = sawman->manager.callbacks.Stop( sawman->manager.context, (long) call_ptr, caller );
+ break;
+
+ case SWMCID_PROCESS_ADDED:
+ if (sawman->manager.callbacks.ProcessAdded)
+ *ret_val = sawman->manager.callbacks.ProcessAdded( sawman->manager.context, call_ptr );
+ break;
+
+ case SWMCID_PROCESS_REMOVED:
+ if (sawman->manager.callbacks.ProcessRemoved)
+ *ret_val = sawman->manager.callbacks.ProcessRemoved( sawman->manager.context, call_ptr );
+ break;
+
+ case SWMCID_INPUT_FILTER:
+ if (sawman->manager.callbacks.InputFilter)
+ *ret_val = sawman->manager.callbacks.InputFilter( sawman->manager.context, call_ptr );
+ break;
+
+ case SWMCID_WINDOW_PRECONFIG:
+ if (sawman->manager.callbacks.WindowPreConfig)
+ *ret_val = sawman->manager.callbacks.WindowPreConfig( sawman->manager.context, call_ptr );
+ break;
+
+ case SWMCID_WINDOW_ADDED:
+ if (sawman->manager.callbacks.WindowAdded)
+ *ret_val = sawman->manager.callbacks.WindowAdded( sawman->manager.context, call_ptr );
+ break;
+
+ case SWMCID_WINDOW_REMOVED:
+ if (sawman->manager.callbacks.WindowRemoved)
+ *ret_val = sawman->manager.callbacks.WindowRemoved( sawman->manager.context, call_ptr );
+ break;
+
+ case SWMCID_WINDOW_RECONFIG:
+ if (sawman->manager.callbacks.WindowReconfig)
+ *ret_val = sawman->manager.callbacks.WindowReconfig( sawman->manager.context, call_ptr );
+ break;
+
+ case SWMCID_WINDOW_RESTACK:
+ if (sawman->manager.callbacks.WindowRestack)
+ *ret_val = sawman->manager.callbacks.WindowRestack( sawman->manager.context,
+ sawman->callback.handle,
+ sawman->callback.relative,
+ (SaWManWindowRelation)call_ptr );
+ break;
+
+ case SWMCID_STACK_RESIZED:
+ if (sawman->manager.callbacks.StackResized)
+ *ret_val = sawman->manager.callbacks.StackResized( sawman->manager.context, call_ptr );
+ break;
+
+ case SWMCID_SWITCH_FOCUS:
+ if (sawman->manager.callbacks.SwitchFocus)
+ *ret_val = sawman->manager.callbacks.SwitchFocus( sawman->manager.context,
+ (SaWManWindowHandle)call_ptr );
+ break;
+
+ case SWMCID_LAYER_RECONFIG:
+ if (sawman->manager.callbacks.LayerReconfig)
+ *ret_val = sawman->manager.callbacks.LayerReconfig( sawman->manager.context, call_ptr );
+ break;
+
+ default:
+ *ret_val = DFB_NOIMPL;
+ }
+
+ return FCHR_RETURN;
+}
+
+/**********************************************************************************************************************/
+/**********************************************************************************************************************/
+
+static DFBResult
+init_hw_cursor( SaWMan *sawman )
+{
+ DFBResult ret;
+
+ sawman->cursor.layer = dfb_layer_at( sawman_config->cursor.layer_id );
+ D_ASSERT( sawman->cursor.layer != NULL );
+
+ ret = dfb_layer_create_context( sawman->cursor.layer, &sawman->cursor.context );
+ if (ret) {
+ D_DERROR( ret, "SaWMan/Cursor: Could not create context at layer (id %u)!\n", sawman_config->cursor.layer_id );
+ return ret;
+ }
+
+ ret = dfb_layer_region_create( sawman->cursor.context, &sawman->cursor.region );
+ if (ret) {
+ D_DERROR( ret, "SaWMan/Cursor: Could not create region at layer (id %u)!\n", sawman_config->cursor.layer_id );
+ dfb_layer_context_unref( sawman->cursor.context );
+ return ret;
+ }
+
+ dfb_layer_activate_context( sawman->cursor.layer, sawman->cursor.context );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+static DirectResult
+add_tier( SaWMan *sawman,
+ FusionWorld *world,
+ DFBDisplayLayerID layer_id,
+ SaWManStackingClasses classes )
+{
+ SaWManTier *tier;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( layer_id >= 0 );
+ D_ASSERT( layer_id < MAX_LAYERS );
+ D_ASSERT( (classes & 7) != 0 );
+ D_ASSERT( (classes & ~7) == 0 );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ direct_list_foreach (tier, sawman->tiers) {
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ if (tier->classes & classes) {
+ D_ERROR( "SaWMan/Tiers: Cannot add tier for layer %d's classes 0x%x which collides with "
+ "layer %d's classes 0x%x!\n", layer_id, classes, tier->layer_id, tier->classes );
+ return DFB_BUSY;
+ }
+
+ if (tier->layer_id == layer_id) {
+ D_ERROR( "SaWMan/Tiers: Cannot add tier with layer %d which is already added!\n", layer_id );
+ return DFB_BUSY;
+ }
+ }
+
+ tier = SHCALLOC( sawman->shmpool, 1, sizeof(SaWManTier) );
+ if (!tier)
+ return D_OOSHM();
+
+ tier->layer_id = layer_id;
+ tier->classes = classes;
+
+ tier->reactor = fusion_reactor_new( 0, "SaWMan Tier", world );
+
+ dfb_updates_init( &tier->updates, tier->update_regions, SAWMAN_MAX_UPDATE_REGIONS );
+
+ D_MAGIC_SET( tier, SaWManTier );
+
+ direct_list_append( &sawman->tiers, &tier->link );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+sawman_initialize( SaWMan *sawman,
+ FusionWorld *world,
+ SaWManProcess **ret_process )
+{
+ int i;
+ DirectResult ret;
+ GraphicsDeviceInfo info;
+
+ D_ASSERT( sawman != NULL );
+ D_ASSERT( world != NULL );
+
+ D_ASSERT( m_sawman == NULL );
+
+ /* Initialize process watcher call. */
+ ret = fusion_call_init( &sawman->process_watch, process_watcher, sawman, world );
+ if (ret)
+ return ret;
+
+ /* Create shared memory pool. */
+ ret = fusion_shm_pool_create( world, "SaWMan Pool", 0x100000, fusion_config->debugshm, &sawman->shmpool );
+ if (ret)
+ goto error;
+
+ /* Initialize lock. */
+ fusion_skirmish_init( &sawman->lock, "SaWMan", world );
+
+ /* Initialize window layout vector. */
+ fusion_vector_init( &sawman->layout, 8, sawman->shmpool );
+
+ /* Default to HW Scaling if supported. */
+ if (dfb_gfxcard_get_device_info( &info ), info.caps.accel & DFXL_STRETCHBLIT)
+ sawman->scaling_mode = SWMSM_STANDARD;
+
+ /* Initialize grabbed keys. */
+ for (i=0; i<SAWMAN_MAX_IMPLICIT_KEYGRABS; i++)
+ sawman->keys[i].code = -1;
+
+ D_MAGIC_SET( sawman, SaWMan );
+
+ sawman_lock( sawman );
+
+ sawman->resolution = sawman_config->resolution;
+
+ /* Initialize tiers. */
+ for (i=0; i<D_ARRAY_SIZE(dfb_config->layers); i++) {
+ if (!dfb_config->layers[i].stacking)
+ continue;
+
+ ret = add_tier( sawman, world, i, dfb_config->layers[i].stacking );
+ if (ret) {
+ sawman_unlock( sawman );
+ D_MAGIC_CLEAR( sawman );
+ goto error;
+ }
+ }
+
+ /* Set global singleton. */
+ m_sawman = sawman;
+ m_world = world;
+
+ /* Register ourself as a new process. */
+ ret = register_process( sawman, SWMPF_MASTER, world );
+ if (ret) {
+ sawman_unlock( sawman );
+ D_MAGIC_CLEAR( sawman );
+ goto error;
+ }
+
+ sawman_unlock( sawman );
+
+ if (ret_process)
+ *ret_process = m_process;
+
+ return DFB_OK;
+
+
+error:
+ if (sawman->tiers) {
+ SaWManTier *tier;
+ DirectLink *next;
+
+ direct_list_foreach_safe (tier, next, sawman->tiers) {
+ D_MAGIC_CLEAR( tier );
+ SHFREE( sawman->shmpool, tier );
+ }
+ }
+
+ fusion_call_destroy( &sawman->process_watch );
+
+ m_sawman = NULL;
+ m_world = NULL;
+ m_process = NULL;
+
+ return ret;
+}
+
+DirectResult
+sawman_post_init( SaWMan *sawman,
+ FusionWorld *world )
+{
+ DFBResult ret;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( world != NULL );
+
+ D_ASSERT( m_sawman == sawman );
+ D_ASSERT( m_world == world );
+ D_MAGIC_ASSERT( m_process, SaWManProcess );
+
+ sawman_lock( sawman );
+
+ /* Initialize HW Cursor? */
+ if (sawman_config->cursor.hw) {
+ ret = init_hw_cursor( sawman );
+ if (ret) {
+ sawman_unlock( sawman );
+ return ret;
+ }
+ }
+
+ sawman_unlock( sawman );
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_join( SaWMan *sawman,
+ FusionWorld *world,
+ SaWManProcess **ret_process )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( world != NULL );
+
+ D_ASSERT( m_sawman == NULL );
+
+ /* Set global singleton. */
+ m_sawman = sawman;
+ m_world = world;
+
+ /* Lock SaWMan. */
+ ret = sawman_lock( sawman );
+ if (ret)
+ goto error;
+
+ /* Register ourself as a new process. */
+ ret = register_process( sawman, SWMPF_NONE, world );
+
+ /* Unlock SaWMan. */
+ sawman_unlock( sawman );
+
+ if (ret)
+ goto error;
+
+ if (ret_process)
+ *ret_process = m_process;
+
+ return DFB_OK;
+
+
+error:
+ m_sawman = NULL;
+ m_world = NULL;
+ m_process = NULL;
+
+ return ret;
+}
+
+DirectResult
+sawman_shutdown( SaWMan *sawman,
+ FusionWorld *world )
+{
+ DirectResult ret;
+ DirectLink *next;
+ SaWManProcess *process;
+ SaWManWindow *sawwin;
+ SaWManGrabbedKey *key;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( world != NULL );
+
+ D_ASSERT( m_sawman == sawman );
+ D_ASSERT( m_world == world );
+
+ D_ASSERT( sawman->processes != NULL );
+ D_ASSERT( sawman->processes->next == NULL );
+
+ process = (SaWManProcess*) sawman->processes;
+
+ D_ASSERT( process == m_process );
+ D_ASSERT( process->fusion_id == fusion_id( world ) );
+
+ /* Lock SaWMan. */
+ ret = sawman_lock( sawman );
+ if (ret)
+ return ret;
+
+ /* Shutdown our own process. */
+ unregister_process( sawman, process );
+
+ /* Clear global singleton. */
+ m_process = NULL;
+
+ /* Destroy process watcher call. */
+ fusion_call_destroy( &sawman->process_watch );
+
+ D_ASSERT( sawman->processes == NULL );
+ D_ASSERT( !sawman->manager.present );
+
+ D_ASSUME( sawman->windows == NULL );
+
+ direct_list_foreach (sawwin, sawman->windows) {
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_ASSERT( sawwin->window != NULL );
+
+ D_WARN( "window %d,%d-%dx%d still there", DFB_RECTANGLE_VALS( &sawwin->bounds ) );
+
+ sawwin->window->stack = NULL;
+ }
+
+ /* FIXME */
+ D_ASSUME( !sawman->windows );
+ D_ASSUME( !sawman->layout.count );
+
+ /* Destroy window layout vector. */
+ fusion_vector_destroy( &sawman->layout );
+
+ /* Destroy lock. */
+ fusion_skirmish_destroy( &sawman->lock );
+
+ /* Free grabbed keys. */
+ direct_list_foreach_safe (key, next, sawman->grabbed_keys) {
+ SHFREE( key->owner->shmpool, key );
+ }
+
+ D_MAGIC_CLEAR( sawman );
+
+ /* Destroy shared memory pool. */
+ fusion_shm_pool_destroy( world, sawman->shmpool );
+
+ /* Clear global singleton. */
+ m_sawman = NULL;
+ m_world = NULL;
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_leave( SaWMan *sawman,
+ FusionWorld *world )
+{
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( world != NULL );
+
+ D_ASSERT( m_sawman == sawman );
+ D_ASSERT( m_world == world );
+ D_MAGIC_ASSERT( m_process, SaWManProcess );
+
+ /* Set 'cleanly exiting' flag. */
+ m_process->flags |= SWMPF_EXITING;
+
+ /* Clear global singletons. */
+ m_sawman = NULL;
+ m_world = NULL;
+ m_process = NULL;
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+sawman_call( SaWMan *sawman,
+ SaWManCallID call,
+ void *ptr )
+{
+ int ret = DFB_FUSION;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ D_ASSERT( m_sawman == sawman );
+
+ /* Check for presence of manager. */
+ if (!sawman->manager.present)
+ return DFB_NOIMPL;
+
+ /* Avoid useless context switches etc. */
+ switch (call) {
+ case SWMCID_START:
+ if (!sawman->manager.callbacks.Start)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_STOP:
+ if (!sawman->manager.callbacks.Stop)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_PROCESS_ADDED:
+ if (!sawman->manager.callbacks.ProcessAdded)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_PROCESS_REMOVED:
+ if (!sawman->manager.callbacks.ProcessRemoved)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_INPUT_FILTER:
+ if (!sawman->manager.callbacks.InputFilter)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_WINDOW_PRECONFIG:
+ if (!sawman->manager.callbacks.WindowPreConfig)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_WINDOW_ADDED:
+ if (!sawman->manager.callbacks.WindowAdded)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_WINDOW_REMOVED:
+ if (!sawman->manager.callbacks.WindowRemoved)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_WINDOW_RECONFIG:
+ if (!sawman->manager.callbacks.WindowReconfig)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_WINDOW_RESTACK:
+ if (!sawman->manager.callbacks.WindowRestack)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_STACK_RESIZED:
+ if (!sawman->manager.callbacks.StackResized)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_SWITCH_FOCUS:
+ if (!sawman->manager.callbacks.SwitchFocus)
+ return DFB_NOIMPL;
+ break;
+
+ case SWMCID_LAYER_RECONFIG:
+ if (!sawman->manager.callbacks.LayerReconfig)
+ return DFB_NOIMPL;
+ break;
+ }
+
+ /* Execute the call in the manager executable. */
+ if (fusion_call_execute( &sawman->manager.call, FCEF_NONE, call, ptr, &ret ))
+ return DFB_NOIMPL;
+
+ return ret;
+}
+
+/**********************************************************************************************************************/
+
+DirectResult
+sawman_register( SaWMan *sawman,
+ const SaWManCallbacks *callbacks,
+ void *context )
+{
+ DirectResult ret;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( callbacks != NULL );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ D_ASSERT( m_sawman == sawman );
+ D_ASSERT( m_world != NULL );
+ D_MAGIC_ASSERT( m_process, SaWManProcess );
+
+ /* Check if another manager already exists. */
+ if (sawman->manager.present)
+ return DFB_BUSY;
+
+ /* Initialize the call to the manager executable (ourself). */
+ ret = fusion_call_init( &sawman->manager.call, manager_call_handler, sawman, m_world );
+ if (ret)
+ return ret;
+
+ /* Initialize manager data. */
+ sawman->manager.callbacks = *callbacks;
+ sawman->manager.context = context;
+
+ /* Set manager flag for our process. */
+ m_process->flags |= SWMPF_MANAGER;
+
+ /* Activate it at last. */
+ sawman->manager.present = true;
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_switch_focus( SaWMan *sawman,
+ SaWManWindow *to )
+{
+ DirectResult ret;
+ DFBWindowEvent evt;
+ SaWManWindow *from;
+
+ D_DEBUG_AT( SaWMan_Focus, "%s( %p, to %p )\n", __FUNCTION__, sawman, to );
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT_IF( to, SaWManWindow );
+
+ from = sawman->focused_window;
+ D_MAGIC_ASSERT_IF( from, SaWManWindow );
+
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ if (from == to)
+ return DFB_OK;
+
+// PR brg36mgr#118432: [550r1ext][Unknown]Directfb changing focuswindow spontaneously.
+// if (to && to->caps & DWCAPS_NOFOCUS)
+ if (to && to->window->caps & DWCAPS_NOFOCUS) {
+ D_DEBUG_AT( SaWMan_Focus, " -> DWCAPS_NOFOCUS, discarding focus switch!\n" );
+
+ return DFB_OK; // PR brg36mgr#118432: [550r1ext][Unknown]Directfb changing focuswindow spontaneously.
+ }
+
+ if (to) {
+ switch (ret = sawman_call( sawman, SWMCID_SWITCH_FOCUS, to )) {
+ case DFB_OK:
+ case DFB_NOIMPL:
+ break;
+
+ default:
+ D_DEBUG_AT( SaWMan_Focus, " -> application manager returned '%s'\n", DirectFBErrorString( ret ) );
+ return ret;
+ }
+ }
+
+ if (from) {
+ D_DEBUG_AT( SaWMan_Focus, " -> removing focus from %p\n", from );
+
+ evt.type = DWET_LOSTFOCUS;
+
+ sawman_post_event( sawman, from, &evt );
+
+ if (sawman_window_border( from ))
+ sawman_update_window( sawman, from, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+ }
+
+ if (to) {
+ CoreWindow *window;
+ CoreLayer *layer;
+
+ window = to->window;
+ D_MAGIC_ASSERT( window, CoreWindow );
+
+ layer = dfb_layer_at( window->stack->context->layer_id );
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ if (window->toplevel) {
+ CoreWindow *toplevel = window->toplevel;
+
+ D_MAGIC_ASSERT( toplevel, CoreWindow );
+
+ toplevel->subfocus = window;
+ }
+ else if (window->subfocus) {
+ window = window->subfocus;
+ D_MAGIC_ASSERT( window, CoreWindow );
+
+ to = window->window_data;
+ D_MAGIC_ASSERT( to, SaWManWindow );
+ }
+#endif
+
+ evt.type = DWET_GOTFOCUS;
+
+ sawman_post_event( sawman, to, &evt );
+
+ if (sawman_window_border( to ))
+ sawman_update_window( sawman, to, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+
+ /* Send notification to windows watchers */
+ dfb_wm_dispatch_WindowFocus( layer->core, to->window );
+ }
+
+ sawman->focused_window = to;
+ sawman->focused_window_switched = true;
+ sawman->focused_window_to = to;
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_post_event( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ DFBWindowEvent *event )
+{
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_ASSERT( sawwin->window != NULL );
+ D_ASSERT( event != NULL );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ event->buttons = sawman->buttons;
+ event->modifiers = sawman->modifiers;
+ event->locks = sawman->locks;
+
+ dfb_window_post_event( sawwin->window, event );
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_update_window( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ const DFBRegion *region,
+ DFBSurfaceFlipFlags flags,
+ SaWManUpdateFlags update_flags )
+{
+ DFBRegion area;
+ CoreWindowStack *stack;
+ CoreWindow *window;
+ SaWManTier *tier;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ DFB_REGION_ASSERT_IF( region );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ stack = sawwin->stack;
+ window = sawwin->window;
+
+ D_ASSERT( stack != NULL );
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ D_DEBUG_AT( SaWMan_Update, "%s( %p, %p )\n", __FUNCTION__, sawwin, region );
+
+ if (!SAWMAN_VISIBLE_WINDOW(window) && !(update_flags & SWMUF_FORCE_INVISIBLE))
+ return DFB_OK;
+
+ D_ASSUME( sawwin->flags & SWMWF_INSERTED );
+
+ /* Make sure window is inserted. */
+ if (!(sawwin->flags & SWMWF_INSERTED)) {
+ D_DEBUG_AT( SaWMan_Update, " -> window %d not inserted!\n", window->id );
+ return DFB_OK;
+ }
+
+ tier = sawman_tier_by_class( sawman, window->config.stacking );
+
+ if (region) {
+ if ((update_flags & SWMUF_SCALE_REGION) && (window->config.options & DWOP_SCALE)) {
+ int sw = sawwin->src.w;
+ int sh = sawwin->src.h;
+ int dw = sawwin->dst.w;
+ int dh = sawwin->dst.h;
+
+ /* horizontal */
+ if (dw > sw) {
+ /* upscaling */
+ area.x1 = (region->x1 - 1) * dw / sw;
+ area.x2 = (region->x2 + 1) * dw / sw;
+ }
+ else {
+ /* downscaling */
+ area.x1 = region->x1 * dw / sw - 1;
+ area.x2 = region->x2 * dw / sw + 1;
+ }
+
+ /* vertical */
+ if (dh > sh) {
+ /* upscaling */
+ area.y1 = (region->y1 - 1) * dh / sh;
+ area.y2 = (region->y2 + 1) * dh / sh;
+ }
+ else {
+ /* downscaling */
+ area.y1 = region->y1 * dh / sh - 1;
+ area.y2 = region->y2 * dh / sh + 1;
+ }
+
+ /* limit to window area */
+ dfb_region_clip( &area, 0, 0, dw - 1, dh - 1 );
+
+ /* screen offset */
+ dfb_region_translate( &area, sawwin->dst.x, sawwin->dst.y );
+ }
+ else
+ area = DFB_REGION_INIT_TRANSLATED( region, sawwin->dst.x, sawwin->dst.y );
+ }
+ else {
+ if ((update_flags & SWMUF_UPDATE_BORDER) && sawman_window_border( sawwin ))
+ area = DFB_REGION_INIT_FROM_RECTANGLE( &sawwin->bounds );
+ else
+ area = DFB_REGION_INIT_FROM_RECTANGLE( &sawwin->dst );
+ }
+
+ if (!dfb_unsafe_region_intersect( &area, 0, 0, tier->size.w - 1, tier->size.h - 1 ))
+ return DFB_OK;
+
+ if (update_flags & SWMUF_FORCE_COMPLETE)
+ dfb_updates_add( &tier->updates, &area );
+ else
+ wind_of_change( sawman, tier, &area, flags,
+ fusion_vector_size( &sawman->layout ) - 1,
+ sawman_window_index( sawman, sawwin ) );
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_showing_window( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ bool *ret_showing )
+{
+ DFBRegion area;
+ CoreWindowStack *stack;
+ CoreWindow *window;
+ SaWManTier *tier;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ stack = sawwin->stack;
+ window = sawwin->window;
+
+ D_ASSERT( stack != NULL );
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ if (!sawman_tier_by_stack( sawman, stack, &tier ))
+ return DFB_BUG;
+
+ *ret_showing = false;
+
+ if (!SAWMAN_VISIBLE_WINDOW(window))
+ return DFB_OK;
+
+ /* Make sure window is inserted. */
+ if (!(sawwin->flags & SWMWF_INSERTED))
+ return DFB_OK;
+
+ area = DFB_REGION_INIT_FROM_RECTANGLE( &sawwin->bounds );
+
+ if (!dfb_unsafe_region_intersect( &area, 0, 0, stack->width - 1, stack->height - 1 ))
+ return DFB_OK;
+
+ if (fusion_vector_has_elements( &sawman->layout ) && window >= 0) {
+ int num = fusion_vector_size( &sawman->layout );
+
+ wind_of_showing( sawman, tier, &area, num - 1,
+ sawman_window_index( sawman, sawwin ), ret_showing );
+ }
+ else
+ *ret_showing = true;
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_insert_window( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ SaWManWindow *relative,
+ bool top )
+{
+ DirectResult ret;
+ int index = 0;
+ SaWManWindow *other;
+ CoreWindow *window;
+ CoreLayer *layer;
+
+ D_DEBUG_AT( SaWMan_Stacking, "%s( %p, %p, %p, %s )\n", __FUNCTION__,
+ sawman, sawwin, relative, top ? "top" : "below" );
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_MAGIC_ASSERT_IF( relative, SaWManWindow );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ layer = dfb_layer_at( window->stack->context->layer_id );
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ /* In case of a sub window, the order from sub window vector is followed */
+ if (window->toplevel) {
+ CoreWindow *toplevel = window->toplevel;
+ CoreWindow *tmp;
+ SaWManWindow *parent;
+
+ /* Enforce association rules... */
+ parent = sawwin->parent;
+ if (parent) {
+ D_MAGIC_ASSERT( parent, SaWManWindow );
+
+ tmp = parent->window;
+ D_ASSERT( tmp != NULL );
+ D_ASSERT( tmp->toplevel == toplevel );
+
+ if (window->config.options & DWOP_KEEP_UNDER) {
+ int under;
+
+ index = fusion_vector_index_of( &toplevel->subwindows, window );
+ under = fusion_vector_index_of( &toplevel->subwindows, parent );
+
+ if (index < under - 1) {
+ D_DEBUG_AT( SaWMan_Stacking, " -> moving under (%d->%d)\n", index, under - 1 );
+
+ fusion_vector_move( &toplevel->subwindows, index, under - 1 );
+ }
+ else if (index > under - 1) {
+ D_DEBUG_AT( SaWMan_Stacking, " -> moving under (%d<-%d)\n", under, index );
+
+ fusion_vector_move( &toplevel->subwindows, index, under );
+ }
+ }
+ else if (window->config.options & DWOP_KEEP_ABOVE) {
+ int above;
+
+ index = fusion_vector_index_of( &toplevel->subwindows, window );
+ above = fusion_vector_index_of( &toplevel->subwindows, parent );
+
+ if (index < above + 1) {
+ D_DEBUG_AT( SaWMan_Stacking, " -> moving above (%d->%d)\n", index, above );
+
+ fusion_vector_move( &toplevel->subwindows, index, above );
+ }
+ else if (index > above + 1) {
+ D_DEBUG_AT( SaWMan_Stacking, " -> moving above (%d<-%d)\n", above + 1, index );
+
+ fusion_vector_move( &toplevel->subwindows, index, above + 1 );
+ }
+ }
+ }
+
+ /* Lookup our index in top level window */
+ index = fusion_vector_index_of( &toplevel->subwindows, window );
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> toplevel %p [%4d,%4d-%4dx%4d] (%d)\n",
+ toplevel, DFB_RECTANGLE_VALS(&toplevel->config.bounds), index );
+
+ /* Get sub window below (or top level) */
+ if (index == 0)
+ tmp = toplevel;
+ else
+ tmp = fusion_vector_at( &toplevel->subwindows, index - 1 );
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> relative %p [%4d,%4d-%4dx%4d] (%d)\n",
+ tmp, DFB_RECTANGLE_VALS(&tmp->config.bounds), index - 1 );
+
+ /* Place on top */
+ relative = tmp->window_data;
+ top = true;
+ }
+ else
+#endif
+ if (sawwin->parent && (window->config.options & (DWOP_KEEP_ABOVE|DWOP_KEEP_UNDER))) {
+ D_MAGIC_ASSERT( sawwin->parent, SaWManWindow );
+
+ relative = sawwin->parent;
+ top = (window->config.options & DWOP_KEEP_ABOVE) ? true : false;
+
+ D_MAGIC_ASSERT( relative, SaWManWindow );
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ if (top && relative->window->subwindows.count) {
+ CoreWindow *tmp;
+
+ tmp = fusion_vector_at( &relative->window->subwindows, relative->window->subwindows.count - 1 );
+ relative = tmp->window_data;
+
+ D_MAGIC_ASSERT( relative, SaWManWindow );
+ }
+#endif
+ }
+
+
+ if (relative)
+ D_ASSUME( relative->priority == sawwin->priority );
+
+ if (relative) {
+ index = sawman_window_index( sawman, relative );
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index < sawman->layout.count );
+
+ if (top)
+ index++;
+ }
+ else if (top) {
+ /*
+ * Iterate from bottom to top,
+ * stopping at the first window with a higher priority.
+ */
+ fusion_vector_foreach (other, index, sawman->layout) {
+ D_MAGIC_ASSERT( other, SaWManWindow );
+
+ if (other->priority > sawwin->priority)
+ break;
+ }
+ }
+ else {
+ /*
+ * Iterate from bottom to top,
+ * stopping at the first window with equal or higher priority.
+ */
+ fusion_vector_foreach (other, index, sawman->layout) {
+ D_MAGIC_ASSERT( other, SaWManWindow );
+
+ if (other->priority >= sawwin->priority)
+ break;
+ }
+ }
+
+ /* (Re)Insert the window at the acquired position. */
+ if (sawwin->flags & SWMWF_INSERTED) {
+ int old = sawman_window_index( sawman, sawwin );
+
+ D_ASSERT( old >= 0 );
+ D_ASSERT( old < sawman->layout.count );
+
+ if (old < index)
+ index--;
+
+ if (old != index) {
+ fusion_vector_move( &sawman->layout, old, index );
+
+ dfb_wm_dispatch_WindowRestack( layer->core, window, index );
+ }
+ }
+ else {
+ ret = fusion_vector_insert( &sawman->layout, sawwin, index );
+ if (ret)
+ return ret;
+
+ dfb_wm_dispatch_WindowRestack( layer->core, window, index );
+
+ /* Set 'inserted' flag. */
+ sawwin->flags |= SWMWF_INSERTED;
+
+ window->flags |= CWF_INSERTED;
+
+ dfb_wm_dispatch_WindowState( layer->core, window );
+ }
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_remove_window( SaWMan *sawman,
+ SaWManWindow *sawwin )
+{
+ int index;
+ CoreWindow *window;
+ SaWManGrabbedKey *key;
+ DirectLink *next;
+ CoreLayer *layer;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ layer = dfb_layer_at( window->stack->context->layer_id );
+
+ if (!(sawwin->flags & SWMWF_INSERTED)) {
+ D_BUG( "window %d not inserted", window->id );
+ return DFB_BUG;
+ }
+
+ sawman_withdraw_window( sawman, sawwin );
+
+ index = sawman_window_index( sawman, sawwin );
+ D_ASSERT( index >= 0 );
+ D_ASSERT( index < sawman->layout.count );
+
+ fusion_vector_remove( &sawman->layout, index );
+
+ /* Release all explicit key grabs. */
+ direct_list_foreach_safe (key, next, sawman->grabbed_keys) {
+ if (key->owner == sawwin) {
+ direct_list_remove( &sawman->grabbed_keys, &key->link );
+ SHFREE( sawwin->shmpool, key );
+ }
+ }
+
+ /* Release grab of unselected keys. */
+ if (sawman->unselkeys_window == sawwin)
+ sawman->unselkeys_window = NULL;
+
+ /* Free key list. */
+ if (window->config.keys) {
+ SHFREE( sawwin->shmpool, window->config.keys );
+
+ window->config.keys = NULL;
+ window->config.num_keys = 0;
+ }
+
+ sawwin->flags &= ~SWMWF_INSERTED;
+
+ window->flags &= ~CWF_INSERTED;
+
+ dfb_wm_dispatch_WindowState( layer->core, window );
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_withdraw_window( SaWMan *sawman,
+ SaWManWindow *sawwin )
+{
+ int i, index;
+ CoreWindow *window;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ /* Make sure window is inserted. */
+ // NDC - remove the if
+ // if (!(sawwin->flags & SWMWF_INSERTED)) {
+ // D_BUG( "window %d not inserted", window->id );
+ // }
+
+ /* No longer be the 'entered window'. */
+ if (sawman->entered_window == sawwin)
+ sawman->entered_window = NULL;
+
+ if (sawman->focused_window_to == sawwin) {
+ sawman->focused_window_to = NULL;
+ sawman->focused_window_switched = false;
+ }
+
+ /* Remove focus from window. */
+ if (sawman->focused_window == sawwin) {
+ SaWManWindow *swin;
+ CoreWindow *cwin;
+
+ sawman_switch_focus( sawman, NULL );
+// sawman->focused_window = NULL;
+
+ /* Always try to have a focused window */
+ fusion_vector_foreach_reverse (swin, index, sawman->layout) {
+ D_MAGIC_ASSERT( swin, SaWManWindow );
+
+ cwin = swin->window;
+ D_ASSERT( cwin != NULL );
+
+ if (swin != sawwin && cwin->config.opacity && !(cwin->config.options & DWOP_GHOST)) {
+ sawman_switch_focus( sawman, swin );
+ break;
+ }
+ }
+ }
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ if (window->toplevel) {
+ CoreWindow *toplevel = window->toplevel;
+
+ D_MAGIC_ASSERT( toplevel, CoreWindow );
+
+ if (toplevel->subfocus == window)
+ toplevel->subfocus = NULL;
+ }
+#endif
+
+ /* Release explicit keyboard grab. */
+ if (sawman->keyboard_window == sawwin)
+ sawman->keyboard_window = NULL;
+
+ /* Release explicit pointer grab. */
+ if (sawman->pointer_window == sawwin)
+ sawman->pointer_window = NULL;
+
+ /* Release all implicit key grabs. */
+ for (i=0; i<SAWMAN_MAX_IMPLICIT_KEYGRABS; i++) {
+ if (sawman->keys[i].code != -1 && sawman->keys[i].owner == sawwin) {
+ if (!DFB_WINDOW_DESTROYED( window )) {
+ DFBWindowEvent we;
+
+ we.type = DWET_KEYUP;
+ we.key_code = sawman->keys[i].code;
+ we.key_id = sawman->keys[i].id;
+ we.key_symbol = sawman->keys[i].symbol;
+
+ sawman_post_event( sawman, sawwin, &we );
+ }
+
+ sawman->keys[i].code = -1;
+ sawman->keys[i].owner = NULL;
+ }
+ }
+
+ /* Hide window. */
+
+ // NDC but don't for SWMWF_INSERTED windows
+ if ((sawwin->flags & SWMWF_INSERTED)) {
+ if (SAWMAN_VISIBLE_WINDOW(window)) {
+ window->config.opacity = 0;
+
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_FORCE_INVISIBLE | SWMUF_UPDATE_BORDER );
+ }
+ }
+ return DFB_OK;
+}
+
+static void
+apply_geometry( const DFBWindowGeometry *geometry,
+ const DFBRegion *clip,
+ const DFBWindowGeometry *parent,
+ DFBRectangle *ret_rect )
+{
+ int width, height;
+
+ D_ASSERT( geometry != NULL );
+ DFB_REGION_ASSERT( clip );
+ D_ASSERT( ret_rect != NULL );
+
+ width = clip->x2 - clip->x1 + 1;
+ height = clip->y2 - clip->y1 + 1;
+
+ switch (geometry->mode) {
+ case DWGM_DEFAULT:
+ D_DEBUG_AT( SaWMan_Geometry, " -- default\n" );
+ *ret_rect = DFB_RECTANGLE_INIT_FROM_REGION( clip );
+ D_DEBUG_AT( SaWMan_Geometry, " => %d,%d-%dx%d\n", DFB_RECTANGLE_VALS( ret_rect ) );
+ return;
+
+ case DWGM_FOLLOW:
+ D_ASSERT( parent != NULL );
+ D_DEBUG_AT( SaWMan_Geometry, " -- FOLLOW\n" );
+ apply_geometry( parent, clip, NULL, ret_rect );
+ break;
+
+ case DWGM_RECTANGLE:
+ D_DEBUG_AT( SaWMan_Geometry, " -- RECTANGLE [%d,%d-%dx%d]\n",
+ DFB_RECTANGLE_VALS( &geometry->rectangle ) );
+ *ret_rect = geometry->rectangle;
+ ret_rect->x += clip->x1;
+ ret_rect->y += clip->y1;
+ break;
+
+ case DWGM_LOCATION:
+ D_DEBUG_AT( SaWMan_Geometry, " -- LOCATION [%.3f,%.3f-%.3fx%.3f]\n",
+ geometry->location.x, geometry->location.y,
+ geometry->location.w, geometry->location.h );
+ ret_rect->x = (int)(geometry->location.x * width + 0.5f) + clip->x1;
+ ret_rect->y = (int)(geometry->location.y * height + 0.5f) + clip->y1;
+ ret_rect->w = (int)(geometry->location.w * width + 0.5f);
+ ret_rect->h = (int)(geometry->location.h * height + 0.5f);
+ break;
+
+ default:
+ D_BUG( "invalid geometry mode %d", geometry->mode );
+ return;
+ }
+
+ D_DEBUG_AT( SaWMan_Geometry, " -> %d,%d-%dx%d / clip [%d,%d-%dx%d]\n",
+ DFB_RECTANGLE_VALS( ret_rect ),
+ DFB_RECTANGLE_VALS_FROM_REGION( clip ) );
+
+ if (!dfb_rectangle_intersect_by_region( ret_rect, clip )) {
+ D_WARN( "invalid geometry" );
+ dfb_rectangle_from_region( ret_rect, clip );
+ }
+
+ D_DEBUG_AT( SaWMan_Geometry, " => %d,%d-%dx%d\n", DFB_RECTANGLE_VALS( ret_rect ) );
+}
+
+DirectResult
+sawman_update_geometry( SaWManWindow *sawwin )
+{
+ int i;
+ CoreWindow *window;
+ CoreWindow *parent_window = NULL;
+ CoreWindow *toplevel;
+ SaWManWindow *topsaw = NULL;
+ SaWMan *sawman;
+ SaWManWindow *parent;
+ SaWManWindow *child;
+ CoreWindow *childwin;
+ DFBRegion clip;
+ DFBRectangle src;
+ DFBRectangle dst;
+ bool src_updated = false;
+ bool dst_updated = false;
+
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ D_DEBUG_AT( SaWMan_Geometry, "%s( %p )\n", __FUNCTION__, sawwin );
+
+ sawman = sawwin->sawman;
+ D_MAGIC_ASSERT_IF( sawman, SaWMan );
+
+ if (sawman)
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ parent = sawwin->parent;
+ if (parent) {
+ D_MAGIC_ASSERT( parent, SaWManWindow );
+
+ parent_window = parent->window;
+ D_ASSERT( parent_window != NULL );
+ }
+
+ toplevel = WINDOW_TOPLEVEL(window);
+ if (toplevel) {
+ topsaw = toplevel->window_data;
+ D_MAGIC_ASSERT( topsaw, SaWManWindow );
+ }
+
+ if (parent && (window->config.options & DWOP_FOLLOW_BOUNDS))
+ /* Initialize bounds from parent window (window association) */
+ sawwin->bounds = parent->bounds;
+ else
+ /* Initialize bounds from base window configuration */
+ sawwin->bounds = window->config.bounds;
+
+ /*
+ * In case of a sub window, the top level surface is the coordinate space instead of the layer surface
+ */
+ toplevel = WINDOW_TOPLEVEL(window);
+ if (toplevel) {
+ DFBDimension in, out;
+
+ D_DEBUG_AT( SaWMan_Geometry, " -> sub bounds %4d,%4d-%4dx%4d (base)\n", DFB_RECTANGLE_VALS(&sawwin->bounds) );
+
+ D_DEBUG_AT( SaWMan_Geometry, " o- top src %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS(&topsaw->src) );
+ D_DEBUG_AT( SaWMan_Geometry, " o- top dst %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS(&topsaw->dst) );
+
+ /*
+ * Translate against top level source geometry
+ */
+ sawwin->bounds.x -= topsaw->src.x;
+ sawwin->bounds.y -= topsaw->src.y;
+
+ D_DEBUG_AT( SaWMan_Geometry, " -> sub bounds %4d,%4d-%4dx%4d (translated)\n", DFB_RECTANGLE_VALS(&sawwin->bounds) );
+
+ /*
+ * Take input dimension from top level source geometry
+ */
+ in.w = topsaw->src.w;
+ in.h = topsaw->src.h;
+
+ /*
+ * Take output dimension from top level destination geometry
+ */
+ out.w = topsaw->dst.w;
+ out.h = topsaw->dst.h;
+
+ /*
+ * Scale the sub window size if top level window is scaled
+ */
+ if (in.w != out.w || in.h != out.h) {
+ D_DEBUG_AT( SaWMan_Geometry, " o- scale in %4dx%4d\n", in.w, in.h );
+ D_DEBUG_AT( SaWMan_Geometry, " o- scale out %4dx%4d\n", out.w, out.h );
+
+ sawwin->bounds.x = sawwin->bounds.x * out.w / in.w;
+ sawwin->bounds.y = sawwin->bounds.y * out.h / in.h;
+ sawwin->bounds.w = sawwin->bounds.w * out.w / in.w;
+ sawwin->bounds.h = sawwin->bounds.h * out.h / in.h;
+
+ D_DEBUG_AT( SaWMan_Geometry, " -> sub bounds %4d,%4d-%4dx%4d (scaled)\n", DFB_RECTANGLE_VALS(&sawwin->bounds) );
+ }
+
+ /*
+ * Translate to top level destination geometry
+ */
+ sawwin->bounds.x += topsaw->dst.x;
+ sawwin->bounds.y += topsaw->dst.y;
+
+ D_DEBUG_AT( SaWMan_Geometry, " => sub bounds %4d,%4d-%4dx%4d (translated)\n", DFB_RECTANGLE_VALS(&sawwin->bounds) );
+ }
+
+ /* Calculate source geometry. */
+ clip.x1 = 0;
+ clip.y1 = 0;
+
+ if ( (window->caps & (DWCAPS_INPUTONLY | DWCAPS_COLOR))
+ || window->config.options & DWOP_INPUTONLY ) {
+ clip.x2 = sawwin->bounds.w - 1;
+ clip.y2 = sawwin->bounds.h - 1;
+ }
+ else {
+ CoreSurface *surface = window->surface;
+ D_ASSERT( surface != NULL );
+
+ clip.x2 = surface->config.size.w - 1;
+ clip.y2 = surface->config.size.h - 1;
+ }
+
+ D_DEBUG_AT( SaWMan_Geometry, " -> Applying source geometry...\n" );
+
+ apply_geometry( &window->config.src_geometry, &clip,
+ parent_window ? &parent_window->config.src_geometry : NULL, &src );
+
+ /* Calculate destination geometry. */
+ clip = DFB_REGION_INIT_FROM_RECTANGLE( &sawwin->bounds );
+
+ D_DEBUG_AT( SaWMan_Geometry, " -> Applying destination geometry...\n" );
+
+ apply_geometry( &window->config.dst_geometry, &clip,
+ parent_window ? &parent_window->config.dst_geometry : NULL, &dst );
+
+ /* Adjust src/dst if clipped by top level window */
+ if (toplevel) {
+ DFBRegion topclip = DFB_REGION_INIT_FROM_RECTANGLE( &topsaw->dst );
+
+ /*
+ * Clip the sub window bounds against the top level window
+ */
+ dfb_clip_stretchblit( &topclip, &src, &dst );
+
+ D_DEBUG_AT( SaWMan_Geometry, " => sub dst %4d,%4d-%4dx%4d (clipped)\n", DFB_RECTANGLE_VALS(&dst) );
+ D_DEBUG_AT( SaWMan_Geometry, " => sub src %4d,%4d-%4dx%4d (clipped)\n", DFB_RECTANGLE_VALS(&src) );
+ }
+
+ /* Update source geometry. */
+ if (!DFB_RECTANGLE_EQUAL( src, sawwin->src )) {
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_NONE );
+
+ sawwin->src = src;
+ src_updated = true;
+ }
+
+ /* Update destination geometry. */
+ if (!DFB_RECTANGLE_EQUAL( dst, sawwin->dst )) {
+ if (!src_updated)
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_NONE );
+
+ sawwin->dst = dst;
+ dst_updated = true;
+
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_NONE );
+ }
+
+ D_DEBUG_AT( SaWMan_Geometry, " -> Updating children (associated windows)...\n" );
+
+ fusion_vector_foreach (child, i, sawwin->children) {
+ D_MAGIC_ASSERT( child, SaWManWindow );
+
+ childwin = child->window;
+ D_ASSERT( childwin != NULL );
+
+ if ((childwin->config.src_geometry.mode == DWGM_FOLLOW && src_updated) ||
+ (childwin->config.dst_geometry.mode == DWGM_FOLLOW && dst_updated) ||
+ (childwin->config.options & DWOP_FOLLOW_BOUNDS))
+ sawman_update_geometry( child );
+ }
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ D_DEBUG_AT( SaWMan_Geometry, " -> Updating children (sub windows)...\n" );
+
+ fusion_vector_foreach (childwin, i, window->subwindows) {
+ D_ASSERT( childwin != NULL );
+
+ sawman_update_geometry( childwin->window_data );
+ }
+#endif
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_set_opacity( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ u8 opacity )
+{
+ u8 old;
+ StackData *data;
+ CoreWindowStack *stack;
+ CoreWindow *window;
+
+ D_DEBUG_AT( SaWMan_Focus, "%s( %p, sawwin %p, opacity 0x%02x )\n", __FUNCTION__, sawman, sawwin, opacity );
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_ASSERT( sawwin->stack_data != NULL );
+ D_ASSERT( sawwin->stack != NULL );
+ D_ASSERT( sawwin->window != NULL );
+
+ data = sawwin->stack_data;
+ stack = sawwin->stack;
+ window = sawwin->window;
+ old = window->config.opacity;
+
+ if (!dfb_config->translucent_windows && opacity) {
+ D_DEBUG_AT( SaWMan_Focus, " -> forcing to 0xff\n" );
+
+ opacity = 0xFF;
+ }
+
+ if (old != opacity) {
+ window->config.opacity = opacity;
+
+ if (sawwin->flags & SWMWF_INSERTED) {
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_FORCE_INVISIBLE | SWMUF_UPDATE_BORDER );
+
+ /* Ungrab pointer/keyboard, pass focus... */
+ if (old && !opacity) {
+ D_DEBUG_AT( SaWMan_Focus, " -> hiding window... (focused %p)\n", sawman->focused_window );
+
+ /* Possibly switch focus to window now under the cursor */
+ if (sawman->focused_window == sawwin) {
+ D_DEBUG_AT( SaWMan_Focus, " -> updating focus\n" );
+
+ sawman_update_focus( data->sawman, data->stack, data->stack->cursor.x, data->stack->cursor.y );
+ }
+
+ D_DEBUG_AT( SaWMan_Focus, " -> withdrawing window...\n" );
+
+ sawman_withdraw_window( sawman, sawwin );
+ }
+ }
+ else
+ D_DEBUG_AT( SaWMan_Focus, " -> not inserted\n" );
+ }
+ else
+ D_DEBUG_AT( SaWMan_Focus, " -> no change\n" );
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_window_set_cursor_flags( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ DFBWindowCursorFlags flags )
+{
+ StackData *data;
+ CoreWindowStack *stack;
+ CoreWindow *window;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_ASSERT( sawwin->stack_data != NULL );
+ D_ASSERT( sawwin->stack != NULL );
+ D_ASSERT( sawwin->window != NULL );
+
+ data = sawwin->stack_data;
+ stack = sawwin->stack;
+ window = sawwin->window;
+
+ if (window->config.cursor_flags != flags) {
+ window->config.cursor_flags = flags;
+
+ if (sawwin == sawman->focused_window)
+ sawman_window_apply_cursor_flags( sawman, sawwin );
+ }
+
+ return DFB_OK;
+}
+
+DirectResult
+sawman_window_apply_cursor_flags( SaWMan *sawman,
+ SaWManWindow *sawwin )
+{
+ StackData *data;
+ CoreWindowStack *stack;
+ CoreWindow *window;
+ CoreCursorUpdateFlags update = CCUF_NONE;
+ u8 opacity;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_ASSERT( sawwin->stack_data != NULL );
+ D_ASSERT( sawwin->stack != NULL );
+ D_ASSERT( sawwin->window != NULL );
+
+ data = sawwin->stack_data;
+ stack = sawwin->stack;
+ window = sawwin->window;
+
+ D_DEBUG_AT( SaWMan_Cursor, "%s( %p, flags 0x%04x )\n", __FUNCTION__, sawwin, window->config.cursor_flags );
+
+ opacity = (window->config.cursor_flags & DWCF_INVISIBLE) ? 0x00 : 0xff;
+
+ D_DEBUG_AT( SaWMan_Cursor, " -> opacity %d\n", opacity );
+
+ if (!(window->config.cursor_flags & DWCF_UNCLIPPED)) {
+ int cx = stack->cursor.x;
+ int cy = stack->cursor.y;
+
+ if (cx < 0)
+ cx = 0;
+ else if (cx >= sawman->resolution.w)
+ cx = sawman->resolution.w - 1;
+
+ if (cy < 0)
+ cy = 0;
+ else if (cy >= sawman->resolution.h)
+ cy = sawman->resolution.h - 1;
+
+ if (cx != stack->cursor.x || cy != stack->cursor.y) {
+ D_DEBUG_AT( SaWMan_Cursor, " -> Cursor clipped %d,%d -> %d,%d\n",
+ stack->cursor.x, stack->cursor.y, cx, cy );
+ printf( "===JK sawman -> Cursor clipped %d,%d -> %d,%d\n",
+ stack->cursor.x, stack->cursor.y, cx, cy );
+
+ stack->cursor.x = cx;
+ stack->cursor.y = cy;
+
+ update |= CCUF_POSITION;
+ }
+ }
+
+ if (stack->cursor.opacity != opacity) {
+ stack->cursor.opacity = opacity;
+
+ update |= CCUF_OPACITY;
+ }
+
+ D_DEBUG_AT( SaWMan_Cursor, " -> update 0x%04x\n", update );
+
+ if (update)
+ dfb_wm_update_cursor( stack, update );
+
+ return DFB_OK;
+}
+
+bool
+sawman_update_focus( SaWMan *sawman,
+ CoreWindowStack *stack,
+ int x,
+ int y )
+{
+ StackData *data;
+
+ D_DEBUG_AT( SaWMan_Focus, "%s( %p, stack %p, xy %d,%d )\n", __FUNCTION__, sawman, stack, x, y );
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( stack != NULL );
+
+ data = stack->stack_data;
+
+ D_MAGIC_ASSERT( data, StackData );
+
+ /* if pointer is not grabbed */
+ if (!sawman->pointer_window) {
+ SaWManWindow *before = sawman->entered_window;
+ SaWManWindow *after = sawman_window_at_pointer( sawman, stack, x, y );
+
+ /* and the window under the cursor is another one now */
+ if (before != after) {
+ DFBWindowEvent we;
+
+ /* send leave event */
+ if (before) {
+ D_MAGIC_ASSERT( before, SaWManWindow );
+ D_ASSERT( before->window != NULL );
+
+ we.type = DWET_LEAVE;
+
+ sawman_window_get_cursor_position( sawman, stack, before, &we.x, &we.y, &we.cx, &we.cy );
+
+ sawman_post_event( sawman, before, &we );
+ }
+
+ /* switch focus and send enter event */
+ sawman_switch_focus( sawman, after );
+
+ if (after) {
+ D_MAGIC_ASSERT( after, SaWManWindow );
+ D_ASSERT( after->window != NULL );
+
+ we.type = DWET_ENTER;
+
+ sawman_window_get_cursor_position( sawman, stack, after, &we.x, &we.y, &we.cx, &we.cy );
+
+ sawman_post_event( sawman, after, &we );
+ }
+
+ /* update pointer to window under the cursor */
+ sawman->entered_window = after;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+DFBResult
+sawman_restack_window( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ SaWManWindow *relative,
+ int relation,
+ DFBWindowStackingClass stacking )
+{
+ int i;
+ int old;
+ int index;
+ int priority;
+ StackData *data;
+ SaWManWindow *tmpsaw;
+ CoreWindow *window;
+ CoreLayer *layer;
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ int n;
+ CoreWindow *tmp;
+#endif
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_MAGIC_ASSERT_IF( relative, SaWManWindow );
+ D_ASSERT( sawwin->stack_data != NULL );
+
+ D_ASSERT( relative == NULL || relative == sawwin || relation != 0);
+
+ D_DEBUG_AT( SaWMan_Stacking, "%s( %p, %p, %p, %d, 0x%d )\n", __FUNCTION__,
+ sawman, sawwin, relative, relation, stacking );
+
+ data = sawwin->stack_data;
+ window = sawwin->window;
+
+ D_ASSERT( window != NULL );
+
+ layer = dfb_layer_at( window->stack->context->layer_id );
+
+ /* Change stacking class. */
+ if (stacking != window->config.stacking) {
+ window->config.stacking = stacking;
+
+ sawwin->priority = sawman_window_priority( sawwin );
+ }
+
+ /* Make sure window is inserted and not kept above/under parent. */
+ if (!(sawwin->flags & SWMWF_INSERTED) || (window->config.options & (DWOP_KEEP_ABOVE|DWOP_KEEP_UNDER)))
+ return DFB_OK;
+
+ /* Get the (new) priority. */
+ priority = sawwin->priority;
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ /* In case of a sub window, the sub window vector is modified and the window reinserted */
+ if (window->toplevel) {
+ CoreWindow *toplevel = window->toplevel;
+
+ /* Get the old index. */
+ old = fusion_vector_index_of( &toplevel->subwindows, window );
+ D_ASSERT( old >= 0 );
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> old sub index %d\n", old );
+
+ /* Calculate the desired index. */
+ if (relative) {
+ index = fusion_vector_index_of( &toplevel->subwindows, relative->window );
+ if (index < 0)
+ return DFB_INVARG;
+
+ if (relation > 0) {
+ if (old < index)
+ index--;
+ }
+ else if (relation < 0) {
+ if (old > index)
+ index++;
+ }
+
+ index += relation;
+
+ if (index < 0)
+ index = 0;
+ else if (index > toplevel->subwindows.count - 1)
+ index = toplevel->subwindows.count - 1;
+ }
+ else if (relation)
+ index = toplevel->subwindows.count - 1;
+ else
+ index = 0;
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> new sub index %d\n", index );
+
+ if (relation < 0) {
+ while (index > 0) {
+ SaWManWindow *other = fusion_vector_at( &toplevel->subwindows, index );
+ SaWManWindow *under = fusion_vector_at( &toplevel->subwindows, index - 1 );
+
+ D_MAGIC_ASSERT( other, SaWManWindow );
+ D_MAGIC_ASSERT( under, SaWManWindow );
+
+ if ((other->window->config.options & DWOP_KEEP_ABOVE) ||
+ (under->window->config.options & DWOP_KEEP_UNDER))
+ index--;
+ else
+ break;
+ }
+ }
+ else if (relation > 0) {
+ while (index < toplevel->subwindows.count - 1) {
+ SaWManWindow *other = fusion_vector_at( &toplevel->subwindows, index );
+ SaWManWindow *above = fusion_vector_at( &toplevel->subwindows, index + 1 );
+
+ D_MAGIC_ASSERT( other, SaWManWindow );
+ D_MAGIC_ASSERT( above, SaWManWindow );
+
+ if ((above->window->config.options & DWOP_KEEP_ABOVE) ||
+ (other->window->config.options & DWOP_KEEP_UNDER))
+ index++;
+ else
+ break;
+ }
+ }
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> new sub index %d\n", index );
+
+ /* Return if index hasn't changed. */
+ if (index == old)
+ return DFB_OK;
+
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+
+ /* Actually change the stacking order now. */
+ fusion_vector_move( &toplevel->subwindows, old, index );
+
+ /* Reinsert to move in layout as well. */
+ sawman_insert_window( sawman, sawwin, NULL, false );
+
+ /* Reinsert associated windows to ensure above/under rules apply. */
+ fusion_vector_foreach (tmpsaw, i, sawwin->children) {
+ if (tmpsaw->window->config.options & (DWOP_KEEP_ABOVE|DWOP_KEEP_UNDER)) {
+ sawman_update_window( sawman, tmpsaw, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+ sawman_insert_window( sawman, tmpsaw, NULL, false );
+ sawman_update_window( sawman, tmpsaw, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+ }
+ }
+ }
+ else
+#endif
+ {
+ /* Get the old index. */
+ old = sawman_window_index( sawman, sawwin );
+ D_ASSERT( old >= 0 );
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> old index %d\n", old );
+
+ /* Calculate the desired index. */
+ if (relative) {
+ index = sawman_window_index( sawman, relative );
+
+ if (relation > 0) {
+ if (old < index)
+ index--;
+ }
+ else if (relation < 0) {
+ if (old > index)
+ index++;
+ }
+
+ index += relation;
+
+ if (relation > 0)
+ index += WINDOW_SUBWINDOWS_COUNT(window);
+
+ if (index < 0)
+ index = 0;
+ else if (index > sawman->layout.count - 1)
+ index = sawman->layout.count - 1;
+ }
+ else if (relation)
+ index = sawman->layout.count - 1;
+ else
+ index = 0;
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> new index %d\n", index );
+
+ /* Assure window won't be above any window with a higher priority. */
+ while (index > 0) {
+ int below = (old < index) ? index : index - 1;
+ SaWManWindow *other = fusion_vector_at( &sawman->layout, below );
+
+ D_MAGIC_ASSERT( other, SaWManWindow );
+
+ if (priority < other->priority)
+ index--;
+ else
+ break;
+ }
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> new index %d\n", index );
+
+ /* Assure window won't be below any window with a lower priority. */
+ while (index < sawman->layout.count - 1) {
+ int above = (old > index) ? index : index + 1;
+ SaWManWindow *other = fusion_vector_at( &sawman->layout, above );
+
+ D_MAGIC_ASSERT( other, SaWManWindow );
+
+ if (priority > other->priority)
+ index++;
+ else
+ break;
+ }
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> new index %d\n", index );
+
+ if (relation < 0) {
+ /* Assure window won't be below a sub window (getting between sub and top or other sub window) */
+ while (index > 0) {
+ SaWManWindow *other = fusion_vector_at( &sawman->layout, index );
+ SaWManWindow *under = fusion_vector_at( &sawman->layout, index - 1 );
+
+ D_MAGIC_ASSERT( other, SaWManWindow );
+ D_MAGIC_ASSERT( under, SaWManWindow );
+
+ if (WINDOW_TOPLEVEL(other->window) ||
+ (other->window->config.options & DWOP_KEEP_ABOVE) ||
+ (under->window->config.options & DWOP_KEEP_UNDER))
+ index--;
+ else
+ break;
+ }
+ }
+ else if (relation > 0) {
+ /* Assure window won't be below a sub window (getting between sub and top or other sub window) */
+ while (index < sawman->layout.count - 1) {
+ SaWManWindow *other = fusion_vector_at( &sawman->layout, index );
+ SaWManWindow *above = fusion_vector_at( &sawman->layout, index + 1 );
+
+ D_MAGIC_ASSERT( other, SaWManWindow );
+ D_MAGIC_ASSERT( above, SaWManWindow );
+
+ if (WINDOW_TOPLEVEL(above->window) ||
+ (above->window->config.options & DWOP_KEEP_ABOVE) ||
+ (other->window->config.options & DWOP_KEEP_UNDER))
+ index++;
+ else
+ break;
+ }
+ }
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> new index %d\n", index );
+
+ /* Return if index hasn't changed. */
+ if (index == old)
+ return DFB_OK;
+
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+
+ /* Actually change the stacking order now. */
+ fusion_vector_move( &sawman->layout, old, index );
+
+ D_DEBUG_AT( SaWMan_Stacking, " -> now index %d\n", fusion_vector_index_of( &sawman->layout, sawwin ) );
+
+ dfb_wm_dispatch_WindowRestack( layer->core, window, index );
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ /* Reinsert sub windows to ensure they're in order (above top level). */
+ fusion_vector_foreach (tmp, i, window->subwindows) {
+ sawman_update_window( sawman, tmp->window_data, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+ sawman_insert_window( sawman, tmp->window_data, NULL, false );
+ sawman_update_window( sawman, tmp->window_data, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+ }
+#endif
+
+ /* Reinsert associated windows to ensure above/under rules apply. */
+ fusion_vector_foreach (tmpsaw, i, sawwin->children) {
+ if (tmpsaw->window->config.options & (DWOP_KEEP_ABOVE|DWOP_KEEP_UNDER)) {
+ sawman_update_window( sawman, tmpsaw, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+ sawman_insert_window( sawman, tmpsaw, NULL, false );
+ sawman_update_window( sawman, tmpsaw, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+
+#ifndef OLD_COREWINDOWS_STRUCTURE
+ /* Reinsert sub windows to ensure they're in order (above top level). */
+ fusion_vector_foreach (tmp, n, tmpsaw->window->subwindows) {
+ sawman_update_window( sawman, tmp->window_data, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+ sawman_insert_window( sawman, tmp->window_data, NULL, false );
+ sawman_update_window( sawman, tmp->window_data, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+ }
+#endif
+ }
+ }
+ }
+
+ sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER );
+
+ return DFB_OK;
+}
+
+
+SaWManWindow*
+sawman_window_at_pointer( SaWMan *sawman,
+ CoreWindowStack *stack,
+ int x,
+ int y )
+{
+ int i;
+ SaWManWindow *sawwin;
+ CoreWindow *window;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( stack != NULL );
+
+ if (!stack->cursor.enabled) {
+ fusion_vector_foreach_reverse (sawwin, i, sawman->layout) {
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ window = sawwin->window;
+ D_ASSERT( window != NULL );
+
+ if (window->config.opacity && !(window->config.options & DWOP_GHOST))
+ return sawwin;
+ }
+
+ return NULL;
+ }
+
+ if (x < 0)
+ x = stack->cursor.x;
+ if (y < 0)
+ y = stack->cursor.y;
+
+ fusion_vector_foreach_reverse (sawwin, i, sawman->layout) {
+ SaWManTier *tier;
+ int tx, ty;
+
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ window = sawwin->window;
+ D_ASSERT( window != NULL );
+
+ /* Retrieve corresponding SaWManTier. */
+ tier = sawman_tier_by_class( sawman, sawwin->window->config.stacking );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ /* Convert to Tier coordinates */
+ tx = (s64) x * (s64) tier->size.w / (s64) sawman->resolution.w;
+ ty = (s64) y * (s64) tier->size.h / (s64) sawman->resolution.h;
+
+ if (!(window->config.options & DWOP_GHOST) && window->config.opacity &&
+ tx >= sawwin->bounds.x && tx < sawwin->bounds.x + sawwin->bounds.w &&
+ ty >= sawwin->bounds.y && ty < sawwin->bounds.y + sawwin->bounds.h)
+ return sawwin;
+ }
+
+ return NULL;
+}
+
+void
+sawman_window_get_cursor_position( SaWMan *sawman,
+ CoreWindowStack *stack,
+ SaWManWindow *sawwin,
+ int *ret_x,
+ int *ret_y,
+ int *ret_cx,
+ int *ret_cy )
+{
+ int x, y;
+ int cx, cy;
+ int sx, sy;
+ SaWManTier *tier;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( stack != NULL );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_ASSERT( sawwin->window != NULL );
+
+ /* Retrieve corresponding SaWManTier. */
+ tier = sawman_tier_by_class( sawman, sawwin->window->config.stacking );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ x = stack->cursor.x;
+ y = stack->cursor.y;
+
+ /* Convert to Tier coordinates */
+ cx = (s64) x * (s64) tier->size.w / (s64) sawman->resolution.w;
+ cy = (s64) y * (s64) tier->size.h / (s64) sawman->resolution.h;
+
+ /* Subtract offset of Window within layout (tier coordinates) */
+ x = cx - sawwin->dst.x;
+ y = cy - sawwin->dst.y;
+
+ /* Convert to Window coordinates */
+ sx = sawwin->window->config.cursor_resolution.w ?: sawwin->src.w;
+ sy = sawwin->window->config.cursor_resolution.h ?: sawwin->src.h;
+
+ x = x * sx / sawwin->dst.w;
+ y = y * sy / sawwin->dst.h;
+
+ cx = cx * sx / sawwin->dst.w;
+ cy = cy * sy / sawwin->dst.h;
+
+ if (ret_x)
+ *ret_x = x;
+
+ if (ret_y)
+ *ret_y = y;
+
+ if (ret_cx)
+ *ret_cx = cx;
+
+ if (ret_cy)
+ *ret_cy = cy;
+
+ D_INFO( "%d,%d - %d,%d\n",x,y,cx,cy);
+}
+
+int
+sawman_window_border( const SaWManWindow *sawwin )
+{
+ SaWMan *sawman;
+ const CoreWindow *window;
+ const SaWManTier *tier;
+ const SaWManBorderInit *border;
+ int thickness = 0;
+
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ sawman = sawwin->sawman;
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ if (sawwin->caps & DWCAPS_NODECORATION)
+ return 0;
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ tier = sawman_tier_by_class( sawwin->sawman, window->config.stacking );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ D_ASSERT( sawman_config != NULL );
+
+ border = &sawman_config->borders[sawman_window_priority(sawwin)];
+
+ thickness = border->thickness;
+ if (thickness && border->resolution.w && border->resolution.h) {
+ if (border->resolution.w != tier->size.w && border->resolution.h != tier->size.h) {
+ int tw = thickness * tier->size.w / border->resolution.w;
+ int th = thickness * tier->size.h / border->resolution.h;
+
+ thickness = (tw + th + 1) / 2;
+ }
+ }
+
+ return thickness;
+}
+
+/**********************************************************************************************************************/
+
+/*
+ skipping opaque windows that are above the window that changed
+*/
+static void
+wind_of_change( SaWMan *sawman,
+ SaWManTier *tier,
+ DFBRegion *update,
+ DFBSurfaceFlipFlags flags,
+ int current,
+ int changed )
+{
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+ D_ASSERT( update != NULL );
+
+ /*
+ loop through windows above
+ */
+ for (; current > changed; current--) {
+ CoreWindow *window;
+ SaWManWindow *sawwin;
+ DFBRegion opaque;
+ DFBWindowOptions options;
+
+ D_ASSERT( changed >= 0 );
+ D_ASSERT( current >= changed );
+ D_ASSERT( current < fusion_vector_size( &sawman->layout ) );
+
+ sawwin = fusion_vector_at( &sawman->layout, current );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ options = window->config.options;
+
+ D_DEBUG_AT( SaWMan_Update, "--[%p] %4d,%4d-%4dx%4d : %d->%d\n",
+ tier, DFB_RECTANGLE_VALS_FROM_REGION( update ), current, changed );
+
+ /*
+ can skip opaque region
+ */
+ if ((tier->classes & (1 << window->config.stacking)) && ( (
+ //can skip all opaque window?
+ (window->config.opacity == 0xff) &&
+ !(window->caps & DWCAPS_INPUTONLY) &&
+ !(options & (DWOP_INPUTONLY | DWOP_COLORKEYING | DWOP_ALPHACHANNEL)) &&
+ (opaque=*update,dfb_region_intersect( &opaque,
+ sawwin->dst.x, sawwin->dst.y,
+ sawwin->dst.x + sawwin->dst.w - 1,
+ sawwin->dst.y + sawwin->dst.h - 1 ) )
+ )||(
+ //can skip opaque region?
+ (options & DWOP_ALPHACHANNEL) &&
+ (options & DWOP_OPAQUE_REGION) &&
+ (window->config.opacity == 0xff) &&
+ !(options & DWOP_COLORKEYING) &&
+ (opaque=*update,dfb_region_intersect( &opaque, /* FIXME: Scaling */
+ sawwin->dst.x + window->config.opaque.x1,
+ sawwin->dst.y + window->config.opaque.y1,
+ sawwin->dst.x + window->config.opaque.x2,
+ sawwin->dst.y + window->config.opaque.y2 ))
+ ) ))
+ {
+ /* left */
+ if (opaque.x1 != update->x1) {
+ DFBRegion left = { update->x1, opaque.y1, opaque.x1-1, opaque.y2};
+ wind_of_change( sawman, tier, &left, flags, current-1, changed );
+ }
+ /* upper */
+ if (opaque.y1 != update->y1) {
+ DFBRegion upper = { update->x1, update->y1, update->x2, opaque.y1-1};
+ wind_of_change( sawman, tier, &upper, flags, current-1, changed );
+ }
+ /* right */
+ if (opaque.x2 != update->x2) {
+ DFBRegion right = { opaque.x2+1, opaque.y1, update->x2, opaque.y2};
+ wind_of_change( sawman, tier, &right, flags, current-1, changed );
+ }
+ /* lower */
+ if (opaque.y2 != update->y2) {
+ DFBRegion lower = { update->x1, opaque.y2+1, update->x2, update->y2};
+ wind_of_change( sawman, tier, &lower, flags, current-1, changed );
+ }
+
+ return;
+ }
+ }
+
+ D_DEBUG_AT( SaWMan_Update, "+ UPDATE %4d,%4d-%4dx%4d\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( update ) );
+
+ dfb_updates_add( &tier->updates, update );
+}
+
+static void
+wind_of_showing( SaWMan *sawman,
+ SaWManTier *tier,
+ DFBRegion *update,
+ int current,
+ int changed,
+ bool *ret_showing )
+{
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+ D_ASSERT( update != NULL );
+
+ if (*ret_showing)
+ return;
+
+ /*
+ loop through windows above
+ */
+ for (; current > changed; current--) {
+ CoreWindow *window;
+ SaWManWindow *sawwin;
+ DFBRegion opaque;
+ DFBWindowOptions options;
+
+ D_ASSERT( changed >= 0 );
+ D_ASSERT( current >= changed );
+ D_ASSERT( current < fusion_vector_size( &sawman->layout ) );
+
+ sawwin = fusion_vector_at( &sawman->layout, current );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ options = window->config.options;
+
+ /*
+ can skip opaque region
+ */
+ if ((tier->classes & (1 << window->config.stacking)) && ( (
+ //can skip all opaque window?
+ (window->config.opacity == 0xff) &&
+ !(options & (DWOP_COLORKEYING | DWOP_ALPHACHANNEL)) &&
+ (opaque=*update,dfb_region_intersect( &opaque,
+ sawwin->dst.x, sawwin->dst.y,
+ sawwin->dst.x + sawwin->dst.w - 1,
+ sawwin->dst.y + sawwin->dst.h - 1 ) )
+ )||(
+ //can skip opaque region?
+ (options & DWOP_ALPHACHANNEL) &&
+ (options & DWOP_OPAQUE_REGION) &&
+ (window->config.opacity == 0xff) &&
+ !(options & DWOP_COLORKEYING) &&
+ (opaque=*update,dfb_region_intersect( &opaque, /* FIXME: Scaling */
+ sawwin->dst.x + window->config.opaque.x1,
+ sawwin->dst.y + window->config.opaque.y1,
+ sawwin->dst.x + window->config.opaque.x2,
+ sawwin->dst.y + window->config.opaque.y2 ))
+ ) ))
+ {
+ /* left */
+ if (opaque.x1 != update->x1) {
+ DFBRegion left = { update->x1, opaque.y1, opaque.x1-1, opaque.y2};
+ wind_of_showing( sawman, tier, &left, current-1, changed, ret_showing );
+ }
+ /* upper */
+ if (opaque.y1 != update->y1) {
+ DFBRegion upper = { update->x1, update->y1, update->x2, opaque.y1-1};
+ wind_of_showing( sawman, tier, &upper, current-1, changed, ret_showing );
+ }
+ /* right */
+ if (opaque.x2 != update->x2) {
+ DFBRegion right = { opaque.x2+1, opaque.y1, update->x2, opaque.y2};
+ wind_of_showing( sawman, tier, &right, current-1, changed, ret_showing );
+ }
+ /* lower */
+ if (opaque.y2 != update->y2) {
+ DFBRegion lower = { update->x1, opaque.y2+1, update->x2, update->y2};
+ wind_of_showing( sawman, tier, &lower, current-1, changed, ret_showing );
+ }
+
+ return;
+ }
+ }
+
+ *ret_showing = true;
+}
+
+static void
+update_region( SaWMan *sawman,
+ SaWManTier *tier,
+ CardState *state,
+ int start,
+ int x1,
+ int y1,
+ int x2,
+ int y2 )
+{
+ int i = start;
+ DFBRegion region = { x1, y1, x2, y2 };
+ CoreWindow *window = NULL;
+ SaWManWindow *sawwin = NULL;
+
+ D_DEBUG_AT( SaWMan_Update, "%s( %p, %d, %d,%d - %d,%d )\n", __FUNCTION__, tier, start, x1, y1, x2, y2 );
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+ D_MAGIC_ASSERT( state, CardState );
+ D_ASSERT( start < fusion_vector_size( &sawman->layout ) );
+ D_ASSUME( x1 <= x2 );
+ D_ASSUME( y1 <= y2 );
+
+ if (x1 > x2 || y1 > y2)
+ return;
+
+ /* Find next intersecting window. */
+ while (i >= 0) {
+ sawwin = fusion_vector_at( &sawman->layout, i );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ if (SAWMAN_VISIBLE_WINDOW( window ) && (tier->classes & (1 << window->config.stacking))) {
+ if (dfb_region_intersect( &region,
+ DFB_REGION_VALS_FROM_RECTANGLE( &sawwin->bounds )))
+ break;
+ }
+
+ i--;
+ }
+
+ /* Intersecting window found? */
+ if (i >= 0) {
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ if (D_FLAGS_ARE_SET( window->config.options, DWOP_ALPHACHANNEL | DWOP_OPAQUE_REGION )) {
+ DFBRegion opaque = DFB_REGION_INIT_TRANSLATED( &window->config.opaque,
+ sawwin->bounds.x,
+ sawwin->bounds.y );
+
+ if (!dfb_region_region_intersect( &opaque, &region )) {
+ update_region( sawman, tier, state, i-1, x1, y1, x2, y2 );
+
+ sawman_draw_window( tier, sawwin, state, &region, true );
+ }
+ else {
+ if ((window->config.opacity < 0xff) || (window->config.options & DWOP_COLORKEYING)) {
+ /* draw everything below */
+ update_region( sawman, tier, state, i-1, x1, y1, x2, y2 );
+ }
+ else {
+ /* left */
+ if (opaque.x1 != x1)
+ update_region( sawman, tier, state, i-1, x1, opaque.y1, opaque.x1-1, opaque.y2 );
+
+ /* upper */
+ if (opaque.y1 != y1)
+ update_region( sawman, tier, state, i-1, x1, y1, x2, opaque.y1-1 );
+
+ /* right */
+ if (opaque.x2 != x2)
+ update_region( sawman, tier, state, i-1, opaque.x2+1, opaque.y1, x2, opaque.y2 );
+
+ /* lower */
+ if (opaque.y2 != y2)
+ update_region( sawman, tier, state, i-1, x1, opaque.y2+1, x2, y2 );
+ }
+
+ /* left */
+ if (opaque.x1 != region.x1) {
+ DFBRegion r = { region.x1, opaque.y1, opaque.x1 - 1, opaque.y2 };
+ sawman_draw_window( tier, sawwin, state, &r, true );
+ }
+
+ /* upper */
+ if (opaque.y1 != region.y1) {
+ DFBRegion r = { region.x1, region.y1, region.x2, opaque.y1 - 1 };
+ sawman_draw_window( tier, sawwin, state, &r, true );
+ }
+
+ /* right */
+ if (opaque.x2 != region.x2) {
+ DFBRegion r = { opaque.x2 + 1, opaque.y1, region.x2, opaque.y2 };
+ sawman_draw_window( tier, sawwin, state, &r, true );
+ }
+
+ /* lower */
+ if (opaque.y2 != region.y2) {
+ DFBRegion r = { region.x1, opaque.y2 + 1, region.x2, region.y2 };
+ sawman_draw_window( tier, sawwin, state, &r, true );
+ }
+
+ /* inner */
+ sawman_draw_window( tier, sawwin, state, &opaque, false );
+ }
+ }
+ else {
+ if (SAWMAN_TRANSLUCENT_WINDOW( window )) {
+ /* draw everything below */
+ update_region( sawman, tier, state, i-1, x1, y1, x2, y2 );
+ }
+ else {
+ DFBRegion dst = DFB_REGION_INIT_FROM_RECTANGLE( &sawwin->dst );
+
+ dfb_region_region_intersect( &dst, &region );
+
+ /* left */
+ if (dst.x1 != x1)
+ update_region( sawman, tier, state, i-1, x1, dst.y1, dst.x1-1, dst.y2 );
+
+ /* upper */
+ if (dst.y1 != y1)
+ update_region( sawman, tier, state, i-1, x1, y1, x2, dst.y1-1 );
+
+ /* right */
+ if (dst.x2 != x2)
+ update_region( sawman, tier, state, i-1, dst.x2+1, dst.y1, x2, dst.y2 );
+
+ /* lower */
+ if (dst.y2 != y2)
+ update_region( sawman, tier, state, i-1, x1, dst.y2+1, x2, y2 );
+ }
+
+ sawman_draw_window( tier, sawwin, state, &region, true );
+ }
+ }
+ else
+ sawman_draw_background( tier, state, &region );
+}
+
+static void
+repaint_tier( SaWMan *sawman,
+ SaWManTier *tier,
+ const DFBRegion *updates,
+ int num_updates,
+ DFBSurfaceFlipFlags flags )
+{
+ int i;
+ CoreLayer *layer;
+ CoreLayerRegion *region;
+ CardState *state;
+ CoreSurface *surface;
+ DFBRegion cursor_inter;
+ CoreWindowStack *stack;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+ D_ASSERT( updates != NULL );
+ D_ASSERT( num_updates > 0 );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ stack = tier->stack;
+ D_ASSERT( stack != NULL );
+
+ region = tier->region;
+ D_ASSERT( region != NULL );
+
+ layer = dfb_layer_at( tier->layer_id );
+ state = &layer->state;
+ surface = region->surface;
+
+ if (/*!data->active ||*/ !surface)
+ return;
+
+ D_DEBUG_AT( SaWMan_Update, "%s( %p, %p )\n", __FUNCTION__, sawman, tier );
+
+ /* Set destination. */
+ state->destination = surface;
+ state->modified |= SMF_DESTINATION;
+
+ for (i=0; i<num_updates; i++) {
+ const DFBRegion *update = &updates[i];
+
+ DFB_REGION_ASSERT( update );
+
+ D_DEBUG_AT( SaWMan_Update, " -> %d, %d - %dx%d (%d)\n",
+ DFB_RECTANGLE_VALS_FROM_REGION( update ), i );
+
+ dfb_state_set_dst_colorkey( state, dfb_color_to_pixel( region->config.format,
+ region->config.src_key.r,
+ region->config.src_key.g,
+ region->config.src_key.b ) );
+
+ /* Set clipping region. */
+ dfb_state_set_clip( state, update );
+
+ /* Compose updated region. */
+ update_region( sawman, tier, state,
+ fusion_vector_size( &sawman->layout ) - 1,
+ update->x1, update->y1, update->x2, update->y2 );
+
+ /* Update cursor? */
+ cursor_inter = tier->cursor_region;
+ if (tier->cursor_drawn && dfb_region_region_intersect( &cursor_inter, update )) {
+ int x, y;
+ DFBRectangle rect = DFB_RECTANGLE_INIT_FROM_REGION( &cursor_inter );
+
+ D_ASSUME( tier->cursor_bs_valid );
+
+ dfb_gfx_copy_to( surface, tier->cursor_bs, &rect,
+ rect.x - tier->cursor_region.x1,
+ rect.y - tier->cursor_region.y1, true );
+
+ x = (s64) stack->cursor.x * (s64) tier->size.w / (s64) sawman_config->resolution.w;
+ y = (s64) stack->cursor.y * (s64) tier->size.h / (s64) sawman_config->resolution.h;
+
+ sawman_draw_cursor( stack, state, &cursor_inter, x, y );
+
+ }
+ }
+
+ /* Reset destination. */
+ state->destination = NULL;
+ state->modified |= SMF_DESTINATION;
+
+ /* Software cursor code relies on a valid back buffer. */
+ if (stack->cursor.enabled)
+ flags |= DSFLIP_BLIT;
+
+ for (i=0; i<num_updates; i++) {
+ const DFBRegion *update = &updates[i];
+
+ DFB_REGION_ASSERT( update );
+
+ /* Flip the updated region .*/
+ dfb_layer_region_flip_update( region, update, flags );
+ }
+
+#ifdef SAWMAN_DUMP_TIER_FRAMES
+ {
+ DFBResult ret;
+ CoreSurfaceBuffer *buffer;
+
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ if (fusion_skirmish_prevail( &surface->lock ))
+ return;
+
+ buffer = dfb_surface_get_buffer( surface, CSBR_FRONT );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ ret = dfb_surface_buffer_dump( buffer, "/", "tier" );
+
+ fusion_skirmish_dismiss( &surface->lock );
+ }
+#endif
+
+ if (1) {
+ SaWManTierUpdate update;
+
+ direct_memcpy( &update.regions[0], updates, sizeof(DFBRegion) * num_updates );
+
+ update.num_regions = num_updates;
+
+ fusion_reactor_dispatch_channel( tier->reactor, SAWMAN_TIER_UPDATE, &update, sizeof(update), true, NULL );
+ }
+}
+
+static SaWManWindow *
+get_single_window( SaWMan *sawman,
+ SaWManTier *tier,
+ bool *ret_none )
+{
+ int n;
+ SaWManWindow *sawwin;
+ SaWManWindow *single = NULL;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ fusion_vector_foreach_reverse (sawwin, n, sawman->layout) {
+ CoreWindow *window;
+
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ if (SAWMAN_VISIBLE_WINDOW(window) && (tier->classes & (1 << window->config.stacking))) {
+ if ( single
+ || ( window->caps & (DWCAPS_INPUTONLY | DWCAPS_COLOR) )
+ || ( window->config.options & DWOP_INPUTONLY ) )
+ return NULL;
+
+ single = sawwin;
+
+ if (single->dst.x == 0 &&
+ single->dst.y == 0 &&
+ single->dst.w == tier->size.w &&
+ single->dst.h == tier->size.h &&
+ !SAWMAN_TRANSLUCENT_WINDOW(window))
+ break;
+ }
+ }
+
+ if (ret_none && !single)
+ *ret_none = true;
+
+ return single;
+}
+
+static bool
+get_border_only( SaWMan *sawman,
+ SaWManTier *tier )
+{
+ int n;
+ SaWManWindow *sawwin;
+ bool none = true;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ fusion_vector_foreach_reverse (sawwin, n, sawman->layout) {
+ CoreWindow *window;
+
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ window = sawwin->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ none = false;
+
+ if ( SAWMAN_VISIBLE_WINDOW(window)
+ && !(window->caps & DWCAPS_INPUTONLY)
+ && !(window->config.options & DWOP_INPUTONLY) )
+ return false;
+ }
+
+ return !none;
+}
+
+static bool
+windows_updating( SaWMan *sawman,
+ SaWManTier *tier )
+{
+ int i;
+ SaWManWindow *window;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ fusion_vector_foreach (window, i, sawman->layout) {
+ D_MAGIC_ASSERT( window, SaWManWindow );
+
+ if (window->flags & SWMWF_UPDATING) {
+ long long diff = direct_clock_get_millis() - window->update_ms;
+
+ if (!sawman_config->flip_once_timeout || diff < sawman_config->flip_once_timeout) {
+ D_DEBUG_AT( SaWMan_FlipOnce, " -> update blocking on window id %u (%lld ms, flags 0x%08x)\n",
+ window->id, diff, window->flags );
+
+ return true;
+ }
+
+ D_DEBUG_AT( SaWMan_FlipOnce, " -> ignoring blocking of window id %u (%lld ms, flags 0x%08x)\n",
+ window->id, diff, window->flags );
+ }
+ }
+
+ D_DEBUG_AT( SaWMan_FlipOnce, " -> update not blocked by any window\n" );
+
+ return false;
+}
+
+/* FIXME: Split up in smaller functions and clean up things like forcing reconfiguration. */
+DirectResult
+sawman_process_updates( SaWMan *sawman,
+ DFBSurfaceFlipFlags flags )
+{
+ DirectResult ret;
+ int idx = -1;
+ SaWManTier *tier;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ D_DEBUG_AT( SaWMan_Update, "%s( %p, 0x%08x )\n", __FUNCTION__, sawman, flags );
+
+ if (sawman->focused_window_switched) {
+ SaWManWindow *to = sawman->focused_window_to;
+
+ if (to) {
+ CoreWindow *window;
+
+ window = to->window;
+ D_MAGIC_ASSERT( window, CoreWindow );
+
+ if (window->config.cursor_flags & DWCF_INVISIBLE) {
+ /* Update cursor */
+ sawman_window_apply_cursor_flags( sawman, to );
+ }
+
+ if (window->cursor.surface) {
+ D_DEBUG_AT( SaWMan_Focus, " -> switching to window's cursor shape\n" );
+
+ dfb_windowstack_cursor_set_shape( window->stack, window->cursor.surface, window->cursor.hot_x, window->cursor.hot_y );
+ }
+
+ if (!(window->config.cursor_flags & DWCF_INVISIBLE)) {
+ /* Update cursor */
+ sawman_window_apply_cursor_flags( sawman, to );
+ }
+ }
+ else {
+ SaWManTier *tier = (SaWManTier*) sawman->tiers;
+
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ if (tier->stack->cursor.opacity) {
+ D_DEBUG_AT( SaWMan_Focus, " -> hiding cursor...\n" );
+
+ tier->stack->cursor.opacity = 0;
+
+ dfb_wm_update_cursor( tier->stack, CCUF_OPACITY );
+ }
+ else
+ D_DEBUG_AT( SaWMan_Focus, " -> cursor already hidden\n" );
+ }
+
+ sawman->focused_window_switched = false;
+ }
+
+ direct_list_foreach (tier, sawman->tiers) {
+ int n, d;
+ int total;
+ int bounding;
+ bool none = false;
+ bool border_only;
+ SaWManWindow *single;
+ CoreLayer *layer;
+ CoreLayerShared *shared;
+ int screen_width;
+ int screen_height;
+ DFBColorKey single_key;
+
+ idx++;
+
+ layer = dfb_layer_at( tier->layer_id );
+ D_ASSERT( layer != NULL );
+
+ shared = layer->shared;
+ D_ASSERT( shared != NULL );
+
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ if (!tier->updates.num_regions)
+ continue;
+
+ if (tier->update_once) {
+ if (windows_updating( sawman, tier ))
+ continue;
+
+ tier->update_once = false;
+ }
+
+ D_DEBUG_AT( SaWMan_Update, " -> %d updates (tier %d, layer %d)\n",
+ tier->updates.num_regions, idx, tier->layer_id );
+
+ D_ASSERT( tier->region != NULL );
+
+ D_DEBUG_AT( SaWMan_Update, " -> [%d] %d updates, bounding %dx%d\n",
+ tier->layer_id, tier->updates.num_regions,
+ tier->updates.bounding.x2 - tier->updates.bounding.x1 + 1,
+ tier->updates.bounding.y2 - tier->updates.bounding.y1 + 1 );
+
+ if (!tier->config.width || !tier->config.height)
+ continue;
+
+ dfb_screen_get_screen_size( layer->screen, &screen_width, &screen_height );
+
+ single = get_single_window( sawman, tier, &none );
+
+ if (none && !sawman_config->show_empty) {
+ if (tier->active) {
+ D_DEBUG_AT( SaWMan_Auto, " -> Disabling region...\n" );
+
+ tier->active = false;
+ tier->single_window = NULL; /* enforce configuration to reallocate buffers */
+
+ dfb_layer_region_disable( tier->region );
+
+ if (sawman->cursor.context && tier->context->layer_id == sawman->cursor.context->layer_id) {
+ dfb_layer_activate_context( dfb_layer_at(sawman->cursor.context->layer_id), sawman->cursor.context );
+
+ dfb_layer_region_flip_update( sawman->cursor.region, NULL, DSFLIP_NONE );
+ }
+ }
+ dfb_updates_reset( &tier->updates );
+ continue;
+ }
+
+ border_only = get_border_only( sawman, tier );
+
+ /* Remember color key before single mode is activated. */
+ if (!tier->single_mode)
+ tier->key = tier->context->primary.config.src_key;
+
+
+ /* If the first mode after turning off the layer is not single, then we need
+ this to force a reconfiguration to reallocate the buffers. */
+ if (!tier->active) {
+ tier->single_mode = true; /* avoid endless loop */
+ tier->border_only = !border_only; /* enforce configuration to reallocate buffers */
+ }
+
+ if (single && !border_only) {
+ CoreWindow *window;
+ CoreSurface *surface;
+ DFBDisplayLayerOptions options = DLOP_NONE;
+ DFBRectangle dst = single->dst;
+ DFBRectangle src = single->src;
+ DFBRegion clip = DFB_REGION_INIT_FROM_DIMENSION( &tier->size );
+
+ if (shared->description.caps & DLCAPS_SCREEN_LOCATION) {
+ dst.x = dst.x * screen_width / tier->size.w;
+ dst.y = dst.y * screen_height / tier->size.h;
+ dst.w = dst.w * screen_width / tier->size.w;
+ dst.h = dst.h * screen_height / tier->size.h;
+ }
+ else {
+ if (dst.w != src.w || dst.h != src.h)
+ goto no_single;
+
+ if (shared->description.caps & DLCAPS_SCREEN_POSITION) {
+ dfb_rectangle_intersect_by_region( &dst, &clip );
+
+ src.x += dst.x - single->dst.x;
+ src.y += dst.y - single->dst.y;
+ src.w = dst.w;
+ src.h = dst.h;
+
+ dst.x += (screen_width - tier->size.w) / 2;
+ dst.y += (screen_height - tier->size.h) / 2;
+ }
+ }
+
+#ifdef SAWMAN_NO_LAYER_DOWNSCALE
+ if (rect.w < src.w)
+ goto no_single;
+#endif
+
+#ifdef SAWMAN_NO_LAYER_DST_WINDOW
+ if (dst.x != 0 || dst.y != 0 || dst.w != screen_width || dst.h != screen_height)
+ goto no_single;
+#endif
+
+
+ window = single->window;
+ D_MAGIC_COREWINDOW_ASSERT( window );
+
+ surface = window->surface;
+ D_ASSERT( surface != NULL );
+
+ if (window->config.options & DWOP_ALPHACHANNEL)
+ options |= DLOP_ALPHACHANNEL;
+
+ if (window->config.options & DWOP_COLORKEYING)
+ options |= DLOP_SRC_COLORKEY;
+
+ single_key = tier->single_key;
+
+ if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) {
+ CorePalette *palette = surface->palette;
+
+ D_ASSERT( palette != NULL );
+ D_ASSERT( palette->num_entries > 0 );
+
+ dfb_surface_set_palette( tier->region->surface, surface->palette );
+
+ if (options & DLOP_SRC_COLORKEY) {
+ int index = window->config.color_key % palette->num_entries;
+
+ single_key.r = palette->entries[index].r;
+ single_key.g = palette->entries[index].g;
+ single_key.b = palette->entries[index].b;
+ single_key.index = index;
+ }
+ }
+ else {
+ DFBColor color;
+
+ dfb_pixel_to_color( surface->config.format, window->config.color_key, &color );
+
+ single_key.r = color.r;
+ single_key.g = color.g;
+ single_key.b = color.b;
+ single_key.index = window->config.color_key;
+ }
+
+ /* Complete reconfig? */
+ if (tier->single_window != single ||
+ !DFB_RECTANGLE_EQUAL( tier->single_src, src ) ||
+ tier->single_format != surface->config.format ||
+ tier->single_options != options)
+ {
+ DFBDisplayLayerConfig config;
+
+ D_DEBUG_AT( SaWMan_Auto, " -> Switching to %dx%d [%dx%d] %s single mode for %p on %p...\n",
+ single->src.w, single->src.h, src.w, src.h,
+ dfb_pixelformat_name( surface->config.format ), single, tier );
+
+ config.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_OPTIONS | DLCONF_BUFFERMODE;
+ config.width = src.w;
+ config.height = src.h;
+ config.pixelformat = surface->config.format;
+ config.options = options;
+ config.buffermode = DLBM_FRONTONLY;
+
+ sawman->callback.layer_reconfig.layer_id = tier->layer_id;
+ sawman->callback.layer_reconfig.single = (SaWManWindowHandle) single;
+ sawman->callback.layer_reconfig.config = config;
+
+ switch (sawman_call( sawman, SWMCID_LAYER_RECONFIG, &sawman->callback.layer_reconfig )) {
+ case DFB_OK:
+ config = sawman->callback.layer_reconfig.config;
+ case DFB_NOIMPL:
+ /* continue, no change demanded */
+ break;
+
+ default:
+ goto no_single;
+ }
+
+ if (dfb_layer_context_test_configuration( tier->context, &config, NULL ) != DFB_OK)
+ goto no_single;
+
+ tier->single_mode = true;
+ tier->single_window = single;
+ tier->single_width = src.w;
+ tier->single_height = src.h;
+ tier->single_src = src;
+ tier->single_dst = dst;
+ tier->single_format = surface->config.format;
+ tier->single_options = options;
+ tier->single_key = single_key;
+
+ tier->active = false;
+ tier->region->state |= CLRSF_FROZEN;
+
+ dfb_updates_reset( &tier->updates );
+
+ dfb_layer_context_set_configuration( tier->context, &config );
+
+ if (shared->description.caps & DLCAPS_SCREEN_LOCATION)
+ dfb_layer_context_set_screenrectangle( tier->context, &dst );
+ else if (shared->description.caps & DLCAPS_SCREEN_POSITION)
+ dfb_layer_context_set_screenposition( tier->context, dst.x, dst.y );
+
+ dfb_layer_context_set_src_colorkey( tier->context,
+ tier->single_key.r, tier->single_key.g,
+ tier->single_key.b, tier->single_key.index );
+
+ dfb_gfx_copy_to( surface, tier->region->surface, &src, 0, 0, false );
+
+ tier->active = true;
+
+ if (sawman->cursor.context && tier->context->layer_id == sawman->cursor.context->layer_id)
+ dfb_layer_activate_context( dfb_layer_at(tier->context->layer_id), tier->context );
+
+ dfb_layer_region_flip_update( tier->region, NULL, flags );
+
+ dfb_updates_reset( &tier->updates );
+
+ if (1) {
+ SaWManTierUpdate update;
+
+ update.regions[0].x1 = 0;
+ update.regions[0].y1 = 0;
+ update.regions[0].x2 = tier->single_width - 1;
+ update.regions[0].y2 = tier->single_height - 1;
+
+ update.num_regions = 1;
+
+ fusion_reactor_dispatch_channel( tier->reactor, SAWMAN_TIER_UPDATE, &update, sizeof(update), true, NULL );
+ }
+ continue;
+ }
+
+ /* Update destination window */
+ if (!DFB_RECTANGLE_EQUAL( tier->single_dst, dst )) {
+ tier->single_dst = dst;
+
+ D_DEBUG_AT( SaWMan_Auto, " -> Changing single destination to %d,%d-%dx%d.\n",
+ DFB_RECTANGLE_VALS(&dst) );
+
+ dfb_layer_context_set_screenrectangle( tier->context, &dst );
+ }
+ else
+ dfb_gfx_copy_to( surface, tier->region->surface, &src, 0, 0, false );
+
+ /* Update color key */
+ if (!DFB_COLORKEY_EQUAL( single_key, tier->single_key )) {
+ D_DEBUG_AT( SaWMan_Auto, " -> Changing single color key.\n" );
+
+ tier->single_key = single_key;
+
+ dfb_layer_context_set_src_colorkey( tier->context,
+ tier->single_key.r, tier->single_key.g,
+ tier->single_key.b, tier->single_key.index );
+ }
+
+ tier->active = true;
+
+ dfb_layer_region_flip_update( tier->region, NULL, flags );
+
+ dfb_updates_reset( &tier->updates );
+
+ fusion_skirmish_notify( &sawman->lock );
+ continue;
+ }
+
+no_single:
+
+ if (tier->single_mode) {
+ D_DEBUG_AT( SaWMan_Auto, " -> Switching back from single mode...\n" );
+
+ tier->border_only = !border_only; /* enforce switch */
+ }
+
+ /* Switch border/default config? */
+ if (tier->border_only != border_only) {
+ DFBDisplayLayerConfig *config;
+
+ tier->border_only = border_only;
+
+ if (border_only)
+ config = &tier->border_config;
+ else
+ config = &tier->config;
+
+ D_DEBUG_AT( SaWMan_Auto, " -> Switching to %dx%d %s %s mode.\n", config->width, config->height,
+ dfb_pixelformat_name( config->pixelformat ), border_only ? "border" : "standard" );
+
+ sawman->callback.layer_reconfig.layer_id = tier->layer_id;
+ sawman->callback.layer_reconfig.single = SAWMAN_WINDOW_NONE;
+ sawman->callback.layer_reconfig.config = *config;
+ ret = sawman_call( sawman, SWMCID_LAYER_RECONFIG, &sawman->callback.layer_reconfig );
+
+ /* on DFB_OK we try to overrule the default configuration */
+ if ( !ret && !dfb_layer_context_test_configuration( tier->context, &(sawman->callback.layer_reconfig.config), NULL ) ) {
+ *config = sawman->callback.layer_reconfig.config;
+ D_DEBUG_AT( SaWMan_Auto, " -> Overruled to %dx%d %s %s mode.\n", config->width, config->height,
+ dfb_pixelformat_name( config->pixelformat ), border_only ? "border" : "standard" );
+ }
+
+ tier->active = false;
+ tier->region->state |= CLRSF_FROZEN;
+
+ dfb_updates_reset( &tier->updates );
+
+ /* Temporarily to avoid configuration errors. */
+ dfb_layer_context_set_screenposition( tier->context, 0, 0 );
+
+ ret = dfb_layer_context_set_configuration( tier->context, config );
+ if (ret) {
+ D_DERROR( ret, "SaWMan/Auto: Switching to standard mode failed!\n" );
+ /* fixme */
+ }
+
+ tier->size.w = config->width;
+ tier->size.h = config->height;
+
+ /* Notify application manager about new tier size if previous mode was single. */
+ if (tier->single_mode)
+ sawman_call( sawman, SWMCID_STACK_RESIZED, &tier->size );
+
+ if (shared->description.caps & DLCAPS_SCREEN_LOCATION) {
+ DFBRectangle full = { 0, 0, screen_width, screen_height };
+
+ dfb_layer_context_set_screenrectangle( tier->context, &full );
+ }
+ else if (shared->description.caps & DLCAPS_SCREEN_POSITION) {
+ dfb_layer_context_set_screenposition( tier->context,
+ (screen_width - config->width) / 2,
+ (screen_height - config->height) / 2 );
+ }
+
+ if (config->options & DLOP_SRC_COLORKEY) {
+ if (DFB_PIXELFORMAT_IS_INDEXED( config->pixelformat )) {
+ int index;
+ CoreSurface *surface;
+ CorePalette *palette;
+
+ surface = tier->region->surface;
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ palette = surface->palette;
+ D_ASSERT( palette != NULL );
+ D_ASSERT( palette->num_entries > 0 );
+
+ index = tier->key.index % palette->num_entries;
+
+ dfb_layer_context_set_src_colorkey( tier->context,
+ palette->entries[index].r,
+ palette->entries[index].g,
+ palette->entries[index].b,
+ index );
+ }
+ else
+ dfb_layer_context_set_src_colorkey( tier->context,
+ tier->key.r, tier->key.g, tier->key.b, tier->key.index );
+ }
+ }
+
+ if (!tier->active) {
+ D_DEBUG_AT( SaWMan_Auto, " -> Activating tier...\n" );
+
+ tier->active = true;
+
+ DFBRegion region = { 0, 0, tier->size.w - 1, tier->size.h - 1 };
+ dfb_updates_add( &tier->updates, &region );
+
+ if (sawman->cursor.context && tier->context->layer_id == sawman->cursor.context->layer_id)
+ dfb_layer_activate_context( dfb_layer_at(tier->context->layer_id), tier->context );
+ }
+
+ tier->single_mode = false;
+ tier->single_window = NULL;
+
+ if (!tier->updates.num_regions)
+ continue;
+
+
+ dfb_updates_stat( &tier->updates, &total, &bounding );
+
+ n = tier->updates.max_regions - tier->updates.num_regions + 1;
+ d = n + 1;
+
+ /* Try to optimize updates. In buffer swapping modes we can save the copy by updating everything. */
+ if ((total > tier->size.w * tier->size.h) ||
+ (total > tier->size.w * tier->size.h * 3 / 5 && (tier->context->config.buffermode == DLBM_BACKVIDEO ||
+ tier->context->config.buffermode == DLBM_TRIPLE)))
+ {
+ DFBRegion region = { 0, 0, tier->size.w - 1, tier->size.h - 1 };
+
+ repaint_tier( sawman, tier, &region, 1, flags );
+ }
+ else if (tier->updates.num_regions < 2 || total < bounding * n / d)
+ repaint_tier( sawman, tier, tier->updates.regions, tier->updates.num_regions, flags );
+ else
+ repaint_tier( sawman, tier, &tier->updates.bounding, 1, flags );
+
+ dfb_updates_reset( &tier->updates );
+
+ fusion_skirmish_notify( &sawman->lock );
+ }
+
+ return DFB_OK;
+}
+
+#endif // !DIRECTFB_PURE_VOODOO \ No newline at end of file
diff --git a/Source/SaWMan/src/sawman_config.c b/Source/SaWMan/src/sawman_config.c
new file mode 100755
index 0000000..0c50a92
--- /dev/null
+++ b/Source/SaWMan/src/sawman_config.c
@@ -0,0 +1,512 @@
+/*
+ (c) Copyright 2006-2007 directfb.org
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sawman.h>
+
+#include <direct/conf.h>
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <misc/conf.h>
+
+#include "sawman_config.h"
+
+
+SaWManConfig *sawman_config = NULL;
+
+static const char *config_usage =
+ "SaWMan Configuration\n"
+ "\n"
+ " --sawman-help Output SaWMan usage information and exit\n"
+ " --sawman:<option>[,<option>]... Pass options to SaWMan (see below)\n"
+ "\n"
+ "SaWMan options:\n"
+ "\n"
+ " init-border=<num> Set border values for tier (0-2)\n"
+ " border-thickness=< \n"
+ " hw-cursor=<layer-id> Set HW Cursor mode\n"
+ " resolution=<width>x<height> Set virtual SaWMan resolution, e.g. 19200000x10800000\n"
+ "\n";
+
+
+static DFBResult
+parse_args( const char *args )
+{
+ char *buf = alloca( strlen(args) + 1 );
+
+ strcpy( buf, args );
+
+ while (buf && buf[0]) {
+ DFBResult ret;
+ char *value;
+ char *next;
+
+ if ((next = strchr( buf, ',' )) != NULL)
+ *next++ = '\0';
+
+ if (strcmp (buf, "help") == 0) {
+ fprintf( stderr, config_usage );
+ exit(1);
+ }
+
+ if ((value = strchr( buf, '=' )) != NULL)
+ *value++ = '\0';
+
+ ret = sawman_config_set( buf, value );
+ switch (ret) {
+ case DFB_OK:
+ break;
+ case DFB_UNSUPPORTED:
+ D_ERROR( "SaWMan/Config: Unknown option '%s'!\n", buf );
+ break;
+ default:
+ return ret;
+ }
+
+ buf = next;
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+config_allocate()
+{
+ if (sawman_config)
+ return DFB_OK;
+
+ sawman_config = D_CALLOC( 1, sizeof(SaWManConfig) );
+ if (!sawman_config)
+ return D_OOM();
+
+ sawman_config->border = &sawman_config->borders[0];
+
+ sawman_config->borders[0].thickness = 4;
+ sawman_config->borders[0].focused[0] = (DFBColor){ 0xff, 0xc0, 0x00, 0x00 };
+ sawman_config->borders[0].focused[1] = (DFBColor){ 0xff, 0xb0, 0x00, 0x00 };
+ sawman_config->borders[0].focused[2] = (DFBColor){ 0xff, 0xa0, 0x00, 0x00 };
+ sawman_config->borders[0].focused[3] = (DFBColor){ 0xff, 0x90, 0x00, 0x00 };
+ sawman_config->borders[0].unfocused[0] = (DFBColor){ 0xff, 0x80, 0x80, 0x80 };
+ sawman_config->borders[0].unfocused[1] = (DFBColor){ 0xff, 0x70, 0x70, 0x70 };
+ sawman_config->borders[0].unfocused[2] = (DFBColor){ 0xff, 0x60, 0x60, 0x60 };
+ sawman_config->borders[0].unfocused[3] = (DFBColor){ 0xff, 0x50, 0x50, 0x50 };
+
+ sawman_config->resolution.w = 1920 << 16;
+ sawman_config->resolution.h = 1080 << 16;
+
+ return DFB_OK;
+}
+
+const char*
+sawman_config_usage( void )
+{
+ return config_usage;
+}
+
+DirectResult
+sawman_config_set( const char *name, const char *value )
+{
+ if (strcmp (name, "init-border" ) == 0) {
+ if (value) {
+ int index;
+
+ if (sscanf( value, "%d", &index ) < 1) {
+ D_ERROR("SaWMan/Config '%s': Could not parse value!\n", name);
+ return DFB_INVARG;
+ }
+
+ if (index < 0 || index > D_ARRAY_SIZE(sawman_config->borders)) {
+ D_ERROR("SaWMan/Config '%s': Value %d out of bounds!\n", name, index);
+ return DFB_INVARG;
+ }
+
+ sawman_config->border = &sawman_config->borders[index];
+ }
+ else {
+ D_ERROR("SaWMan/Config '%s': No value specified!\n", name);
+ return DFB_INVARG;
+ }
+ } else
+ if (strcmp (name, "border-thickness" ) == 0) {
+ SaWManBorderInit *border = sawman_config->border;
+
+ if (value) {
+ if (sscanf( value, "%d", &border->thickness ) < 1) {
+ D_ERROR("SaWMan/Config '%s': Could not parse value!\n", name);
+ return DFB_INVARG;
+ }
+ }
+ else {
+ D_ERROR("SaWMan/Config '%s': No value specified!\n", name);
+ return DFB_INVARG;
+ }
+ } else
+ if (strcmp (name, "border-resolution" ) == 0) {
+ SaWManBorderInit *border = sawman_config->border;
+
+ if (value) {
+ int width, height;
+
+ if (sscanf( value, "%dx%d", &width, &height ) < 2) {
+ D_ERROR("SaWMan/Config '%s': Could not parse dimension!\n", name);
+ return DFB_INVARG;
+ }
+
+ border->resolution.w = width;
+ border->resolution.h = height;
+ }
+ else {
+ D_ERROR("SaWMan/Config '%s': No width and height specified!\n", name);
+ return DFB_INVARG;
+ }
+ } else
+ if (strcmp (name, "border-format" ) == 0) {
+ SaWManBorderInit *border = sawman_config->border;
+
+ if (value) {
+ DFBSurfacePixelFormat format;
+
+ format = dfb_config_parse_pixelformat( value );
+ if (format == DSPF_UNKNOWN) {
+ D_ERROR("SaWMan/Config '%s': Could not parse format!\n", name);
+ return DFB_INVARG;
+ }
+
+ border->format = format;
+ }
+ else {
+ D_ERROR("SaWMan/Config '%s': No format specified!\n", name);
+ return DFB_INVARG;
+ }
+ } else
+ if (strncmp (name, "border-focused-color-index", 26 ) == 0 || strncmp (name, "border-unfocused-color-index", 28 ) == 0) {
+ SaWManBorderInit *border = sawman_config->border;
+ int cindex = (name[7] == 'f') ? (name[26] - '0') : (name[28] - '0');
+
+ if (cindex < 0 || cindex > D_ARRAY_SIZE(border->focused)) {
+ D_ERROR("SaWMan/Config '%s': Value %d out of bounds!\n", name, cindex);
+ return DFB_INVARG;
+ }
+
+ if (value) {
+ char *error;
+ u32 index;
+
+ index = strtoul( value, &error, 10 );
+
+ if (*error) {
+ D_ERROR( "SaWMan/Config '%s': Error in index '%s'!\n", name, error );
+ return DFB_INVARG;
+ }
+
+ if (strncmp (name, "border-focused-color-index", 26 ) == 0)
+ border->focused_index[cindex] = index;
+ else
+ border->unfocused_index[cindex] = index;
+ }
+ else {
+ D_ERROR( "SaWMan/Config '%s': No index specified!\n", name );
+ return DFB_INVARG;
+ }
+ } else
+ if (strncmp (name, "border-focused-color", 20 ) == 0 || strncmp (name, "border-unfocused-color", 22 ) == 0) {
+ SaWManBorderInit *border = sawman_config->border;
+ int cindex = (name[7] == 'f') ? (name[20] - '0') : (name[22] - '0');
+
+ if (cindex < 0 || cindex > D_ARRAY_SIZE(border->focused)) {
+ D_ERROR("SaWMan/Config '%s': Value %d out of bounds!\n", name, cindex);
+ return DFB_INVARG;
+ }
+
+ if (value) {
+ char *error;
+ u32 argb;
+
+ argb = strtoul( value, &error, 16 );
+
+ if (*error) {
+ D_ERROR( "SaWMan/Config '%s': Error in color '%s'!\n", name, error );
+ return DFB_INVARG;
+ }
+
+ if (strncmp (name, "border-focused-color", 20 ) == 0) {
+ border->focused[cindex].a = (argb & 0xFF000000) >> 24;
+ border->focused[cindex].r = (argb & 0xFF0000) >> 16;
+ border->focused[cindex].g = (argb & 0xFF00) >> 8;
+ border->focused[cindex].b = (argb & 0xFF);
+ border->focused_index[cindex] = -1;
+ }
+ else {
+ border->unfocused[cindex].a = (argb & 0xFF000000) >> 24;
+ border->unfocused[cindex].r = (argb & 0xFF0000) >> 16;
+ border->unfocused[cindex].g = (argb & 0xFF00) >> 8;
+ border->unfocused[cindex].b = (argb & 0xFF);
+ border->unfocused_index[cindex] = -1;
+ }
+ }
+ else {
+ D_ERROR( "SaWMan/Config '%s': No color specified!\n", name );
+ return DFB_INVARG;
+ }
+ } else
+ if (strcmp (name, "show-empty") == 0) {
+ sawman_config->show_empty = true;
+ } else
+ if (strcmp (name, "no-show-empty") == 0) {
+ sawman_config->show_empty = false;
+ } else
+ if (strcmp (name, "flip-once-timeout") == 0) {
+ if (value) {
+ char *error;
+ u32 timeout;
+
+ timeout = strtoul( value, &error, 10 );
+
+ if (*error) {
+ D_ERROR( "SaWMan/Config '%s': Error in timeout '%s'!\n", name, error );
+ return DFB_INVARG;
+ }
+
+ sawman_config->flip_once_timeout = timeout;
+ }
+ else {
+ D_ERROR( "SaWMan/Config '%s': No timeout specified!\n", name );
+ return DFB_INVARG;
+ }
+ } else
+ if (strcmp (name, "hw-cursor" ) == 0) {
+ if (value) {
+ int id;
+
+ if (sscanf( value, "%d", &id ) < 1) {
+ D_ERROR("SaWMan/Config '%s': Could not parse value!\n", name);
+ return DFB_INVARG;
+ }
+
+ if (id < 0 || id >= MAX_LAYERS) {
+ D_ERROR("SaWMan/Config '%s': Value %d out of bounds!\n", name, id);
+ return DFB_INVARG;
+ }
+
+ sawman_config->cursor.hw = true;
+ sawman_config->cursor.layer_id = id;
+ }
+ else {
+ D_ERROR("SaWMan/Config '%s': No value specified!\n", name);
+ return DFB_INVARG;
+ }
+ } else
+ if (strcmp (name, "resolution" ) == 0) {
+ if (value) {
+ int width, height;
+
+ if (sscanf( value, "%dx%d", &width, &height ) < 2) {
+ D_ERROR("SaWMan/Config '%s': Could not parse dimension!\n", name);
+ return DFB_INVARG;
+ }
+
+ sawman_config->resolution.w = width;
+ sawman_config->resolution.h = height;
+ }
+ else {
+ D_ERROR("SaWMan/Config '%s': No width and height specified!\n", name);
+ return DFB_INVARG;
+ }
+ } else
+ return DFB_UNSUPPORTED;
+
+ return DFB_OK;
+}
+
+static DFBResult
+sawman_config_read( const char *filename )
+{
+ DFBResult ret = DFB_OK;
+ char line[400];
+ FILE *f;
+
+ f = fopen( filename, "r" );
+ if (!f) {
+ D_DEBUG( "SaWMan/Config: "
+ "Unable to open config file `%s'!\n", filename );
+ return DFB_IO;
+ } else {
+ D_INFO( "SaWMan/Config: "
+ "Parsing config file '%s'.\n", filename );
+ }
+
+ while (fgets( line, 400, f )) {
+ char *name = line;
+ char *value = strchr( line, '=' );
+
+ if (value) {
+ *value++ = 0;
+ direct_trim( &value );
+ }
+
+ direct_trim( &name );
+
+ if (!*name || *name == '#')
+ continue;
+
+ ret = sawman_config_set( name, value );
+ if (ret) {
+ if (ret == DFB_UNSUPPORTED)
+ D_ERROR( "SaWMan/Config: In config file `%s': "
+ "Invalid option `%s'!\n", filename, name );
+ break;
+ }
+ }
+
+ fclose( f );
+
+ return ret;
+}
+
+DirectResult
+sawman_config_init( int *argc, char **argv[] )
+{
+ DFBResult ret;
+
+ if (!sawman_config) {
+ char *home = getenv( "HOME" );
+ char *prog = NULL;
+ char *swargs;
+
+ ret = config_allocate();
+ if (ret)
+ return ret;
+
+ /* Read system settings. */
+ ret = sawman_config_read( SYSCONFDIR"/sawmanrc" );
+ if (ret && ret != DFB_IO)
+ return ret;
+
+ /* Read user settings. */
+ if (home) {
+ int len = strlen(home) + sizeof("/.sawmanrc");
+ char buf[len];
+
+ snprintf( buf, len, "%s/.sawmanrc", home );
+
+ ret = sawman_config_read( buf );
+ if (ret && ret != DFB_IO)
+ return ret;
+ }
+
+ /* Get application name. */
+ if (argc && *argc && argv && *argv) {
+ prog = strrchr( (*argv)[0], '/' );
+
+ if (prog)
+ prog++;
+ else
+ prog = (*argv)[0];
+ }
+
+ /* Read global application settings. */
+ if (prog && prog[0]) {
+ int len = sizeof(SYSCONFDIR"/sawmanrc.") + strlen(prog);
+ char buf[len];
+
+ snprintf( buf, len, SYSCONFDIR"/sawmanrc.%s", prog );
+
+ ret = sawman_config_read( buf );
+ if (ret && ret != DFB_IO)
+ return ret;
+ }
+
+ /* Read user application settings. */
+ if (home && prog && prog[0]) {
+ int len = strlen(home) + sizeof("/.sawmanrc.") + strlen(prog);
+ char buf[len];
+
+ snprintf( buf, len, "%s/.sawmanrc.%s", home, prog );
+
+ ret = sawman_config_read( buf );
+ if (ret && ret != DFB_IO)
+ return ret;
+ }
+
+ /* Read settings from environment variable. */
+ swargs = getenv( "SAWMANARGS" );
+ if (swargs) {
+ ret = parse_args( swargs );
+ if (ret)
+ return ret;
+ }
+ }
+
+ /* Read settings from command line. */
+ if (argc && argv) {
+ int i;
+
+ for (i = 1; i < *argc; i++) {
+
+ if (!strcmp( (*argv)[i], "--sawman-help" )) {
+ fprintf( stderr, config_usage );
+ exit(1);
+ }
+
+ if (!strncmp( (*argv)[i], "--sawman:", 5 )) {
+ ret = parse_args( (*argv)[i] + 5 );
+ if (ret)
+ return ret;
+
+ (*argv)[i] = NULL;
+ }
+ }
+
+ for (i = 1; i < *argc; i++) {
+ int k;
+
+ for (k = i; k < *argc; k++)
+ if ((*argv)[k] != NULL)
+ break;
+
+ if (k > i) {
+ int j;
+
+ k -= i;
+
+ for (j = i + k; j < *argc; j++)
+ (*argv)[j-k] = (*argv)[j];
+
+ *argc -= k;
+ }
+ }
+ }
+
+ return DFB_OK;
+}
+
diff --git a/Source/SaWMan/src/sawman_config.h b/Source/SaWMan/src/sawman_config.h
new file mode 100755
index 0000000..2eb843a
--- /dev/null
+++ b/Source/SaWMan/src/sawman_config.h
@@ -0,0 +1,76 @@
+/*
+ (c) Copyright 2006-2007 directfb.org
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __SAWMAN__SAWMAN_CONFIG_H__
+#define __SAWMAN__SAWMAN_CONFIG_H__
+
+#include <directfb.h>
+#include <sawman.h>
+
+typedef struct {
+ int thickness;
+ DFBDimension resolution;
+ DFBSurfacePixelFormat format;
+ DFBColor focused[4];
+ DFBColor unfocused[4];
+ int focused_index[4];
+ int unfocused_index[4];
+} SaWManBorderInit;
+
+typedef struct {
+ SaWManBorderInit *border;
+ SaWManBorderInit borders[3];
+
+ bool show_empty; /* Don't hide layer when no window is visible. */
+
+ unsigned int flip_once_timeout;
+
+ struct {
+ bool hw;
+ DFBDisplayLayerID layer_id;
+ } cursor;
+
+ DFBDimension resolution;
+} SaWManConfig;
+
+
+extern SaWManConfig *sawman_config;
+
+
+/*
+ * Allocate Config struct, fill with defaults and parse command line options
+ * for overrides. Options identified as SaWMan options are stripped out
+ * of the array.
+ */
+DirectResult sawman_config_init( int *argc, char **argv[] );
+
+/*
+ * Set individual option. Used by sawman_config_init(), and SaWManSetOption()
+ */
+DirectResult sawman_config_set( const char *name, const char *value );
+
+const char *sawman_config_usage( void );
+
+
+#endif /* __SAWMAN__SAWMAN_CONFIG_H__ */
+
diff --git a/Source/SaWMan/src/sawman_draw.c b/Source/SaWMan/src/sawman_draw.c
new file mode 100755
index 0000000..16ce61b
--- /dev/null
+++ b/Source/SaWMan/src/sawman_draw.c
@@ -0,0 +1,677 @@
+/*
+ (c) Copyright 2001-2007 directfb.org
+ (c) Copyright 2000-2004 convergence (integrated) media GmbH.
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org> and
+ Ville Syrjälä <syrjala@sci.fi>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <directfb.h>
+#include <directfb_util.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <core/gfxcard.h>
+#include <core/palette.h>
+#include <core/state.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+#include <core/windows.h>
+#include <core/windows_internal.h>
+#include <core/windowstack.h>
+
+#include <gfx/convert.h>
+
+#include <misc/util.h>
+
+#include <sawman_config.h>
+#include <sawman_internal.h>
+
+D_DEBUG_DOMAIN( SaWMan_Draw, "SaWMan/Draw", "SaWMan window manager drawing" );
+
+/**********************************************************************************************************************/
+
+void
+sawman_draw_cursor( CoreWindowStack *stack, CardState *state, DFBRegion *region, int x, int y )
+{
+ DFBRectangle src;
+ DFBRectangle clip;
+ DFBSurfaceBlittingFlags flags = DSBLIT_BLEND_ALPHACHANNEL;
+
+ D_ASSERT( stack != NULL );
+ D_MAGIC_ASSERT( state, CardState );
+ DFB_REGION_ASSERT( region );
+
+ D_ASSUME( stack->cursor.opacity > 0 );
+
+ D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__,
+ stack, DFB_RECTANGLE_VALS_FROM_REGION( region ) );
+
+ /* Initialize source rectangle. */
+ src.x = region->x1 - x + stack->cursor.hot.x;
+ src.y = region->y1 - y + stack->cursor.hot.y;
+ src.w = region->x2 - region->x1 + 1;
+ src.h = region->y2 - region->y1 + 1;
+
+ /* Initialize source clipping rectangle */
+ clip.x = clip.y = 0;
+ clip.w = stack->cursor.surface->config.size.w;
+ clip.h = stack->cursor.surface->config.size.h;
+
+ /* Intersect rectangles */
+ if (!dfb_rectangle_intersect( &src, &clip ))
+ return;
+
+ /* Use global alpha blending. */
+ if (stack->cursor.opacity != 0xFF) {
+ flags |= DSBLIT_BLEND_COLORALPHA;
+
+ /* Set opacity as blending factor. */
+ if (state->color.a != stack->cursor.opacity) {
+ state->color.a = stack->cursor.opacity;
+ state->modified |= SMF_COLOR;
+ }
+ }
+
+ /* Different compositing methods depending on destination format. */
+ if (flags & DSBLIT_BLEND_ALPHACHANNEL) {
+ if (DFB_PIXELFORMAT_HAS_ALPHA( state->destination->config.format )) {
+ /*
+ * Always use compliant Porter/Duff SRC_OVER,
+ * if the destination has an alpha channel.
+ *
+ * Cd = destination color (non-premultiplied)
+ * Ad = destination alpha
+ *
+ * Cs = source color (non-premultiplied)
+ * As = source alpha
+ *
+ * Ac = color alpha
+ *
+ * cd = Cd * Ad (premultiply destination)
+ * cs = Cs * As (premultiply source)
+ *
+ * The full equation to calculate resulting color and alpha (premultiplied):
+ *
+ * cx = cd * (1-As*Ac) + cs * Ac
+ * ax = Ad * (1-As*Ac) + As * Ac
+ */
+ dfb_state_set_src_blend( state, DSBF_ONE );
+
+ /* Need to premultiply source with As*Ac or only with Ac? */
+ if (! (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED))
+ flags |= DSBLIT_SRC_PREMULTIPLY;
+ else if (flags & DSBLIT_BLEND_COLORALPHA)
+ flags |= DSBLIT_SRC_PREMULTCOLOR;
+
+ /* Need to premultiply/demultiply destination? */
+// if (! (state->destination->caps & DSCAPS_PREMULTIPLIED))
+// flags |= DSBLIT_DST_PREMULTIPLY | DSBLIT_DEMULTIPLY;
+ }
+ else {
+ /*
+ * We can avoid DSBLIT_SRC_PREMULTIPLY for destinations without an alpha channel
+ * by using another blending function, which is more likely that it's accelerated
+ * than premultiplication at this point in time.
+ *
+ * This way the resulting alpha (ax) doesn't comply with SRC_OVER,
+ * but as the destination doesn't have an alpha channel it's no problem.
+ *
+ * As the destination's alpha value is always 1.0 there's no need for
+ * premultiplication. The resulting alpha value will also be 1.0 without
+ * exceptions, therefore no need for demultiplication.
+ *
+ * cx = Cd * (1-As*Ac) + Cs*As * Ac (still same effect as above)
+ * ax = Ad * (1-As*Ac) + As*As * Ac (wrong, but discarded anyways)
+ */
+ if (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED) {
+ /* Need to premultiply source with Ac? */
+ if (flags & DSBLIT_BLEND_COLORALPHA)
+ flags |= DSBLIT_SRC_PREMULTCOLOR;
+
+ dfb_state_set_src_blend( state, DSBF_ONE );
+ }
+ else
+ dfb_state_set_src_blend( state, DSBF_SRCALPHA );
+ }
+ }
+
+ /* Set blitting flags. */
+ dfb_state_set_blitting_flags( state, flags );
+
+ /* Set blitting source. */
+ state->source = stack->cursor.surface;
+ state->modified |= SMF_SOURCE;
+
+ /* Blit from the window to the region being updated. */
+ dfb_gfxcard_blit( &src, region->x1, region->y1, state );
+
+ /* Reset blitting source. */
+ state->source = NULL;
+ state->modified |= SMF_SOURCE;
+}
+
+static void
+draw_border( SaWManWindow *sawwin,
+ CardState *state,
+ const DFBRegion *region,
+ int thickness )
+{
+ int i;
+ DFBRegion old_clip;
+ DFBRectangle rects[thickness];
+ CoreWindow *window;
+ const SaWManBorderInit *border;
+ const DFBColor *colors;
+ const int *indices;
+ unsigned int num_colors;
+ unsigned int num_indices;
+
+ window = sawwin->window;
+ D_ASSERT( window != NULL );
+
+ D_DEBUG_AT( SaWMan_Draw, "%s( %p, %p, %d,%d-%dx%d, %d )\n", __FUNCTION__,
+ sawwin, state, DFB_RECTANGLE_VALS_FROM_REGION( region ), thickness );
+
+ if (thickness > sawwin->bounds.w / 2)
+ thickness = sawwin->bounds.w / 2;
+
+ if (thickness > sawwin->bounds.h / 2)
+ thickness = sawwin->bounds.h / 2;
+
+ /* Check thickness. */
+ if (thickness < 1)
+ return;
+
+ /* Initialize border rectangles. */
+ rects[0] = sawwin->bounds;
+
+ for (i=1; i<thickness; i++) {
+ rects[i].x = rects[i-1].x + 1;
+ rects[i].y = rects[i-1].y + 1;
+ rects[i].w = rects[i-1].w - 2;
+ rects[i].h = rects[i-1].h - 2;
+ }
+
+ /* Save clipping region. */
+ old_clip = state->clip;
+
+ /* Change clipping region. */
+ dfb_state_set_clip( state, region );
+
+ border = &sawman_config->borders[sawman_window_priority(sawwin)];
+
+ if (window->flags & CWF_FOCUSED) {
+ colors = border->focused;
+ indices = border->focused_index;
+ num_colors = D_ARRAY_SIZE(border->focused);
+ num_indices = D_ARRAY_SIZE(border->focused_index);
+ }
+ else {
+ colors = border->unfocused;
+ indices = border->unfocused_index;
+ num_colors = D_ARRAY_SIZE(border->unfocused);
+ num_indices = D_ARRAY_SIZE(border->unfocused_index);
+ }
+
+ /* Draw border rectangles. */
+ for (i=0; i<thickness; i++) {
+ dfb_state_set_color_or_index( state,
+ &colors[i*num_colors/thickness],
+ indices[i*num_indices/thickness] );
+
+ dfb_gfxcard_drawrectangle( &rects[i], state );
+ }
+
+ /* Restore clipping region. */
+ dfb_state_set_clip( state, &old_clip );
+}
+
+static void
+draw_window( SaWManTier *tier,
+ SaWManWindow *sawwin,
+ CardState *state,
+ DFBRegion *region,
+ bool alpha_channel )
+{
+ SaWMan *sawman;
+ CoreWindow *window;
+ DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
+ DFBRectangle dst;
+ DFBRectangle src;
+ DFBRegion clip;
+ DFBRegion old_clip;
+
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_MAGIC_ASSERT( state, CardState );
+ DFB_REGION_ASSERT( region );
+
+ sawman = sawwin->sawman;
+ window = sawwin->window;
+ dst = sawwin->dst;
+ src = sawwin->src;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( window != NULL );
+ D_ASSERT( window->surface != NULL );
+
+ D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__,
+ sawwin, DFB_RECTANGLE_VALS_FROM_REGION( region ) );
+
+ /* Setup clipping region. */
+ clip = *region;
+
+ if (!dfb_region_rectangle_intersect( &clip, &dst ))
+ return;
+
+ /* Backup clipping region. */
+ old_clip = state->clip;
+
+ /* Use per pixel alpha blending. */
+ if (alpha_channel && (window->config.options & DWOP_ALPHACHANNEL))
+ flags |= DSBLIT_BLEND_ALPHACHANNEL;
+
+ /* Use global alpha blending. */
+ if (window->config.opacity != 0xFF) {
+ flags |= DSBLIT_BLEND_COLORALPHA;
+
+ /* Set opacity as blending factor. */
+ if (state->color.a != window->config.opacity) {
+ state->color.a = window->config.opacity;
+ state->modified |= SMF_COLOR;
+ }
+ }
+
+ /* Use source color keying. */
+ if (window->config.options & DWOP_COLORKEYING) {
+ flags |= DSBLIT_SRC_COLORKEY;
+
+ D_DEBUG_AT( SaWMan_Draw, " -> key 0x%08x\n", window->config.color_key );
+
+ /* Set window color key. */
+ dfb_state_set_src_colorkey( state, window->config.color_key );
+ }
+
+ /* Use automatic deinterlacing. */
+ if (window->surface->config.caps & DSCAPS_INTERLACED)
+ flags |= DSBLIT_DEINTERLACE;
+
+ /* Different compositing methods depending on destination format. */
+ if (flags & DSBLIT_BLEND_ALPHACHANNEL) {
+ if (DFB_PIXELFORMAT_HAS_ALPHA( state->destination->config.format )) {
+ /*
+ * Always use compliant Porter/Duff SRC_OVER,
+ * if the destination has an alpha channel.
+ *
+ * Cd = destination color (non-premultiplied)
+ * Ad = destination alpha
+ *
+ * Cs = source color (non-premultiplied)
+ * As = source alpha
+ *
+ * Ac = color alpha
+ *
+ * cd = Cd * Ad (premultiply destination)
+ * cs = Cs * As (premultiply source)
+ *
+ * The full equation to calculate resulting color and alpha (premultiplied):
+ *
+ * cx = cd * (1-As*Ac) + cs * Ac
+ * ax = Ad * (1-As*Ac) + As * Ac
+ */
+ dfb_state_set_src_blend( state, DSBF_ONE );
+
+ /* Need to premultiply source with As*Ac or only with Ac? */
+ if (! (window->surface->config.caps & DSCAPS_PREMULTIPLIED))
+ flags |= DSBLIT_SRC_PREMULTIPLY;
+ else if (flags & DSBLIT_BLEND_COLORALPHA)
+ flags |= DSBLIT_SRC_PREMULTCOLOR;
+
+ /* Need to premultiply/demultiply destination? */
+// if (! (state->destination->caps & DSCAPS_PREMULTIPLIED))
+// flags |= DSBLIT_DST_PREMULTIPLY | DSBLIT_DEMULTIPLY;
+ }
+ else {
+ /*
+ * We can avoid DSBLIT_SRC_PREMULTIPLY for destinations without an alpha channel
+ * by using another blending function, which is more likely that it's accelerated
+ * than premultiplication at this point in time.
+ *
+ * This way the resulting alpha (ax) doesn't comply with SRC_OVER,
+ * but as the destination doesn't have an alpha channel it's no problem.
+ *
+ * As the destination's alpha value is always 1.0 there's no need for
+ * premultiplication. The resulting alpha value will also be 1.0 without
+ * exceptions, therefore no need for demultiplication.
+ *
+ * cx = Cd * (1-As*Ac) + Cs*As * Ac (still same effect as above)
+ * ax = Ad * (1-As*Ac) + As*As * Ac (wrong, but discarded anyways)
+ */
+ if (window->surface->config.caps & DSCAPS_PREMULTIPLIED) {
+ /* Need to premultiply source with Ac? */
+ if (flags & DSBLIT_BLEND_COLORALPHA)
+ flags |= DSBLIT_SRC_PREMULTCOLOR;
+
+ dfb_state_set_src_blend( state, DSBF_ONE );
+ }
+ else
+ dfb_state_set_src_blend( state, DSBF_SRCALPHA );
+ }
+ }
+
+ /* Use color (key) protection if layer is keyed. */
+ if (tier->context->config.options & DLOP_SRC_COLORKEY) {
+ flags |= DSBLIT_COLORKEY_PROTECT;
+
+ dfb_state_set_colorkey( state, &tier->key );
+ }
+
+ /* Set blitting flags. */
+ dfb_state_set_blitting_flags( state, flags );
+
+ /* Set render options. */
+ if (sawman->scaling_mode == SWMSM_SMOOTH_SW)
+ dfb_state_set_render_options( state, DSRO_SMOOTH_DOWNSCALE | DSRO_SMOOTH_UPSCALE );
+ else
+ dfb_state_set_render_options( state, DSRO_NONE );
+
+ /* Set blitting source. */
+ state->source = window->surface;
+ state->modified |= SMF_SOURCE;
+
+ D_DEBUG_AT( SaWMan_Draw, " [][] %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( &clip ) );
+
+ /* Change clipping region. */
+ dfb_state_set_clip( state, &clip );
+
+ D_DEBUG_AT( SaWMan_Draw, " => %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d\n",
+ DFB_RECTANGLE_VALS( &dst ), DFB_RECTANGLE_VALS( &src ) );
+
+ /* Scale window to the screen clipped by the region being updated. */
+ dfb_gfxcard_stretchblit( &src, &dst, state );
+
+ /* Restore clipping region. */
+ dfb_state_set_clip( state, &old_clip );
+}
+
+static void
+draw_window_color( SaWManWindow *sawwin,
+ CardState *state,
+ DFBRegion *region,
+ bool alpha_channel )
+{
+ SaWMan *sawman;
+ CoreWindow *window;
+ DFBSurfaceDrawingFlags flags = DSDRAW_NOFX;
+ DFBRectangle dst;
+ DFBRegion clip;
+ DFBRegion old_clip;
+ DFBColor color;
+
+
+ sawman = sawwin->sawman;
+ window = sawwin->window;
+ dst = sawwin->dst;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( window != NULL );
+
+ D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__,
+ sawwin, DFB_RECTANGLE_VALS_FROM_REGION( region ) );
+
+ color = window->config.color;
+
+ /* Setup clipping region. */
+ clip = *region;
+
+ if (!dfb_region_rectangle_intersect( &clip, &dst ))
+ return;
+
+ /* Backup clipping region. */
+ old_clip = state->clip;
+
+ /* Use per pixel alpha blending. */
+ if (alpha_channel && (window->config.options & DWOP_ALPHACHANNEL))
+ flags |= DSDRAW_BLEND;
+
+ /* we assume the passed color is never premultiplied */
+ flags |= DSDRAW_SRC_PREMULTIPLY;
+
+ /* when not opaque, we simply adjust the color */
+ if (window->config.opacity != 0xFF) {
+ flags |= DSDRAW_BLEND;
+ color.a = (color.a * window->config.opacity) >> 8;
+ }
+
+ dfb_state_set_drawing_flags( state, flags );
+
+ if (DFB_PIXELFORMAT_IS_INDEXED( state->destination->config.format )) {
+ unsigned int i = dfb_palette_search( state->destination->palette,
+ color.r, color.g, color.b, color.a );
+ dfb_state_set_color_index( state, i );
+ }
+ else
+ dfb_state_set_color( state, &color );
+
+ D_DEBUG_AT( SaWMan_Draw, " [][] %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( &clip ) );
+
+ /* Change clipping region. */
+ dfb_state_set_clip( state, &clip );
+
+ D_DEBUG_AT( SaWMan_Draw, " => %4d,%4d-%4dx%4d\n",
+ DFB_RECTANGLE_VALS( &dst ) );
+
+ dfb_gfxcard_fillrectangles( &dst, 1, state );
+
+ /* Restore clipping region. */
+ dfb_state_set_clip( state, &old_clip );
+}
+
+void
+sawman_draw_window( SaWManTier *tier,
+ SaWManWindow *sawwin,
+ CardState *state,
+ DFBRegion *pregion,
+ bool alpha_channel )
+{
+ CoreWindow *window;
+ DFBRegion xregion = *pregion;
+ DFBRegion *region = &xregion;
+ int border;
+ bool input;
+
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ D_MAGIC_ASSERT( state, CardState );
+ DFB_REGION_ASSERT( region );
+
+ window = sawwin->window;
+
+ D_ASSERT( window != NULL );
+
+ D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__,
+ sawwin, DFB_RECTANGLE_VALS_FROM_REGION( pregion ) );
+
+ border = sawman_window_border( sawwin );
+
+ /* if input only, we only draw the border */
+ input = (window->caps & DWCAPS_INPUTONLY) || (window->config.options & DWOP_INPUTONLY);
+
+
+ if (!input &&
+ dfb_region_intersect( region,
+ sawwin->bounds.x + border,
+ sawwin->bounds.y + border,
+ sawwin->bounds.x + sawwin->bounds.w - border - 1,
+ sawwin->bounds.y + sawwin->bounds.h - border - 1 ) &&
+ dfb_region_rectangle_intersect( region, &sawwin->dst )
+ ) {
+ if( window->surface )
+ draw_window( tier, sawwin, state, region, alpha_channel );
+ else if( window->caps & DWCAPS_COLOR )
+ draw_window_color( sawwin, state, region, alpha_channel );
+ }
+
+ if (border)
+ draw_border( sawwin, state, pregion, border );
+
+ /* Reset blitting source. */
+ state->source = NULL;
+ state->modified |= SMF_SOURCE;
+}
+
+void
+sawman_draw_background( SaWManTier *tier, CardState *state, DFBRegion *region )
+{
+ DFBRectangle dst;
+ CoreWindowStack *stack;
+
+ D_MAGIC_ASSERT( tier, SaWManTier );
+ D_MAGIC_ASSERT( state, CardState );
+ DFB_REGION_ASSERT( region );
+
+ D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__, tier,
+ DFB_RECTANGLE_VALS_FROM_REGION( region ) );
+
+ stack = tier->stack;
+ D_ASSERT( stack != NULL );
+
+ D_ASSERT( stack->bg.image != NULL || (stack->bg.mode != DLBM_IMAGE &&
+ stack->bg.mode != DLBM_TILE) );
+
+ /* Initialize destination rectangle. */
+ dfb_rectangle_from_region( &dst, region );
+
+ switch (stack->bg.mode) {
+ case DLBM_COLOR: {
+ /* Set the background color. */
+ dfb_state_set_color_or_index( state, &stack->bg.color, stack->bg.color_index );
+
+ if (stack->bg.color_index < 0 || !state->destination->palette)
+ D_DEBUG_AT( SaWMan_Draw, " -> fill %02x %02x %02x %02x [%d]\n",
+ stack->bg.color.a, stack->bg.color.r, stack->bg.color.g, stack->bg.color.b,
+ stack->bg.color_index );
+ else
+ D_DEBUG_AT( SaWMan_Draw, " -> fill %02x %02x %02x %02x [%d] -> %02x %02x %02x %02x\n",
+ stack->bg.color.a, stack->bg.color.r, stack->bg.color.g, stack->bg.color.b,
+ stack->bg.color_index,
+ state->destination->palette->entries[stack->bg.color_index].a,
+ state->destination->palette->entries[stack->bg.color_index].r,
+ state->destination->palette->entries[stack->bg.color_index].g,
+ state->destination->palette->entries[stack->bg.color_index].b );
+
+ /* Simply fill the background. */
+ dfb_gfxcard_fillrectangles( &dst, 1, state );
+
+ break;
+ }
+
+ case DLBM_IMAGE: {
+ CoreSurface *bg = stack->bg.image;
+
+ /* Set blitting source. */
+ state->source = bg;
+ state->modified |= SMF_SOURCE;
+
+ /* Set blitting flags. */
+ dfb_state_set_blitting_flags( state, DSBLIT_NOFX );
+
+ /* Check the size of the background image. */
+ if (bg->config.size.w == stack->width && bg->config.size.h == stack->height) {
+ /* Simple blit for 100% fitting background image. */
+ dfb_gfxcard_blit( &dst, dst.x, dst.y, state );
+ }
+ else {
+ DFBRegion old_clip = state->clip;
+ DFBRectangle src = { 0, 0, bg->config.size.w, bg->config.size.h };
+
+ /* Change clipping region. */
+ dfb_state_set_clip( state, region );
+
+ /*
+ * Scale image to fill the whole screen
+ * clipped to the region being updated.
+ */
+ dst.x = 0;
+ dst.y = 0;
+ dst.w = stack->width;
+ dst.h = stack->height;
+
+ /* Stretch blit for non fitting background images. */
+ dfb_gfxcard_stretchblit( &src, &dst, state );
+
+ /* Restore clipping region. */
+ dfb_state_set_clip( state, &old_clip );
+ }
+
+ /* Reset blitting source. */
+ state->source = NULL;
+ state->modified |= SMF_SOURCE;
+
+ break;
+ }
+
+ case DLBM_TILE: {
+ CoreSurface *bg = stack->bg.image;
+ DFBRegion old_clip = state->clip;
+ DFBRectangle src = { 0, 0, bg->config.size.w, bg->config.size.h };
+
+ /* Set blitting source. */
+ state->source = bg;
+ state->modified |= SMF_SOURCE;
+
+ /* Set blitting flags. */
+ dfb_state_set_blitting_flags( state, DSBLIT_NOFX );
+
+ /* Change clipping region. */
+ dfb_state_set_clip( state, region );
+
+ /* Tiled blit (aligned). */
+ dfb_gfxcard_tileblit( &src,
+ (region->x1 / src.w) * src.w,
+ (region->y1 / src.h) * src.h,
+ (region->x2 / src.w + 1) * src.w,
+ (region->y2 / src.h + 1) * src.h,
+ state );
+
+ /* Restore clipping region. */
+ dfb_state_set_clip( state, &old_clip );
+
+ /* Reset blitting source. */
+ state->source = NULL;
+ state->modified |= SMF_SOURCE;
+
+ break;
+ }
+
+ case DLBM_DONTCARE:
+ break;
+
+ default:
+ D_BUG( "unknown background mode" );
+ break;
+ }
+}
+
diff --git a/Source/SaWMan/src/sawman_draw.h b/Source/SaWMan/src/sawman_draw.h
new file mode 100755
index 0000000..08208f7
--- /dev/null
+++ b/Source/SaWMan/src/sawman_draw.h
@@ -0,0 +1,55 @@
+/*
+ (c) Copyright 2001-2007 directfb.org
+ (c) Copyright 2000-2004 convergence (integrated) media GmbH.
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org> and
+ Ville Syrjälä <syrjala@sci.fi>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __SAWMAN_DRAW_H__
+#define __SAWMAN_DRAW_H__
+
+#include <directfb.h>
+
+#include <core/coretypes.h>
+
+#include <sawman_types.h>
+
+
+void sawman_draw_cursor ( CoreWindowStack *stack,
+ CardState *state,
+ DFBRegion *region,
+ int x,
+ int y );
+
+void sawman_draw_window ( SaWManTier *tier,
+ SaWManWindow *sawwin,
+ CardState *state,
+ DFBRegion *pregion,
+ bool alpha_channel );
+
+void sawman_draw_background( SaWManTier *tier,
+ CardState *state,
+ DFBRegion *region );
+
+#endif
+
diff --git a/Source/SaWMan/src/sawman_internal.h b/Source/SaWMan/src/sawman_internal.h
new file mode 100755
index 0000000..ddf304b
--- /dev/null
+++ b/Source/SaWMan/src/sawman_internal.h
@@ -0,0 +1,573 @@
+/*
+ (c) Copyright 2006-2007 directfb.org
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __SAWMAN_MANAGER_H__
+#define __SAWMAN_MANAGER_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <directfb_util.h>
+#include <directfb_version.h>
+
+#include <direct/list.h>
+#include <direct/interface.h>
+
+#include <fusion/call.h>
+#include <fusion/lock.h>
+#include <fusion/ref.h>
+#include <fusion/vector.h>
+
+#include <core/windows.h>
+#include <core/layers_internal.h> /* FIXME */
+#include <core/windows_internal.h> /* FIXME */
+
+#include "sawman_types.h"
+
+
+/* compatibility towards 1.2.x and 1.4.x DirectFB branches */
+#if DIRECTFB_MAJOR_VERSION==1
+#if DIRECTFB_MINOR_VERSION<=2
+#define OLD_COREWINDOWS_STRUCTURE
+#endif
+#endif
+
+#ifdef OLD_COREWINDOWS_STRUCTURE
+#define D_MAGIC_COREWINDOW_ASSERT(window)
+#define WINDOW_TOPLEVEL(window) (0)
+#define DWOP_FOLLOW_BOUNDS (0x00400000)
+#define WINDOW_SUBWINDOWS_COUNT(window) (0)
+#else
+#define D_MAGIC_COREWINDOW_ASSERT(window) D_MAGIC_ASSERT( (window), CoreWindow )
+#define WINDOW_TOPLEVEL(window) ((window)->toplevel)
+#define WINDOW_SUBWINDOWS_COUNT(window) ((window)->subwindows.count)
+#endif
+
+#define SAWMANWINDOWCONFIG_COPY( a, b ) { \
+ (a)->bounds = (b)->bounds; \
+ (a)->opacity = (b)->opacity; \
+ (a)->stacking = (b)->stacking; \
+ (a)->options = (b)->options; \
+ (a)->events = (b)->events; \
+ (a)->color = (b)->color; \
+ (a)->color_key = (b)->color_key; \
+ (a)->opaque = (b)->opaque; \
+ (a)->association = (b)->association; \
+ (a)->cursor_flags = (b)->cursor_flags; \
+ (a)->cursor_resolution = (b)->cursor_resolution; \
+ (a)->src_geometry = (b)->src_geometry; \
+ (a)->dst_geometry = (b)->dst_geometry; }
+
+#define SAWMANWINDOWCONFIG_COPY_IF( a, b, f ) { \
+ if (f & CWCF_POSITION) { (a)->bounds.x = (b)->bounds.x; \
+ (a)->bounds.y = (b)->bounds.y; } \
+ if (f & CWCF_SIZE) { (a)->bounds.w = (b)->bounds.w; \
+ (a)->bounds.h = (b)->bounds.h; } \
+ if (f & CWCF_OPACITY) (a)->opacity = (b)->opacity; \
+ if (f & CWCF_STACKING) (a)->stacking = (b)->stacking; \
+ if (f & CWCF_OPTIONS) (a)->options = (b)->options; \
+ if (f & CWCF_EVENTS) (a)->events = (b)->events; \
+ if (f & CWCF_COLOR) (a)->color = (b)->color; \
+ if (f & CWCF_COLOR_KEY) (a)->color_key = (b)->color_key; \
+ if (f & CWCF_OPAQUE) (a)->opaque = (b)->opaque; \
+ if (f & CWCF_ASSOCIATION) (a)->association = (b)->association; \
+ if (f & CWCF_CURSOR_FLAGS) (a)->cursor_flags = (b)->cursor_flags; \
+ if (f & CWCF_CURSOR_RESOLUTION) (a)->cursor_resolution = (b)->cursor_resolution; \
+ if (f & CWCF_SRC_GEOMETRY) (a)->src_geometry = (b)->src_geometry; \
+ if (f & CWCF_DST_GEOMETRY) (a)->dst_geometry = (b)->dst_geometry; }
+
+
+#define SAWMAN_MAX_UPDATE_REGIONS 8
+#define SAWMAN_MAX_IMPLICIT_KEYGRABS 16
+
+
+
+typedef enum {
+ SWMCID_START,
+ SWMCID_STOP,
+ SWMCID_PROCESS_ADDED,
+ SWMCID_PROCESS_REMOVED,
+ SWMCID_INPUT_FILTER,
+ SWMCID_WINDOW_PRECONFIG,
+ SWMCID_WINDOW_ADDED,
+ SWMCID_WINDOW_REMOVED,
+ SWMCID_WINDOW_RECONFIG,
+ SWMCID_WINDOW_RESTACK,
+ SWMCID_STACK_RESIZED,
+ SWMCID_SWITCH_FOCUS,
+ SWMCID_LAYER_RECONFIG,
+} SaWManCallID;
+
+typedef enum {
+ SWMSC_MIDDLE = (1 << DWSC_MIDDLE),
+ SWMSC_UPPER = (1 << DWSC_UPPER),
+ SWMSC_LOWER = (1 << DWSC_LOWER)
+} SaWManStackingClasses;
+
+typedef enum {
+ SWMUF_NONE = 0x0000,
+
+ SWMUF_FORCE_COMPLETE = 0x0001,
+ SWMUF_FORCE_INVISIBLE = 0x0002,
+ SWMUF_SCALE_REGION = 0x0004,
+ SWMUF_UPDATE_BORDER = 0x0008,
+
+ SWMUF_ALL = 0x000F
+} SaWManUpdateFlags;
+
+struct __SaWMan_SaWMan {
+ int magic;
+
+ FusionSkirmish lock;
+
+ FusionSHMPoolShared *shmpool;
+
+
+ DirectLink *processes;
+ DirectLink *windows;
+
+ FusionCall process_watch;
+
+ DFBWindowID window_ids;
+
+ SaWManScalingMode scaling_mode;
+
+ DFBDimension resolution;
+
+ FusionVector layout;
+
+ DirectLink *tiers;
+
+ DFBInputDeviceButtonMask buttons;
+ DFBInputDeviceModifierMask modifiers;
+ DFBInputDeviceLockState locks;
+
+ SaWManWindow *pointer_window; /* window grabbing the pointer */
+ SaWManWindow *keyboard_window; /* window grabbing the keyboard */
+ SaWManWindow *focused_window; /* window having the focus */
+ bool focused_window_switched; /* window having the focus */
+ SaWManWindow *focused_window_to; /* window having the focus */
+ SaWManWindow *entered_window; /* window under the pointer */
+ SaWManWindow *unselkeys_window; /* window grabbing unselected keys */
+
+ DirectLink *grabbed_keys; /* List of currently grabbed keys. */
+
+ struct {
+ DFBInputDeviceKeySymbol symbol;
+ DFBInputDeviceKeyIdentifier id;
+ int code;
+ SaWManWindow *owner;
+ } keys[SAWMAN_MAX_IMPLICIT_KEYGRABS];
+
+ struct {
+ bool present;
+
+ FusionCall call;
+
+ SaWManCallbacks callbacks;
+ void *context;
+
+ DFBInputEvent event;
+ } manager;
+
+ /* reserved area for callback stuctures */
+ struct {
+ SaWManWindowInfo info;
+ SaWManWindowReconfig reconfig;
+ DFBDimension size;
+ SaWManWindowHandle handle;
+ SaWManWindowHandle relative;
+ SaWManLayerReconfig layer_reconfig;
+ } callback;
+
+ struct {
+ CoreLayer *layer;
+ CoreLayerContext *context;
+ CoreLayerRegion *region;
+
+
+ /* Temporary motion delta until flushed by last event (without DIEF_FOLLOW) */
+ int dx; // Device coordinates
+ int dy;
+
+ SaWManWindow *confined;
+ } cursor;
+};
+
+
+typedef enum {
+ SAWMAN_TIER_UPDATE
+} SaWManTierChannels;
+
+typedef struct {
+ DFBRegion regions[SAWMAN_MAX_UPDATE_REGIONS];
+ unsigned int num_regions;
+} SaWManTierUpdate;
+
+struct __SaWMan_SaWManTier {
+ DirectLink link;
+
+ int magic;
+
+ DFBDisplayLayerID layer_id;
+ SaWManStackingClasses classes;
+
+ CoreWindowStack *stack;
+ CoreLayerContext *context;
+ CoreLayerRegion *region;
+
+ DFBDisplayLayerConfig config;
+ DFBColorKey key;
+
+ DFBDimension size; // Resolution of Tier coordinates
+
+ DFBUpdates updates;
+ DFBRegion update_regions[SAWMAN_MAX_UPDATE_REGIONS];
+ bool update_once;
+
+ bool active;
+
+ bool single_mode;
+ SaWManWindow *single_window;
+ int single_width;
+ int single_height;
+ DFBRectangle single_src;
+ DFBRectangle single_dst;
+ DFBSurfacePixelFormat single_format;
+ DFBDisplayLayerOptions single_options;
+ DFBColorKey single_key;
+
+ bool border_only;
+ DFBDisplayLayerConfig border_config;
+
+ CoreSurface *cursor_bs; /* backing store for region under cursor */
+ bool cursor_bs_valid;
+ DFBRegion cursor_region;
+ bool cursor_drawn;
+
+ int cursor_dx; //JMH to be removed
+ int cursor_dy; //JMH to be removed
+
+ FusionReactor *reactor;
+};
+
+struct __SaWMan_SaWManWindow {
+ DirectLink link;
+
+ int magic;
+
+ SaWMan *sawman;
+ FusionSHMPoolShared *shmpool;
+
+ SaWManWindow *parent;
+ CoreWindow *parent_window;
+ FusionVector children;
+
+ SaWManProcess *process;
+
+
+ DFBWindowID id;
+ DFBWindowCapabilities caps;
+ CoreWindow *window;
+
+ CoreWindowStack *stack;
+ void *stack_data;
+
+ int priority; /* derived from stacking class */
+
+ long long update_ms;
+
+ SaWManWindowFlags flags;
+
+ DFBRectangle bounds; // Tier coordinates
+
+ DFBRectangle src;
+ DFBRectangle dst;
+};
+
+struct __SaWMan_SaWManGrabbedKey {
+ DirectLink link;
+
+ DFBInputDeviceKeySymbol symbol;
+ DFBInputDeviceModifierMask modifiers;
+
+ SaWManWindow *owner;
+};
+
+typedef struct {
+ int magic;
+
+ bool active;
+
+ SaWMan *sawman;
+
+ CoreWindowStack *stack;
+} StackData;
+
+DirectResult sawman_initialize( SaWMan *sawman,
+ FusionWorld *world,
+ SaWManProcess **ret_process );
+
+DirectResult sawman_join ( SaWMan *sawman,
+ FusionWorld *world,
+ SaWManProcess **ret_process );
+
+DirectResult sawman_shutdown ( SaWMan *sawman,
+ FusionWorld *world );
+
+DirectResult sawman_leave ( SaWMan *sawman,
+ FusionWorld *world );
+
+DirectResult sawman_post_init ( SaWMan *sawman,
+ FusionWorld *world );
+
+DirectResult sawman_call ( SaWMan *sawman,
+ SaWManCallID call,
+ void *ptr );
+
+
+DirectResult sawman_register ( SaWMan *sawman,
+ const SaWManCallbacks *callbacks,
+ void *context );
+
+DirectResult sawman_switch_focus ( SaWMan *sawman,
+ SaWManWindow *to );
+
+DirectResult sawman_post_event ( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ DFBWindowEvent *event );
+
+DirectResult sawman_update_window ( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ const DFBRegion *region,
+ DFBSurfaceFlipFlags flags,
+ SaWManUpdateFlags update_flags );
+
+DirectResult sawman_showing_window ( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ bool *ret_showing );
+
+DirectResult sawman_insert_window ( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ SaWManWindow *relative,
+ bool top );
+
+DirectResult sawman_remove_window ( SaWMan *sawman,
+ SaWManWindow *sawwin );
+
+DirectResult sawman_withdraw_window( SaWMan *sawman,
+ SaWManWindow *sawwin );
+
+DirectResult sawman_update_geometry( SaWManWindow *sawwin );
+
+DirectResult sawman_set_opacity ( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ u8 opacity );
+
+DFBResult sawman_restack_window( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ SaWManWindow *relative,
+ int relation,
+ DFBWindowStackingClass stacking );
+
+DirectResult sawman_window_set_cursor_flags( SaWMan *sawman,
+ SaWManWindow *sawwin,
+ DFBWindowCursorFlags flags );
+
+DirectResult sawman_window_apply_cursor_flags( SaWMan *sawman,
+ SaWManWindow *sawwin );
+
+bool sawman_update_focus( SaWMan *sawman,
+ CoreWindowStack *stack,
+ int x,
+ int y );
+
+SaWManWindow *sawman_window_at_pointer( SaWMan *sawman,
+ CoreWindowStack *stack,
+ int x,
+ int y );
+
+void sawman_window_get_cursor_position( SaWMan *sawman,
+ CoreWindowStack *stack,
+ SaWManWindow *sawwin,
+ int *ret_x,
+ int *ret_y,
+ int *ret_cx,
+ int *ret_cy );
+
+DirectResult sawman_process_updates( SaWMan *sawman,
+ DFBSurfaceFlipFlags flags );
+
+static inline DirectResult
+sawman_lock( SaWMan *sawman )
+{
+ D_MAGIC_ASSERT( sawman, SaWMan );
+
+ return fusion_skirmish_prevail( &sawman->lock );
+}
+
+static inline DirectResult
+sawman_unlock( SaWMan *sawman )
+{
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ return fusion_skirmish_dismiss( &sawman->lock );
+}
+
+static inline int
+sawman_window_priority( const SaWManWindow *sawwin )
+{
+ const CoreWindow *window;
+
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+
+ window = sawwin->window;
+ D_ASSERT( window != NULL );
+
+ switch (window->config.stacking) {
+ case DWSC_UPPER:
+ return 2;
+
+ case DWSC_MIDDLE:
+ return 1;
+
+ case DWSC_LOWER:
+ return 0;
+
+ default:
+ D_BUG( "unknown stacking class" );
+ break;
+ }
+
+ return 0;
+}
+
+static inline int
+sawman_window_index( SaWMan *sawman,
+ SaWManWindow *sawwin )
+{
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_MAGIC_ASSERT( sawwin, SaWManWindow );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ D_ASSERT( fusion_vector_contains( &sawman->layout, sawwin ) );
+
+ return fusion_vector_index_of( &sawman->layout, sawwin );
+}
+
+static inline SaWManTier *
+sawman_tier_by_class( SaWMan *sawman,
+ DFBWindowStackingClass stacking )
+{
+ SaWManTier *tier;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( (stacking & ~3) == 0 );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ direct_list_foreach (tier, sawman->tiers) {
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ if (tier->classes & (1 << stacking))
+ break;
+ }
+
+ D_ASSERT( tier != NULL );
+
+ return tier;
+}
+
+static inline bool
+sawman_tier_by_stack( SaWMan *sawman,
+ CoreWindowStack *stack,
+ SaWManTier **ret_tier )
+{
+ SaWManTier *tier;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( stack != NULL );
+ D_ASSERT( ret_tier != NULL );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ direct_list_foreach (tier, sawman->tiers) {
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ if (tier->stack == stack) {
+ *ret_tier = tier;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static inline bool
+sawman_tier_by_layer( SaWMan *sawman,
+ DFBDisplayLayerID layer_id,
+ SaWManTier **ret_tier )
+{
+ SaWManTier *tier;
+
+ D_MAGIC_ASSERT( sawman, SaWMan );
+ D_ASSERT( ret_tier != NULL );
+ FUSION_SKIRMISH_ASSERT( &sawman->lock );
+
+ direct_list_foreach (tier, sawman->tiers) {
+ D_MAGIC_ASSERT( tier, SaWManTier );
+
+ if (tier->layer_id == layer_id) {
+ *ret_tier = tier;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int sawman_window_border( const SaWManWindow *sawwin );
+
+#ifdef OLD_COREWINDOWS_STRUCTURE
+#define SAWMAN_VISIBLE_WINDOW(w) ((!((w)->caps & DWCAPS_INPUTONLY) || sawman_window_border((w)->window_data)) && \
+ (w)->config.opacity > 0 && !DFB_WINDOW_DESTROYED(w))
+#else
+#define SAWMAN_VISIBLE_WINDOW(w) ( ( !(((w)->caps & DWCAPS_INPUTONLY) || ((w)->config.options & DWOP_INPUTONLY)) \
+ || sawman_window_border((w)->window_data)) \
+ && (w)->config.opacity > 0 \
+ && !DFB_WINDOW_DESTROYED(w) \
+ && (!(w)->toplevel || (w)->toplevel->config.opacity > 0) )
+#endif
+
+#define SAWMAN_TRANSLUCENT_WINDOW(w) ((w)->config.opacity < 0xff || \
+ (w)->config.options & (DWOP_INPUTONLY | DWOP_ALPHACHANNEL | DWOP_COLORKEYING) ||\
+ (w)->config.dst_geometry.mode != DWGM_DEFAULT ||\
+ ((w)->caps & (DWCAPS_INPUTONLY)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+