├── man ├── .gitignore ├── Makefile.am └── quartz-wm.man ├── src ├── .gitignore ├── utils.h ├── Makefile.am ├── x11-geometry.c ├── x-list.h ├── x11-geometry.h ├── frame.h ├── x-screen.h ├── dock-support-handler.m ├── utils.m ├── frame.m ├── x-window.h ├── quartz-wm.h ├── x-list.c ├── x-input.m ├── x-screen.m └── main.m ├── .gitattributes ├── lib ├── .gitignore ├── libquartz-wm-ds.apsl.dylib ├── Makefile.am └── dock-support.h ├── README.md ├── autogen.sh ├── .gitignore ├── Makefile.am ├── configure.ac └── COPYING /man/.gitignore: -------------------------------------------------------------------------------- 1 | quartz-wm.1 2 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | *.o 3 | quartz-wm 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.m diff=objc 2 | *.h diff=objc 3 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | libquartz-wm-ds.1.dylib 2 | libquartz-wm-ds.dylib 3 | -------------------------------------------------------------------------------- /lib/libquartz-wm-ds.apsl.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XQuartz/quartz-wm/HEAD/lib/libquartz-wm-ds.apsl.dylib -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Relocated ## 2 | 3 | quartz-wm is now part of gitlab.freedesktop.org. Please goto [https://gitlab.freedesktop.org/xorg/app/quartz-wm](https://gitlab.freedesktop.org/xorg/app/quartz-wm). 4 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | srcdir=`dirname $0` 4 | test -z "$srcdir" && srcdir=. 5 | 6 | ORIGDIR=`pwd` 7 | cd $srcdir 8 | 9 | autoreconf -v --install || exit 1 10 | cd $ORIGDIR || exit $? 11 | 12 | $srcdir/configure --enable-maintainer-mode "$@" 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ChangeLog 2 | INSTALL 3 | aclocal.m4 4 | autom4te.cache/ 5 | config.guess 6 | config.h 7 | config.h.in 8 | config.log 9 | config.status 10 | config.sub 11 | configure 12 | depcomp 13 | install-sh 14 | missing 15 | stamp-h1 16 | 17 | Makefile.in 18 | Makefile 19 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010 Apple Inc. All Rights Reserved. 2 | # 3 | # @APPLE_LICENSE_HEADER_START@ 4 | # 5 | # This file contains Original Code and/or Modifications of Original Code 6 | # as defined in and that are subject to the Apple Public Source License 7 | # Version 2.0 (the 'License'). You may not use this file except in 8 | # compliance with the License. Please obtain a copy of the License at 9 | # http://www.opensource.apple.com/apsl/ and read it before using this 10 | # file. 11 | # 12 | # The Original Code and all software distributed under the License are 13 | # distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | # EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | # INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 17 | # Please see the License for the specific language governing rights and 18 | # limitations under the License. 19 | # 20 | # @APPLE_LICENSE_HEADER_END@ 21 | 22 | DIST_SUBDIRS = lib src man 23 | BASE_SUBDIRS = src man 24 | 25 | if !XPLUGIN_DOCK_SUPPORT 26 | LIB_SUBDIRS = lib 27 | endif 28 | 29 | SUBDIRS = $(LIB_SUBDIRS) $(BASE_SUBDIRS) 30 | 31 | MAINTAINERCLEANFILES = ChangeLog INSTALL 32 | 33 | INSTALL: 34 | $(INSTALL_CMD) 35 | 36 | ChangeLog: 37 | $(CHANGELOG_CMD) 38 | 39 | dist-hook: ChangeLog INSTALL 40 | 41 | .PHONY: ChangeLog INSTALL 42 | -------------------------------------------------------------------------------- /man/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010-2011 Apple Inc. All Rights Reserved. 2 | # 3 | # @APPLE_LICENSE_HEADER_START@ 4 | # 5 | # This file contains Original Code and/or Modifications of Original Code 6 | # as defined in and that are subject to the Apple Public Source License 7 | # Version 2.0 (the 'License'). You may not use this file except in 8 | # compliance with the License. Please obtain a copy of the License at 9 | # http://www.opensource.apple.com/apsl/ and read it before using this 10 | # file. 11 | # 12 | # The Original Code and all software distributed under the License are 13 | # distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | # EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | # INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 17 | # Please see the License for the specific language governing rights and 18 | # limitations under the License. 19 | # 20 | # @APPLE_LICENSE_HEADER_END@ 21 | 22 | appmandir = $(APP_MAN_DIR) 23 | appman_PRE = quartz-wm.man 24 | appman_DATA = $(appman_PRE:man=$(APP_MAN_SUFFIX)) 25 | 26 | EXTRA_DIST = $(appman_PRE) 27 | CLEANFILES = $(appman_DATA) 28 | SUFFIXES = .$(APP_MAN_SUFFIX) .man 29 | 30 | MAN_SUBSTS += -e 's|__bundle_id_prefix__|$(BUNDLE_ID_PREFIX)|g' 31 | 32 | .man.$(APP_MAN_SUFFIX): 33 | $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@ 34 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | /* utils.h 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifndef UTILS_H 26 | #define UTILS_H 27 | 28 | #include 29 | 30 | #define Cursor X_Cursor 31 | #include 32 | #undef Cursor 33 | 34 | extern int x_get_property (Window xwindow_id, Atom atom, long *dest, 35 | unsigned int dest_size, unsigned int min_items); 36 | extern NSString *x_get_string_property (Window xwindow_id, Atom atom); 37 | 38 | #endif /* UTILS_H */ 39 | -------------------------------------------------------------------------------- /lib/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012 Apple Inc. All Rights Reserved. 2 | # 3 | # @APPLE_LICENSE_HEADER_START@ 4 | # 5 | # This file contains Original Code and/or Modifications of Original Code 6 | # as defined in and that are subject to the Apple Public Source License 7 | # Version 2.0 (the 'License'). You may not use this file except in 8 | # compliance with the License. Please obtain a copy of the License at 9 | # http://www.opensource.apple.com/apsl/ and read it before using this 10 | # file. 11 | # 12 | # The Original Code and all software distributed under the License are 13 | # distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | # EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | # INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 17 | # Please see the License for the specific language governing rights and 18 | # limitations under the License. 19 | # 20 | # @APPLE_LICENSE_HEADER_END@ 21 | 22 | DIST_LIB = libquartz-wm-ds.apsl.dylib 23 | LIBRARY_BASENAME = libquartz-wm-ds.1.dylib 24 | LIBRARY_SYMLINK = libquartz-wm-ds.dylib 25 | 26 | all : $(LIBRARY_SYMLINK) 27 | 28 | $(LIBRARY_SYMLINK) : $(LIBRARY_BASENAME) 29 | rm -f $@ 30 | ln -s $^ $@ 31 | 32 | $(LIBRARY_BASENAME) : $(DIST_LIB) 33 | cp $^ $@ 34 | install_name_tool -id $(libdir)/$@ $@ 35 | 36 | install-exec-hook : $(LIBRARY_BASENAME) 37 | install -d -m 755 $(DESTDIR)$(libdir) 38 | install -m 755 $(LIBRARY_BASENAME) $(DESTDIR)$(libdir) 39 | rm -f $(DESTDIR)$(libdir)/$(LIBRARY_SYMLINK) 40 | ln -s $(LIBRARY_BASENAME) $(DESTDIR)$(libdir)/$(LIBRARY_SYMLINK) 41 | 42 | CLEANFILES = $(LIBRARY_SYMLINK) $(LIBRARY_BASENAME) 43 | 44 | EXTRA_DIST = dock-support.h $(DIST_LIB) 45 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010 Apple Inc. All Rights Reserved. 2 | # 3 | # @APPLE_LICENSE_HEADER_START@ 4 | # 5 | # This file contains Original Code and/or Modifications of Original Code 6 | # as defined in and that are subject to the Apple Public Source License 7 | # Version 2.0 (the 'License'). You may not use this file except in 8 | # compliance with the License. Please obtain a copy of the License at 9 | # http://www.opensource.apple.com/apsl/ and read it before using this 10 | # file. 11 | # 12 | # The Original Code and all software distributed under the License are 13 | # distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | # EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | # INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 17 | # Please see the License for the specific language governing rights and 18 | # limitations under the License. 19 | # 20 | # @APPLE_LICENSE_HEADER_END@ 21 | 22 | bin_PROGRAMS = quartz-wm 23 | 24 | AM_CPPFLAGS = -I$(top_srcdir)/lib -DXP_NO_X_HEADERS 25 | AM_OBJCFLAGS = $(QUARTZWM_CFLAGS) $(CWARNFLAGS) 26 | AM_CFLAGS = $(QUARTZWM_CFLAGS) $(CWARNFLAGS) 27 | 28 | quartz_wm_LDFLAGS = $(QUARTZWM_LIBS) \ 29 | -framework AppKit 30 | 31 | if XPLUGIN_DOCK_SUPPORT 32 | quartz_wm_LDFLAGS += -lXplugin 33 | else 34 | quartz_wm_LDFLAGS += -L$(top_builddir)/lib -lquartz-wm-ds 35 | endif 36 | 37 | quartz_wm_SOURCES = \ 38 | dock-support-handler.m \ 39 | frame.h \ 40 | frame.m \ 41 | main.m \ 42 | quartz-wm.h \ 43 | utils.h \ 44 | utils.m \ 45 | x-input.m \ 46 | x-list.c \ 47 | x-list.h \ 48 | x-screen.h \ 49 | x-screen.m \ 50 | x-window.h \ 51 | x-window.m \ 52 | x11-geometry.c \ 53 | x11-geometry.h 54 | -------------------------------------------------------------------------------- /src/x11-geometry.c: -------------------------------------------------------------------------------- 1 | /* x11-geometry.c 2 | * 3 | * Copyright (c) 2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include "x11-geometry.h" 30 | 31 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 32 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 33 | 34 | X11Rect X11EmptyRect = {0, 0, 0, 0}; 35 | 36 | X11Rect X11RectIntersection(X11Rect a, X11Rect b) { 37 | pixman_box32_t ba, bb, f; 38 | 39 | ba.x1 = a.x; 40 | ba.y1 = a.y; 41 | ba.x2 = a.x + a.width; 42 | ba.y2 = a.y + a.height; 43 | 44 | bb.x1 = b.x; 45 | bb.y1 = b.y; 46 | bb.x2 = b.x + b.width; 47 | bb.y2 = b.y + b.height; 48 | 49 | f.x1 = MAX(ba.x1, bb.x1); 50 | f.y1 = MAX(ba.y1, bb.y1); 51 | f.x2 = MIN(ba.x2, bb.x2); 52 | f.y2 = MIN(ba.y2, bb.y2); 53 | 54 | if(f.x1 <= f.x2 && f.y1 <= f.y2) { 55 | return X11RectMake(f.x1, f.y1, f.x2 - f.x1, f.y2 - f.y1); 56 | } else { 57 | return X11EmptyRect; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl Copyright (c) 2010 Apple Inc. All Rights Reserved. 2 | dnl 3 | dnl @APPLE_LICENSE_HEADER_START@ 4 | dnl 5 | dnl This file contains Original Code and/or Modifications of Original Code 6 | dnl as defined in and that are subject to the Apple Public Source License 7 | dnl Version 2.0 (the 'License'). You may not use this file except in 8 | dnl compliance with the License. Please obtain a copy of the License at 9 | dnl http://www.opensource.apple.com/apsl/ and read it before using this 10 | dnl file. 11 | dnl 12 | dnl The Original Code and all software distributed under the License are 13 | dnl distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 | dnl EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 | dnl INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 | dnl FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 17 | dnl Please see the License for the specific language governing rights and 18 | dnl limitations under the License. 19 | dnl 20 | dnl @APPLE_LICENSE_HEADER_END@ 21 | 22 | AC_PREREQ([2.61]) 23 | AC_INIT(quartz-wm,[1.3.2], [http://xquartz.macosforge.org],quartz-wm) 24 | AM_INIT_AUTOMAKE([foreign dist-bzip2 dist-xz]) 25 | AM_MAINTAINER_MODE 26 | 27 | AC_CONFIG_HEADERS([config.h]) 28 | 29 | # Require xorg-macros: XORG_DEFAULT_OPTIONS 30 | m4_ifndef([XORG_MACROS_VERSION], 31 | [m4_fatal([must install xorg-macros 1.3 or later before running autoconf/autogen])]) 32 | XORG_MACROS_VERSION(1.3) 33 | XORG_DEFAULT_OPTIONS 34 | 35 | AC_PROG_CC 36 | AC_PROG_OBJC 37 | AC_PROG_INSTALL 38 | 39 | # Checks for pkg-config packages 40 | PKG_CHECK_MODULES(QUARTZWM, [applewm >= 1.4] pixman-1 x11 xext xinerama xrandr xproto >= 7.0.17) 41 | AC_SUBST(QUARTZWM_CFLAGS) 42 | AC_SUBST(QUARTZWM_LIBS) 43 | 44 | AC_ARG_WITH(bundle-id-prefix, AS_HELP_STRING([--with-bundle-id-prefix=PATH], [Prefix to use for bundle identifiers (default: org.x)]), 45 | [BUNDLE_ID_PREFIX="${withval}"], 46 | [BUNDLE_ID_PREFIX="org.x"]) 47 | AC_SUBST([BUNDLE_ID_PREFIX]) 48 | AC_DEFINE_UNQUOTED(BUNDLE_ID_PREFIX, "$BUNDLE_ID_PREFIX", [Prefix to use for bundle identifiers]) 49 | 50 | AC_ARG_ENABLE(xplugin-dock-support, AS_HELP_STRING([--enable-xplugin-dock-support], [Enable using libXplugin directly for dock support (default: NO)]), 51 | [XPLUGIN_DOCK_SUPPORT="${enableval}"], 52 | [XPLUGIN_DOCK_SUPPORT="no"]) 53 | AC_SUBST([XPLUGIN_DOCK_SUPPORT]) 54 | if test "x$XPLUGIN_DOCK_SUPPORT" = "xyes"; then 55 | AC_DEFINE(XPLUGIN_DOCK_SUPPORT, 1, [Use libXplugin directly for dock support]) 56 | fi 57 | AM_CONDITIONAL(XPLUGIN_DOCK_SUPPORT, [test "x$XPLUGIN_DOCK_SUPPORT" = "xyes"]) 58 | 59 | AC_OUTPUT([Makefile 60 | lib/Makefile 61 | src/Makefile 62 | man/Makefile]) 63 | -------------------------------------------------------------------------------- /src/x-list.h: -------------------------------------------------------------------------------- 1 | /* x-list.h -- simple list type 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifndef X_LIST_H 26 | #define X_LIST_H 1 27 | 28 | /* This is just a cons. */ 29 | 30 | typedef struct x_list_struct x_list; 31 | 32 | struct x_list_struct { 33 | void *data; 34 | x_list *next; 35 | }; 36 | 37 | #ifndef X_PFX 38 | # define X_PFX(x) x_ ## x 39 | #endif 40 | 41 | #ifndef X_EXTERN 42 | # define X_EXTERN __private_extern__ 43 | #endif 44 | 45 | X_EXTERN void X_PFX (list_free_1) (x_list *node); 46 | X_EXTERN x_list *X_PFX (list_prepend) (x_list *lst, void *data); 47 | 48 | X_EXTERN x_list *X_PFX (list_append) (x_list *lst, void *data); 49 | X_EXTERN x_list *X_PFX (list_remove) (x_list *lst, void *data); 50 | X_EXTERN void X_PFX (list_free) (x_list *lst); 51 | X_EXTERN x_list *X_PFX (list_pop) (x_list *lst, void **data_ret); 52 | 53 | X_EXTERN x_list *X_PFX (list_copy) (x_list *lst); 54 | X_EXTERN x_list *X_PFX (list_reverse) (x_list *lst); 55 | X_EXTERN x_list *X_PFX (list_find) (x_list *lst, void *data); 56 | X_EXTERN x_list *X_PFX (list_nth) (x_list *lst, int n); 57 | X_EXTERN x_list *X_PFX (list_filter) (x_list *src, 58 | int (*pred) (void *item, void *data), 59 | void *data); 60 | X_EXTERN x_list *X_PFX (list_map) (x_list *src, 61 | void *(*fun) (void *item, void *data), 62 | void *data); 63 | 64 | X_EXTERN unsigned int X_PFX (list_length) (x_list *lst); 65 | X_EXTERN void X_PFX (list_foreach) (x_list *lst, void (*fun) 66 | (void *data, void *user_data), 67 | void *user_data); 68 | 69 | X_EXTERN x_list *X_PFX (list_sort) (x_list *lst, int (*less) (const void *, 70 | const void *)); 71 | 72 | #endif /* X_LIST_H */ 73 | -------------------------------------------------------------------------------- /src/x11-geometry.h: -------------------------------------------------------------------------------- 1 | /* x11-geometry.h 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifndef __X11_GEOMETRY_H__ 26 | #define __X11_GEOMETRY_H__ 27 | 28 | #include 29 | #include 30 | 31 | typedef pixman_rectangle32_t X11Rect; 32 | typedef struct {int32_t x; int32_t y;} X11Point; 33 | typedef struct {int32_t width; int32_t height;} X11Size; 34 | typedef pixman_region32_t X11Region; 35 | 36 | extern X11Rect X11EmptyRect; 37 | 38 | static inline X11Rect X11RectMake(int32_t x, int32_t y, int32_t w, int32_t h) { 39 | X11Rect ret; 40 | ret.x = x; 41 | ret.y = y; 42 | ret.width = w; 43 | ret.height = h; 44 | return ret; 45 | } 46 | 47 | static inline X11Point X11PointMake(int32_t x, int32_t y) { 48 | X11Point ret; 49 | ret.x = x; 50 | ret.y = y; 51 | return ret; 52 | } 53 | 54 | static inline X11Size X11SizeMake(int32_t width, int32_t height) { 55 | X11Size ret; 56 | ret.width = width; 57 | ret.height = height; 58 | return ret; 59 | } 60 | 61 | static inline X11Point X11RectOrigin(X11Rect r) { 62 | return X11PointMake(r.x, r.y); 63 | } 64 | 65 | static inline X11Size X11RectSize(X11Rect r) { 66 | return X11SizeMake(r.width, r.height); 67 | } 68 | 69 | static inline bool X11PointEqualToPoint(X11Point a, X11Point b) { 70 | return (a.x == b.x && a.y == b.y); 71 | } 72 | 73 | static inline bool X11SizeEqualToSize(X11Size a, X11Size b) { 74 | return (a.width == b.width && a.height == b.height); 75 | } 76 | 77 | static inline bool X11RectEqualToRect(X11Rect a, X11Rect b) { 78 | return (a.x == b.x && a.y == b.y && 79 | a.width == b.width && a.height == b.height); 80 | } 81 | 82 | static inline bool X11RectContainsPoint(X11Rect r, X11Point p) { 83 | return (r.x <= p.x && p.x <= r.x + r.width && 84 | r.y <= p.y && p.y <= r.y + r.height); 85 | } 86 | 87 | static inline bool X11RectIsEmpty(X11Rect r) { 88 | return X11RectEqualToRect(r, X11EmptyRect); 89 | } 90 | 91 | extern X11Rect X11RectIntersection(X11Rect a, X11Rect b); 92 | 93 | #endif /* __X11_GEOMETRY_H__ */ 94 | -------------------------------------------------------------------------------- /src/frame.h: -------------------------------------------------------------------------------- 1 | /* frame.h 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifndef FRAME_H 26 | #define FRAME_H 1 27 | 28 | #include 29 | 30 | #define XP_NO_X_HEADERS 1 31 | #include 32 | 33 | #define Cursor X_Cursor 34 | #include 35 | #undef Cursor 36 | 37 | #include "x11-geometry.h" 38 | 39 | #if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION < 4 40 | #warning "Old libXplugin version detected. Some features may not be supported." 41 | 42 | typedef enum xp_frame_class_enum xp_frame_class; 43 | typedef enum xp_frame_attr_enum xp_frame_attr; 44 | 45 | #define XP_FRAME_CLASS_DECOR_LARGE XP_FRAME_CLASS_DOCUMENT 46 | #define XP_FRAME_CLASS_DECOR_SMALL XP_FRAME_CLASS_UTILITY 47 | #define XP_FRAME_CLASS_DECOR_NONE XP_FRAME_CLASS_SPLASH 48 | #define XP_FRAME_CLASS_BEHAVIOR_MANAGED (1 << 15) 49 | #define XP_FRAME_CLASS_BEHAVIOR_TRANSIENT (1 << 16) 50 | #define XP_FRAME_CLASS_BEHAVIOR_STATIONARY (1 << 17) 51 | 52 | #define XP_FRAME_ATTR_ACTIVE XP_FRAME_ACTIVE 53 | #define XP_FRAME_ATTR_URGENT XP_FRAME_URGENT 54 | #define XP_FRAME_ATTR_TITLE XP_FRAME_TITLE 55 | #define XP_FRAME_ATTR_PRELIGHT XP_FRAME_PRELIGHT 56 | #define XP_FRAME_ATTR_SHADED XP_FRAME_SHADED 57 | #define XP_FRAME_ATTR_CLOSE_BOX XP_FRAME_CLOSE_BOX 58 | #define XP_FRAME_ATTR_COLLAPSE XP_FRAME_COLLAPSE 59 | #define XP_FRAME_ATTR_ZOOM XP_FRAME_ZOOM 60 | #define XP_FRAME_ATTR_CLOSE_BOX_CLICKED XP_FRAME_CLOSE_BOX_CLICKED 61 | #define XP_FRAME_ATTR_COLLAPSE_BOX_CLICKED XP_FRAME_COLLAPSE_BOX_CLICKED 62 | #define XP_FRAME_ATTR_ZOOM_BOX_CLICKED XP_FRAME_ZOOM_BOX_CLICKED 63 | #define XP_FRAME_ATTR_GROW_BOX XP_FRAME_GROW_BOX 64 | 65 | #define XP_FRAME_ATTRS_ANY_BUTTON XP_FRAME_ANY_BUTTON 66 | #define XP_FRAME_ATTRS_ANY_CLICKED XP_FRAME_ANY_CLICKED 67 | #define XP_FRAME_ATTRS_POINTER XP_FRAME_POINTER_ATTRS 68 | #endif 69 | 70 | extern void draw_frame (int screen, Window xwindow_id, X11Rect outer_r, 71 | X11Rect inner_r, xp_frame_class class, 72 | xp_frame_attr attr, CFStringRef title, 73 | int shortcut_index); 74 | extern int frame_titlebar_height (xp_frame_class class); 75 | extern X11Rect frame_tracking_rect (X11Rect outer_r, X11Rect inner_r, 76 | xp_frame_class class); 77 | extern X11Rect frame_growbox_rect (X11Rect outer_r, X11Rect inner_r, 78 | xp_frame_class class); 79 | extern unsigned int frame_hit_test (X11Rect outer_r, X11Rect inner_r, 80 | xp_frame_class class, X11Point p); 81 | 82 | #endif /* XP_FRAME_H */ 83 | -------------------------------------------------------------------------------- /src/x-screen.h: -------------------------------------------------------------------------------- 1 | /* x-screen.h 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifndef X_SCREEN_H 26 | #define X_SCREEN_H 1 27 | 28 | #import 29 | 30 | #define Cursor X_Cursor 31 | #include 32 | #undef Cursor 33 | 34 | #include "x-list.h" 35 | #include "x11-geometry.h" 36 | #include "dock-support.h" 37 | 38 | @class x_window; 39 | 40 | @interface x_screen : NSObject 41 | { 42 | @public 43 | Screen *_screen; 44 | int _id; 45 | Window _root; 46 | int _x, _y; 47 | int _width, _height; 48 | 49 | int _depth; 50 | Visual *_visual; 51 | Colormap _colormap; 52 | unsigned long _black_pixel; 53 | 54 | X11Rect *_heads; 55 | int _head_count; 56 | X11Rect _main_head; 57 | 58 | X11Region * _screen_region; 59 | 60 | x_list *_window_list; 61 | x_list *_stacking_list; 62 | 63 | Window _net_wm_window; 64 | 65 | unsigned _updates_disabled :1; 66 | } 67 | 68 | - (void) set_root_property:(const char *)name type:(const char *)type 69 | length:(int)length data:(const long *)data; 70 | - init_with_screen_id:(int)id; 71 | - (void) update_geometry; 72 | - (void) focus_topmost:(Time)timestamp; 73 | - (x_list *) stacking_order:(x_list *)group; 74 | - (void) raise_windows:(id *)array count:(size_t)n; 75 | - (void) adopt_window:(Window)xwindow_id initializing:(BOOL)flag; 76 | - (void) remove_window:(x_window *)w safe:(BOOL)safe; 77 | - (void) remove_window:(x_window *)w; 78 | - (void) remove_callback:(NSTimer *)timer; 79 | - (void) window_hidden:(x_window *)w; 80 | - (void) adopt_windows; 81 | - (void) unadopt_windows; 82 | - (void) error_shutdown; 83 | - get_window:(Window)xwindow_id; 84 | - get_window_by_osx_id:(xp_native_window_id)id; 85 | - (X11Rect) validate_window_position:(X11Rect)r titlebar_height:(size_t)titlebar_height; 86 | - (X11Rect) zoomed_rect:(X11Point)p; 87 | - (X11Rect) zoomed_rect; 88 | - (X11Point) center_on_head:(X11Point)p; 89 | - (void) disable_update; 90 | - (void) reenable_update; 91 | - (void) raise_all; 92 | - (void) hide_all; 93 | - (void) show_all:(BOOL)flag; 94 | - (void) foreach_window:(SEL)selector; 95 | - find_window_at:(X11Point)p slop:(int)epsilon; 96 | 97 | /* Convert geometry on this screen */ 98 | - (X11Point) CGToX11Point:(CGPoint)p; 99 | - (X11Point) NSToX11Point:(NSPoint)p; 100 | - (X11Rect) CGToX11Rect:(CGRect)r; 101 | - (X11Rect) NSToX11Rect:(NSRect)r; 102 | - (CGPoint) X11ToCGPoint:(X11Point)p; 103 | - (NSPoint) X11ToNSPoint:(X11Point)p; 104 | - (CGRect) X11ToCGRect:(X11Rect)r; 105 | - (NSRect) X11ToNSRect:(X11Rect)r; 106 | 107 | @end 108 | 109 | #endif /* X_SCREEN_H */ 110 | -------------------------------------------------------------------------------- /src/dock-support-handler.m: -------------------------------------------------------------------------------- 1 | /* dock-support-handler.m 2 | * 3 | * Copyright (c) 2012 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include 30 | #include 31 | 32 | #include "quartz-wm.h" 33 | #include "x-list.h" 34 | #include "x-window.h" 35 | 36 | #include "dock-support.h" 37 | 38 | void dock_event_handler(xp_dock_event *event) { 39 | x_list *s_node = NULL, *w_node = NULL; 40 | x_window *w = NULL; 41 | x_screen *s = NULL; 42 | xp_native_window_id *native_wid; 43 | 44 | switch (event->type) { 45 | case XP_DOCK_EVENT_RESTORE_ALL_WINDOWS: 46 | for (s_node = screen_list; s_node != NULL; s_node = s_node->next) { 47 | s = s_node->data; 48 | for (w_node = s->_window_list; w_node != NULL; w_node = w_node->next) { 49 | w = w_node->data; 50 | if (w->_minimized) { 51 | DB(" restoring window wid:%x\n", [w get_osx_id]); 52 | [w do_uncollapse_and_tell_dock:FALSE]; 53 | } 54 | } 55 | } 56 | break; 57 | case XP_DOCK_EVENT_RESTORE_WINDOWS: 58 | case XP_DOCK_EVENT_SELECT_WINDOWS: 59 | case XP_DOCK_EVENT_RESTORE_DONE: 60 | case XP_DOCK_EVENT_MINIMIZE_DONE: 61 | if (event->type == XP_DOCK_EVENT_RESTORE_WINDOWS || 62 | event->type == XP_DOCK_EVENT_SELECT_WINDOWS) 63 | XAppleWMSetFrontProcess (x_dpy); 64 | 65 | for (native_wid = event->windows; *native_wid != XP_NULL_NATIVE_WINDOW_ID; native_wid++) { 66 | w = x_get_window_by_osx_id (*native_wid); 67 | if (w == NULL) { 68 | DB("Invalid native window id: %u\n", *native_wid); 69 | return; 70 | } 71 | 72 | switch (event->type) { 73 | case XP_DOCK_EVENT_RESTORE_WINDOWS: 74 | [w do_uncollapse_and_tell_dock:FALSE]; 75 | [w activate:CurrentTime]; 76 | break; 77 | case XP_DOCK_EVENT_SELECT_WINDOWS: 78 | [w activate:CurrentTime]; 79 | break; 80 | case XP_DOCK_EVENT_RESTORE_DONE: 81 | [w uncollapse_finished:event->success]; 82 | break; 83 | case XP_DOCK_EVENT_MINIMIZE_DONE: 84 | [w collapse_finished:event->success]; 85 | break; 86 | default: 87 | break; 88 | } 89 | } 90 | XFlush (x_dpy); 91 | break; 92 | default: 93 | break; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/utils.m: -------------------------------------------------------------------------------- 1 | /* utils.m 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include "utils.h" 30 | #include "quartz-wm.h" 31 | 32 | #include 33 | 34 | int 35 | x_get_property (Window xwindow_id, Atom atom, long *dest, 36 | unsigned int dest_size, unsigned int min_items) 37 | { 38 | Atom type; 39 | int format; 40 | unsigned int i; 41 | unsigned long nitems; 42 | unsigned char *data = 0; 43 | int ret = 0; 44 | 45 | do { 46 | long long_length = 32; 47 | u_long bytes_after; 48 | while (1) 49 | { 50 | if (data != NULL) 51 | XFree (data); 52 | 53 | if (XGetWindowProperty (x_dpy, xwindow_id, atom, 0, long_length, False, 54 | AnyPropertyType, &type, &format, 55 | &nitems, &bytes_after, &data) != Success) 56 | return 0; 57 | if (type == None) 58 | return 0; 59 | if (bytes_after == 0) 60 | break; 61 | long_length += (bytes_after / sizeof(unsigned long)) + 1; 62 | } 63 | } while (0); 64 | 65 | if (format == 32 && nitems >= min_items) 66 | { 67 | for (i = 0; i < MIN (nitems, dest_size); i++) 68 | dest[i] = ((unsigned long *) data)[i]; 69 | ret = i; 70 | } 71 | 72 | XFree (data); 73 | 74 | return ret; 75 | } 76 | 77 | NSString * 78 | x_get_string_property (Window xwindow_id, Atom atom) 79 | { 80 | Atom type; 81 | int format; 82 | unsigned long nitems; 83 | unsigned char *data = 0; 84 | NSString *ret = nil; 85 | 86 | do { 87 | long long_length = 32; 88 | u_long bytes_after; 89 | while (1) 90 | { 91 | if (data != NULL) 92 | XFree (data); 93 | 94 | if (XGetWindowProperty (x_dpy, xwindow_id, atom, 0, long_length, False, 95 | AnyPropertyType, &type, &format, 96 | &nitems, &bytes_after, &data) != Success) 97 | return nil; 98 | if (type == None) 99 | return nil; 100 | if (bytes_after == 0) 101 | break; 102 | long_length += (bytes_after / sizeof(unsigned long)) + 1; 103 | } 104 | } while (0); 105 | 106 | if (format == 8) { 107 | if (type == atoms.utf8_string) 108 | ret = [NSString stringWithUTF8String:(char *) data]; 109 | else 110 | ret = [NSString stringWithCString:(char *) data encoding:NSASCIIStringEncoding]; 111 | } 112 | 113 | XFree (data); 114 | 115 | return ret; 116 | } 117 | -------------------------------------------------------------------------------- /lib/dock-support.h: -------------------------------------------------------------------------------- 1 | /* dock-support.h 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifndef __DOCK_SUPPORT_H__ 26 | #define __DOCK_SUPPORT_H__ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #ifdef XPLUGIN_DOCK_SUPPORT 33 | 34 | #if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION < 5 35 | #error "The installed version of libXplugin is not recent enough to support quartz-wm. Please reconfigure and use the provided libquartz-wm-ds instead." 36 | #endif 37 | 38 | #define qwm_dock_get_orientation xp_dock_get_orientation 39 | #define qwm_dock_get_rect xp_dock_get_rect 40 | #define qwm_dock_is_window_visible xp_dock_is_window_visible 41 | #define qwm_dock_minimize_item_with_title_async xp_dock_minimize_item_with_title_async 42 | #define qwm_dock_restore_item_async xp_dock_restore_item_async 43 | #define qwm_dock_remove_item xp_dock_remove_item 44 | #define qwm_dock_drag_begin xp_dock_drag_begin 45 | #define qwm_dock_drag_end xp_dock_drag_end 46 | #define qwm_dock_event_set_handler xp_dock_event_set_handler 47 | 48 | static inline void qwm_dock_init(bool only_proxy) { 49 | int options = XP_IN_BACKGROUND; 50 | 51 | if (!only_proxy) 52 | options |= XP_DOCK_SUPPORT; 53 | xp_init(options); 54 | } 55 | 56 | #else 57 | 58 | /* If our Xplugin headers aren't new enough, provide missing types */ 59 | #if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION < 5 60 | typedef unsigned int xp_native_window_id; 61 | 62 | #define XP_NULL_NATIVE_WINDOW_ID ((xp_native_window_id)0) 63 | 64 | /* Dock location */ 65 | enum xp_dock_orientation_enum { 66 | XP_DOCK_ORIENTATION_BOTTOM = 2, 67 | XP_DOCK_ORIENTATION_LEFT = 3, 68 | XP_DOCK_ORIENTATION_RIGHT = 4, 69 | }; 70 | typedef enum xp_dock_orientation_enum xp_dock_orientation; 71 | 72 | /* Event handling */ 73 | typedef enum { 74 | XP_DOCK_EVENT_RESTORE_ALL_WINDOWS = 1, 75 | XP_DOCK_EVENT_RESTORE_WINDOWS = 2, 76 | XP_DOCK_EVENT_SELECT_WINDOWS = 3, 77 | XP_DOCK_EVENT_RESTORE_DONE = 4, 78 | XP_DOCK_EVENT_MINIMIZE_DONE = 5, 79 | } xp_dock_event_type; 80 | 81 | typedef struct { 82 | xp_dock_event_type type; 83 | 84 | /* XP_NULL_NATIVE_WINDOW_ID terminated list of windows affected by this event */ 85 | xp_native_window_id *windows; 86 | 87 | /* YES if the event was successful (for XP_DOCK_EVENT_RESTORE_DONE and XP_DOCK_EVENT_MINIMIZE_DONE) */ 88 | xp_bool success; 89 | } xp_dock_event; 90 | 91 | typedef void (*xp_dock_event_handler)(xp_dock_event *event); 92 | #endif 93 | 94 | extern xp_dock_orientation qwm_dock_get_orientation(void); 95 | extern xp_box qwm_dock_get_rect(void); 96 | 97 | /* Window Visibility */ 98 | extern xp_error qwm_dock_is_window_visible(xp_native_window_id osxwindow_id, xp_bool *is_visible); 99 | 100 | /* Minimize / Restore */ 101 | extern xp_error qwm_dock_minimize_item_with_title_async(xp_native_window_id osxwindow_id, const char * title); 102 | extern xp_error qwm_dock_restore_item_async(xp_native_window_id osxwindow_id); 103 | extern xp_error qwm_dock_remove_item(xp_native_window_id osxwindow_id); 104 | 105 | /* Window dragging */ 106 | extern xp_error qwm_dock_drag_begin(xp_native_window_id osxwindow_id); 107 | extern xp_error qwm_dock_drag_end(xp_native_window_id osxwindow_id); 108 | 109 | /* Initialization */ 110 | extern void qwm_dock_init(bool only_proxy); 111 | extern void qwm_dock_event_set_handler(xp_dock_event_handler new_handler); 112 | 113 | #endif /* XPLUGIN_DOCK_SUPPORT */ 114 | #endif /* __DOCK_SUPPORT_H__ */ 115 | -------------------------------------------------------------------------------- /src/frame.m: -------------------------------------------------------------------------------- 1 | /* frame.m 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include "frame.h" 30 | #include "quartz-wm.h" 31 | #include 32 | 33 | int 34 | frame_titlebar_height (xp_frame_class class) 35 | { 36 | short x, y, w, h; 37 | 38 | XAppleWMFrameGetRect (x_dpy, class, XP_FRAME_RECT_TITLEBAR, 39 | 0, 0, 0, 0, 0, 0, 0, 0, &x, &y, &w, &h); 40 | 41 | return h; 42 | } 43 | 44 | void 45 | draw_frame (int screen, Window xwindow_id, X11Rect outer_r, X11Rect inner_r, 46 | xp_frame_class class, xp_frame_attr attr, CFStringRef title, 47 | int shortcut_index) 48 | { 49 | unsigned char title_bytes[512]; 50 | CFIndex title_length; 51 | size_t prefix_length = 0; 52 | 53 | if (show_shortcut && enable_key_equivalents) 54 | { 55 | if (shortcut_index > 0) 56 | { 57 | // E2 8C 98 = PLACE OF INTEREST SIGN 58 | snprintf((char *)title_bytes, sizeof title_bytes, "\xE2\x8C\x98%d%s", 59 | shortcut_index, title == NULL ? "" : " - "); 60 | 61 | prefix_length = strlen((char *)title_bytes); 62 | } 63 | } 64 | 65 | if (title == NULL) 66 | title_length = 0; 67 | else 68 | { 69 | /* FIXME: kind of lame */ 70 | CFStringGetBytes (title, CFRangeMake (0, CFStringGetLength (title)), 71 | kCFStringEncodingUTF8, 0, 72 | FALSE, title_bytes + prefix_length, 73 | sizeof (title_bytes) - prefix_length, 74 | &title_length); 75 | } 76 | 77 | title_length += prefix_length; 78 | 79 | DB("id: 0x%ld outer_r: (%d,%d %dx%d) inner_r: (%d,%d %dx%d) class: 0x%d attr: 0x%d title: %s", 80 | xwindow_id, outer_r.x, outer_r.y, outer_r.width, outer_r.height, 81 | inner_r.x, inner_r.y, inner_r.width, inner_r.height, class, attr, 82 | title_length ? (char *)title_bytes : "(none)"); 83 | 84 | XAppleWMFrameDraw (x_dpy, screen, xwindow_id, class, attr, 85 | inner_r.x, inner_r.y, 86 | inner_r.width, inner_r.height, 87 | outer_r.x, outer_r.y, 88 | outer_r.width, outer_r.height, 89 | title_length, title_bytes); 90 | } 91 | 92 | X11Rect 93 | frame_tracking_rect (X11Rect outer_r, X11Rect inner_r, xp_frame_class class) 94 | { 95 | short x, y, w, h; 96 | 97 | XAppleWMFrameGetRect (x_dpy, class, XP_FRAME_RECT_TRACKING, 98 | inner_r.x, inner_r.y, 99 | inner_r.width, inner_r.height, 100 | outer_r.x, outer_r.y, 101 | outer_r.width, outer_r.height, 102 | &x, &y, &w, &h); 103 | 104 | return X11RectMake (x, y, w, h); 105 | } 106 | 107 | X11Rect 108 | frame_growbox_rect (X11Rect outer_r, X11Rect inner_r, xp_frame_class class) 109 | { 110 | short x, y, w, h; 111 | 112 | XAppleWMFrameGetRect (x_dpy, class, XP_FRAME_RECT_GROWBOX, 113 | inner_r.x, inner_r.y, 114 | inner_r.width, inner_r.height, 115 | outer_r.x, outer_r.y, 116 | outer_r.width, outer_r.height, 117 | &x, &y, &w, &h); 118 | 119 | return X11RectMake (x, y, w, h); 120 | } 121 | 122 | unsigned int 123 | frame_hit_test (X11Rect outer_r, X11Rect inner_r, unsigned int class, X11Point p) 124 | { 125 | return XAppleWMFrameHitTest (x_dpy, class, p.x, p.y, 126 | inner_r.x, inner_r.y, 127 | inner_r.width, inner_r.height, 128 | outer_r.x, outer_r.y, 129 | outer_r.width, outer_r.height); 130 | } 131 | -------------------------------------------------------------------------------- /man/quartz-wm.man: -------------------------------------------------------------------------------- 1 | .\" Copyright 1993, 1994, 1998 The Open Group 2 | .\" Portions copyright 1988 Evans & Sutherland Computer Corporation. 3 | .\" Portions copyright 1989 Hewlett-Packard Company 4 | .\" Portions copyright 2003-2011 Apple Inc. All rights reserved. 5 | .\" 6 | .\" Permission to use, copy, modify, distribute, and sell this software and its 7 | .\" documentation for any purpose is hereby granted without fee, provided that 8 | .\" the above copyright notice appear in all copies and that both that 9 | .\" copyright notice and this permission notice appear in supporting 10 | .\" documentation. 11 | .\" 12 | .\" The above copyright notice and this permission notice shall be included 13 | .\" in all copies or substantial portions of the Software. 14 | .\" 15 | .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | .\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | .\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 | .\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 | .\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 | .\" OTHER DEALINGS IN THE SOFTWARE. 22 | .\" 23 | .\" Except as contained in this notice, the name of The Open Group shall 24 | .\" not be used in advertising or otherwise to promote the sale, use or 25 | .\" other dealings in this Software without prior written authorization 26 | .\" from The Open Group. 27 | .\" 28 | .\" 29 | .Dd May 13, 2011 30 | .Dt quartz-wm 1 31 | .Os 32 | .Sh NAME 33 | .Nm quartz-wm 34 | .Nd Aqua Window Manager for the X Window System on OS X 35 | .Sh SYNOPSIS 36 | .Nm 37 | .Op Fl -prefs-domain Ar domain 38 | .Sh DESCRIPTION 39 | .Nm 40 | is a window manager for the X Window System. It provides titlebars for 41 | X11 windows that aim to match the look and feel of native 42 | .Ar Mac OS X 43 | windows. 44 | .Pp 45 | The following options are available: 46 | .Bl -tag -width indent 47 | .It Fl -prefs-domain Ar domain 48 | This option can be used to override the domain used to read preferences 49 | from. This is useful if you want to have multiple X11.apps running at 50 | the same time. 51 | .El 52 | .Sh CUSTOMIZATION 53 | .Nm 54 | can be customized using the 55 | .Xr defaults 1 56 | command. Examples are shown using the default __bundle_id_prefix__.X11 domain. If you 57 | use another domain (either through the X11_PREFS_DOMAIN environment 58 | variable or the --prefs-domain command line argument), then you need 59 | to substitute that instead. 60 | .Nm 61 | can be forced to re-read these preferences by sending it a SIGHUP using 62 | .Xr kill 1 . 63 | .Pp 64 | The available options are: 65 | .Pp 66 | .Bl -tag -width indent 67 | .It defaults write __bundle_id_prefix__.X11 wm_ffm -bool true 68 | Enables focus-follows-mouse mode. Windows belonging to the X server may 69 | then be focused by moving the pointer over them, as well as the default 70 | mode of clicking in them. 71 | .It defaults write __bundle_id_prefix__.X11 wm_click_through -bool true 72 | Disables the default behavior of swallowing window-activating mouse events. 73 | .It defaults write __bundle_id_prefix__.X11 wm_limit_size -bool true 74 | Limit the size of each window to the size of the current head. 75 | .It defaults write __bundle_id_prefix__.x11 wm_focus_on_new_window -bool false 76 | Don't tell X11.app to take focus when a new X11 window is created. 77 | .It defaults write __bundle_id_prefix__.X11 wm_window_shading -bool true 78 | Enables double clicking on a titlebar to shade the window 79 | .It defaults write __bundle_id_prefix__.X11 wm_auto_quit -bool true 80 | Automatically quit 81 | .Nm 82 | (thus shutting down the X11 server) when the last window is closed. 83 | .It defaults write __bundle_id_prefix__.X11 wm_auto_quit_timeout -int 3 84 | Set the timeout for the auto-quit feature. If wm_auto_quit is true, quartz-wm 85 | will wait this many seconds before attempting to shutdown. If another window 86 | is created in that time, quartz-wm will not shutdown. 87 | .It defaults write __bundle_id_prefix__.X11 wm_show_shortcut -bool true 88 | Show each window's key equivalent, if it has one, in its title bar. 89 | .El 90 | .Sh LOGGING 91 | .Pp 92 | quartz-wm sends messages to 93 | .Xr syslogd 8 94 | using 95 | .Xr asl 3 . 96 | These logs are sent to the __bundle_id_prefix__ facility, and you can watch 97 | these logs using the following 98 | .Xr syslog 1 99 | command: 100 | .Bl -tag -width indent 101 | .It $ syslog -w -k Facility eq __bundle_id_prefix__ 102 | .El 103 | .Pp 104 | By default, debugging logs are filtered out. You can adjust the filter to 105 | print debugging information for the running quartz-wm with this 106 | .Xr 107 | syslog 1 108 | command 109 | .Bl -tag -width indent 110 | .It $ syslog -c quartz-wm -d 111 | .El 112 | .Pp 113 | See 114 | .Xr syslog 1 115 | or 116 | .Xr asl 3 117 | for more information on syslog filtering. 118 | .Sh ENVIRONMENT VARIABLES 119 | .Pp 120 | .Bl -tag -width indent 121 | .It DISPLAY 122 | This variable is used to determine which X server to use. 123 | .It X11_PREFS_DOMAIN 124 | This variable is used as Ar domain if the Fl -prefs-domain command line option 125 | is not given. If neither Fl -prefs-domain nor X11_PREFS_DOMAIN are set, then 126 | the default value of __bundle_id_prefix__.X11 is used instead. 127 | .It DEBUG 128 | If this variable is set, debug logging will be printed to stderr in addition to asl. 129 | .El 130 | .Sh SEE ALSO 131 | .Xr X 7 , 132 | .Xr Xquartz 1 , 133 | .Xr xpbproxy 1 , 134 | .Xr xrdb 1 , 135 | .Xr twm 1 136 | -------------------------------------------------------------------------------- /src/x-window.h: -------------------------------------------------------------------------------- 1 | /* x-window.h 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifndef X_WINDOW_H 26 | #define X_WINDOW_H 1 27 | 28 | #import "x-screen.h" 29 | #include "x-list.h" 30 | #include "frame.h" 31 | 32 | #include 33 | 34 | @interface x_window : NSObject 35 | { 36 | @public 37 | Window _id; 38 | Window _frame_id; 39 | Window _group_id; 40 | 41 | X11Rect _current_frame; 42 | 43 | Window _tracking_id; 44 | X11Rect _tracking_rect; 45 | 46 | Window _growbox_id; 47 | X11Rect _growbox_rect; 48 | 49 | x_screen *_screen; 50 | 51 | /*_xattr is for the Window _id, NOT _frame_id. Note that this is also 52 | * contains the x/y from a ConfigureRequestEvent or XGetWindowAttributes 53 | * This is NOT the actual position (inner or outer) since these coordinates 54 | * need to go through a transformation based on the window's gravity setting. 55 | */ 56 | XWindowAttributes _xattr; 57 | 58 | xp_frame_attr _frame_attr; 59 | 60 | int _frame_title_height; 61 | 62 | int _level; 63 | 64 | unsigned _reparented :1; 65 | unsigned _shaped :1; 66 | unsigned _shaped_empty :1; 67 | unsigned _removed :1; 68 | unsigned _deleted :1; 69 | unsigned _focused :1; 70 | unsigned _minimized :1; 71 | unsigned _unmapped :1; 72 | unsigned _always_click_through :1; 73 | unsigned _movable :1; 74 | unsigned _shadable :1; 75 | 76 | NSString *_title; 77 | int _shortcut_index; /* 0 for unset */ 78 | 79 | @private 80 | unsigned _set_shape :1; 81 | unsigned _decorated :1; 82 | unsigned _fullscreen :1; 83 | unsigned _resizable :1; 84 | unsigned _animating :1; /* (by the dock) */ 85 | unsigned _shaded :1; 86 | unsigned _hidden :1; 87 | unsigned _client_unmapped :1; 88 | unsigned _does_wm_take_focus :1; 89 | unsigned _does_wm_delete_window :1; 90 | unsigned _pending_frame_change :1; 91 | unsigned _queued_frame_change :1; 92 | unsigned _has_unzoomed_frame :1; 93 | unsigned _pending_decorate :1; 94 | unsigned _resizing_title :1; 95 | unsigned _needs_configure_notify :1; 96 | unsigned _modal :1; 97 | unsigned _in_window_menu :1; 98 | unsigned _pending_raise :1; 99 | 100 | /* This differs from _current_frame.height in that it is the height 101 | * when the frame is not shaded. 102 | */ 103 | int _frame_height; 104 | 105 | /* "pending" is new frame bounds we've dispatched to X server, but 106 | not yet seen come through in a configure-notify. "queued" is a 107 | new set of bounds we want to set, but won't until we've seen 108 | the configure-notify from the "pending" change. */ 109 | 110 | X11Rect _pending_frame; 111 | X11Rect _queued_frame; 112 | X11Rect _unzoomed_frame; 113 | 114 | /* Stored result from XGetWMHints() and XGetWMNormalHints() */ 115 | XWMHints *_wm_hints; 116 | 117 | /* Stored result from XGetWMNormalHints() */ 118 | XSizeHints _size_hints; 119 | long _size_hints_supplied; 120 | 121 | xp_frame_class _frame_decor; 122 | xp_frame_class _frame_behavior; 123 | 124 | Window *_colormap_windows; 125 | int _n_colormap_windows; 126 | 127 | /* Store what our decorations were the last time we drew the frame. 128 | * This is different from _frame_decor because it may be NONE due 129 | * to _fullscreen. 130 | */ 131 | xp_frame_class _drawn_frame_decor; 132 | 133 | /* Mac IDs corresponding to these windows */ 134 | xp_native_window_id _osx_id; 135 | xp_native_window_id _minimized_osx_id; 136 | 137 | /* Transience tree */ 138 | Window _transient_for_id; 139 | x_window *_transient_for; 140 | x_list *_transients; 141 | } 142 | 143 | - (Window) toplevel_id; 144 | - (void) reparent_in; 145 | - (void) reparent_out; 146 | - (void) send_configure; 147 | - init_with_id:(Window)xwindow_id screen:screen initializing:(BOOL)flag; 148 | - (void) resize_frame:(X11Rect)r; 149 | - (void) report_frame_size:(X11Rect)r; 150 | - (void) resize_client:(X11Rect)r; 151 | - (void) update_shaped; 152 | - (void) update_shape; 153 | - (void) expose; 154 | - (void) decorate; 155 | - (void) property_changed:(Atom)atom; 156 | - (void) update_net_wm_action_property; 157 | - (x_list *) window_group; 158 | - (xp_native_window_id) get_osx_id; 159 | - (void) set_wm_state:(int)state; 160 | - (void) raise; 161 | - (BOOL) focus:(Time)timestamp; 162 | - (BOOL) focus:(Time)timestamp raise:(BOOL)flag; 163 | - (BOOL) focus:(Time)timestamp raise:(BOOL)raise force:(BOOL)force; 164 | - (void) set_is_active:(BOOL)state; 165 | - (void) show; 166 | - (void) activate:(Time)timestamp; 167 | - (void) x_focus_in; 168 | - (void) x_focus_out; 169 | - (unsigned) hit_test_frame:(X11Point)point; 170 | - (void) do_close:(Time)timestamp; 171 | - (void) do_collapse; 172 | - (void) do_uncollapse; 173 | - (void) do_uncollapse_and_tell_dock:(BOOL)tell_dock; 174 | - (void) do_zoom; 175 | - (void) do_shade:(Time)timestamp; 176 | - (void) do_unshade:(Time)timestamp; 177 | - (void) do_toggle_shaded:(Time)timestamp; 178 | - (void) do_hide; 179 | - (void) do_unhide; 180 | - (void) do_net_wm_state_change:(int)mode atom:(Atom)state; 181 | - (X11Size) validate_window_size:(X11Rect)r; 182 | - (X11Rect) validate_client_rect:(X11Rect)r; 183 | - (X11Rect) validate_frame_rect:(X11Rect)r; 184 | - (X11Rect) validate_frame_rect:(X11Rect)r from_user:(BOOL)flag; 185 | - (void) set_resizing_title:(X11Rect)r; 186 | - (void) remove_resizing_title; 187 | - (void) error_shutdown; 188 | - (void) update_colormaps; 189 | - (void) install_colormaps; 190 | - (void) collapse_finished:(BOOL)success; 191 | - (void) uncollapse_finished:(BOOL)success; 192 | 193 | @end 194 | 195 | #endif /* X_WINDOW_H */ 196 | -------------------------------------------------------------------------------- /src/quartz-wm.h: -------------------------------------------------------------------------------- 1 | /* quartz-wm.h 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifndef QUARTZ_WM_H 26 | #define QUARTZ_WM_H 1 27 | 28 | #include 29 | 30 | #define Cursor OSX_Cursor 31 | #define Picture OSX_Picture 32 | #import 33 | #undef Picture 34 | #undef Cursor 35 | 36 | #undef _SHAPE_H_ 37 | #include 38 | #include 39 | 40 | #include "x-list.h" 41 | #include "x11-geometry.h" 42 | #include "dock-support.h" 43 | 44 | #define X_ROOT_WINDOW_EVENTS \ 45 | (SubstructureRedirectMask | SubstructureNotifyMask \ 46 | | StructureNotifyMask) 47 | 48 | #define X_CLIENT_WINDOW_EVENTS \ 49 | (PropertyChangeMask | StructureNotifyMask \ 50 | | ColormapChangeMask) 51 | 52 | #define X_CLIENT_BUTTON_GRAB_EVENTS \ 53 | (ButtonPressMask | ButtonReleaseMask) 54 | 55 | #define X_FRAME_WINDOW_EVENTS \ 56 | (ButtonPressMask | ButtonReleaseMask \ 57 | | ButtonMotionMask | PointerMotionHintMask \ 58 | | SubstructureRedirectMask | FocusChangeMask \ 59 | | EnterWindowMask | LeaveWindowMask \ 60 | | ExposureMask) 61 | 62 | #define X_TRACKING_WINDOW_EVENTS \ 63 | (EnterWindowMask | LeaveWindowMask) 64 | 65 | #define X_GROWBOX_WINDOW_EVENTS \ 66 | (ButtonPressMask | ButtonReleaseMask \ 67 | | ButtonMotionMask | PointerMotionHintMask) 68 | 69 | #define DRAG_THRESHOLD 3 70 | 71 | #define PREFS_FFM "wm_ffm" 72 | #define PREFS_CLICK_THROUGH "wm_click_through" 73 | #define PREFS_LIMIT_SIZE "wm_limit_size" 74 | #define PREFS_FOCUS_ON_NEW_WINDOW "wm_focus_on_new_window" 75 | #define PREFS_WINDOW_SHADING "wm_window_shading" 76 | #define PREFS_ROOTLESS "rootless" 77 | #define PREFS_AUTO_QUIT "wm_auto_quit" 78 | #define PREFS_AUTO_QUIT_TIMEOUT "wm_auto_quit_timeout" 79 | #define PREFS_MINIMIZE_ON_DOUBLE_CLICK "AppleMiniaturizeOnDoubleClick" 80 | #define PREFS_SHOW_SHORTCUT "wm_show_shortcut" 81 | #define PREFS_ENABLE_KEY_EQUIVALENTS "enable_key_equivalents" 82 | 83 | /* from main.m */ 84 | extern x_list *screen_list; 85 | extern BOOL focus_follows_mouse, focus_click_through, limit_window_size, focus_on_new_window, window_shading, rootless, auto_quit, minimize_on_double_click, show_shortcut, enable_key_equivalents; 86 | extern int auto_quit_timeout; 87 | extern void x_grab_server (Bool do_sync); 88 | extern void x_ungrab_server (void); 89 | extern void x_update_meta_modifier (void); 90 | extern void x_update_keymap (void); 91 | extern id x_get_screen (Screen *xs); 92 | extern id x_get_screen_with_root (Window xwindow_id); 93 | extern id x_get_window (Window xwindow_id); 94 | extern id x_get_window_by_osx_id (xp_native_window_id osxwindow_id); 95 | extern void x_set_active_window (id w); 96 | extern id x_get_active_window (void); 97 | extern void x_set_is_active (BOOL state); 98 | extern BOOL x_get_is_active (void); 99 | extern void x_bring_one_to_front (Time timestamp); 100 | extern void x_bring_all_to_front (Time timestamp); 101 | extern void x_hide_all (Time timestamp); 102 | extern void x_show_all (Time timestamp, BOOL minimized); 103 | extern void x_update_window_in_menu (id w); 104 | extern void x_add_window_to_menu (id w); 105 | extern void x_remove_window_from_menu (id w); 106 | extern void x_activate_window_in_menu (int n, Time timestamp); 107 | extern void x_change_window_count (int delta); 108 | extern int x_allocate_window_shortcut (void); 109 | extern void x_release_window_shortcut (int x); 110 | extern Time x_current_timestamp (void); 111 | 112 | extern aslclient aslc; 113 | extern Display *x_dpy; 114 | extern unsigned int x_meta_mod; 115 | extern int x_shape_event_base, x_shape_error_base; 116 | extern int x_apple_wm_event_base, x_apple_wm_error_base; 117 | extern int x_xinerama_event_base, x_xinerama_error_base; 118 | extern BOOL prefs_reload; 119 | 120 | /* from x-input.m */ 121 | extern void x_input_register (void); 122 | extern void x_input_run (void); 123 | 124 | /* Try to work with older libAppleWM for Codeweavers support */ 125 | typedef Bool (* XAppleWMSendPSNProcPtr)(Display *dpy); 126 | extern XAppleWMSendPSNProcPtr _XAppleWMSendPSN; 127 | 128 | typedef Bool (* XAppleWMAttachTransientProcPtr)(Display *dpy, Window child, Window parent); 129 | extern XAppleWMAttachTransientProcPtr _XAppleWMAttachTransient; 130 | 131 | struct atoms_struct_t { 132 | Atom apple_no_order_in; 133 | Atom atom; 134 | Atom clipboard; 135 | Atom cstring; 136 | Atom motif_wm_hints; 137 | Atom multiple; 138 | Atom native_screen_origin; 139 | Atom native_window_id; 140 | Atom net_active_window; 141 | Atom net_close_window; 142 | Atom net_wm_action_close; 143 | Atom net_wm_action_fullscreen; 144 | Atom net_wm_action_maximize_horz; 145 | Atom net_wm_action_maximize_vert; 146 | Atom net_wm_action_minimize; 147 | Atom net_wm_action_move; 148 | Atom net_wm_action_resize; 149 | Atom net_wm_action_shade; 150 | Atom net_wm_allowed_actions; 151 | Atom net_wm_name; 152 | Atom net_wm_state; 153 | Atom net_wm_state_fullscreen; 154 | Atom net_wm_state_hidden; 155 | Atom net_wm_state_maximized_horz; 156 | Atom net_wm_state_maximized_vert; 157 | Atom net_wm_state_modal; 158 | Atom net_wm_state_shaded; 159 | Atom net_wm_state_skip_pager; 160 | Atom net_wm_state_skip_taskbar; 161 | Atom net_wm_state_sticky; 162 | Atom net_wm_window_type; 163 | Atom net_wm_window_type_combo; 164 | Atom net_wm_window_type_desktop; 165 | Atom net_wm_window_type_dialog; 166 | Atom net_wm_window_type_dropdown_menu; 167 | Atom net_wm_window_type_dnd; 168 | Atom net_wm_window_type_dock; 169 | Atom net_wm_window_type_menu; 170 | Atom net_wm_window_type_normal; 171 | Atom net_wm_window_type_notification; 172 | Atom net_wm_window_type_popup_menu; 173 | Atom net_wm_window_type_splash; 174 | Atom net_wm_window_type_toolbar; 175 | Atom net_wm_window_type_tooltip; 176 | Atom net_wm_window_type_utility; 177 | Atom primary; 178 | Atom string; 179 | Atom targets; 180 | Atom text; 181 | Atom utf8_string; 182 | Atom wm_change_state; 183 | Atom wm_colormap_windows; 184 | Atom wm_delete_window; 185 | Atom wm_hints; 186 | Atom wm_name; 187 | Atom wm_normal_hints; 188 | Atom wm_protocols; 189 | Atom wm_state; 190 | Atom wm_take_focus; 191 | Atom wm_transient_for; 192 | }; 193 | 194 | extern struct atoms_struct_t atoms; 195 | 196 | /* Dock Events */ 197 | #include "dock-support.h" 198 | extern void dock_event_handler(xp_dock_event *event); 199 | 200 | /* Debugging support */ 201 | extern void debug_printf (const char *fmt, ...) _X_ATTRIBUTE_PRINTF(1,2); 202 | extern void debug_asl (const char *file, const char *function, int line, const char *fmt, ...) _X_ATTRIBUTE_PRINTF(4,5); 203 | extern const char *str_for_atom(Atom atom); 204 | 205 | #define DB(msg, args...) debug_asl(__FILE__, __FUNCTION__, __LINE__, msg, ##args); 206 | #define TRACE() DB("TRACE") 207 | 208 | #endif /* QUARTZ_WM_H */ 209 | -------------------------------------------------------------------------------- /src/x-list.c: -------------------------------------------------------------------------------- 1 | /* x-list.c 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include "x-list.h" 30 | #include 31 | #include 32 | #include 33 | 34 | /* Allocate in ~4k blocks */ 35 | #define NODES_PER_BLOCK 508 36 | 37 | typedef struct x_list_block_struct x_list_block; 38 | 39 | struct x_list_block_struct { 40 | x_list l[NODES_PER_BLOCK]; 41 | }; 42 | 43 | static x_list *freelist; 44 | 45 | static pthread_mutex_t freelist_lock = PTHREAD_MUTEX_INITIALIZER; 46 | 47 | static inline void 48 | list_free_1 (x_list *node) 49 | { 50 | node->next = freelist; 51 | freelist = node; 52 | } 53 | 54 | X_EXTERN void 55 | X_PFX (list_free_1) (x_list *node) 56 | { 57 | assert (node != NULL); 58 | 59 | pthread_mutex_lock (&freelist_lock); 60 | 61 | list_free_1 (node); 62 | 63 | pthread_mutex_unlock (&freelist_lock); 64 | } 65 | 66 | X_EXTERN void 67 | X_PFX (list_free) (x_list *lst) 68 | { 69 | x_list *next; 70 | 71 | pthread_mutex_lock (&freelist_lock); 72 | 73 | for (; lst != NULL; lst = next) 74 | { 75 | next = lst->next; 76 | list_free_1 (lst); 77 | } 78 | 79 | pthread_mutex_unlock (&freelist_lock); 80 | } 81 | 82 | X_EXTERN x_list * 83 | X_PFX (list_prepend) (x_list *lst, void *data) 84 | { 85 | x_list *node; 86 | 87 | pthread_mutex_lock (&freelist_lock); 88 | 89 | if (freelist == NULL) 90 | { 91 | x_list_block *b; 92 | int i; 93 | 94 | b = malloc (sizeof (x_list_block)); 95 | 96 | for (i = 0; i < NODES_PER_BLOCK - 1; i++) 97 | b->l[i].next = &(b->l[i+1]); 98 | b->l[i].next = NULL; 99 | 100 | freelist = b->l; 101 | } 102 | 103 | node = freelist; 104 | freelist = node->next; 105 | 106 | pthread_mutex_unlock (&freelist_lock); 107 | 108 | node->next = lst; 109 | node->data = data; 110 | 111 | return node; 112 | } 113 | 114 | X_EXTERN x_list * 115 | X_PFX (list_append) (x_list *lst, void *data) 116 | { 117 | x_list *head = lst; 118 | 119 | if (lst == NULL) 120 | return X_PFX (list_prepend) (NULL, data); 121 | 122 | while (lst->next != NULL) 123 | lst = lst->next; 124 | 125 | lst->next = X_PFX (list_prepend) (NULL, data); 126 | 127 | return head; 128 | } 129 | 130 | X_EXTERN x_list * 131 | X_PFX (list_reverse) (x_list *lst) 132 | { 133 | x_list *head = NULL, *next; 134 | 135 | while (lst != NULL) 136 | { 137 | next = lst->next; 138 | lst->next = head; 139 | head = lst; 140 | lst = next; 141 | } 142 | 143 | return head; 144 | } 145 | 146 | X_EXTERN x_list * 147 | X_PFX (list_find) (x_list *lst, void *data) 148 | { 149 | for (; lst != NULL; lst = lst->next) 150 | { 151 | if (lst->data == data) 152 | return lst; 153 | } 154 | 155 | return NULL; 156 | } 157 | 158 | X_EXTERN x_list * 159 | X_PFX (list_nth) (x_list *lst, int n) 160 | { 161 | while (n-- > 0 && lst != NULL) 162 | lst = lst->next; 163 | 164 | return lst; 165 | } 166 | 167 | X_EXTERN x_list * 168 | X_PFX (list_pop) (x_list *lst, void **data_ret) 169 | { 170 | void *data = NULL; 171 | 172 | if (lst != NULL) 173 | { 174 | x_list *tem = lst; 175 | data = lst->data; 176 | lst = lst->next; 177 | X_PFX (list_free_1) (tem); 178 | } 179 | 180 | if (data_ret != NULL) 181 | *data_ret = data; 182 | 183 | return lst; 184 | } 185 | 186 | X_EXTERN x_list * 187 | X_PFX (list_filter) (x_list *lst, 188 | int (*pred) (void *item, void *data), void *data) 189 | { 190 | x_list *ret = NULL, *node; 191 | 192 | for (node = lst; node != NULL; node = node->next) 193 | { 194 | if ((*pred) (node->data, data)) 195 | ret = X_PFX (list_prepend) (ret, node->data); 196 | } 197 | 198 | return X_PFX (list_reverse) (ret); 199 | } 200 | 201 | X_EXTERN x_list * 202 | X_PFX (list_map) (x_list *lst, 203 | void *(*fun) (void *item, void *data), void *data) 204 | { 205 | x_list *ret = NULL, *node; 206 | 207 | for (node = lst; node != NULL; node = node->next) 208 | { 209 | X_PFX (list_prepend) (ret, fun (node->data, data)); 210 | } 211 | 212 | return X_PFX (list_reverse) (ret); 213 | } 214 | 215 | X_EXTERN x_list * 216 | X_PFX (list_copy) (x_list *lst) 217 | { 218 | x_list *copy = NULL; 219 | 220 | for (; lst != NULL; lst = lst->next) 221 | { 222 | copy = X_PFX (list_prepend) (copy, lst->data); 223 | } 224 | 225 | return X_PFX (list_reverse) (copy); 226 | } 227 | 228 | X_EXTERN x_list * 229 | X_PFX (list_remove) (x_list *lst, void *data) 230 | { 231 | x_list **ptr, *node; 232 | 233 | for (ptr = &lst; *ptr != NULL;) 234 | { 235 | node = *ptr; 236 | 237 | if (node->data == data) 238 | { 239 | *ptr = node->next; 240 | X_PFX (list_free_1) (node); 241 | } 242 | else 243 | ptr = &((*ptr)->next); 244 | } 245 | 246 | return lst; 247 | } 248 | 249 | X_EXTERN unsigned int 250 | X_PFX (list_length) (x_list *lst) 251 | { 252 | unsigned int n; 253 | 254 | n = 0; 255 | for (; lst != NULL; lst = lst->next) 256 | n++; 257 | 258 | return n; 259 | } 260 | 261 | X_EXTERN void 262 | X_PFX (list_foreach) (x_list *lst, 263 | void (*fun) (void *data, void *user_data), 264 | void *user_data) 265 | { 266 | for (; lst != NULL; lst = lst->next) 267 | { 268 | (*fun) (lst->data, user_data); 269 | } 270 | } 271 | 272 | static x_list * 273 | list_sort_1 (x_list *lst, int length, 274 | int (*less) (const void *, const void *)) 275 | { 276 | x_list *mid, *ptr; 277 | x_list *out_head, *out; 278 | int mid_point, i; 279 | 280 | /* This is a standard (stable) list merge sort */ 281 | 282 | if (length < 2) 283 | return lst; 284 | 285 | /* Calculate the halfway point. Split the list into two sub-lists. */ 286 | 287 | mid_point = length / 2; 288 | ptr = lst; 289 | for (i = mid_point - 1; i > 0; i--) 290 | ptr = ptr->next; 291 | mid = ptr->next; 292 | ptr->next = NULL; 293 | 294 | /* Sort each sub-list. */ 295 | 296 | lst = list_sort_1 (lst, mid_point, less); 297 | mid = list_sort_1 (mid, length - mid_point, less); 298 | 299 | /* Then merge them back together. */ 300 | 301 | assert (lst != NULL && mid != NULL); 302 | 303 | if ((*less) (mid->data, lst->data)) 304 | out = out_head = mid, mid = mid->next; 305 | else 306 | out = out_head = lst, lst = lst->next; 307 | 308 | while (lst != NULL && mid != NULL) 309 | { 310 | if ((*less) (mid->data, lst->data)) 311 | out = out->next = mid, mid = mid->next; 312 | else 313 | out = out->next = lst, lst = lst->next; 314 | } 315 | 316 | if (lst != NULL) 317 | out->next = lst; 318 | else 319 | out->next = mid; 320 | 321 | return out_head; 322 | } 323 | 324 | X_EXTERN x_list * 325 | X_PFX (list_sort) (x_list *lst, int (*less) (const void *, const void *)) 326 | { 327 | int length; 328 | 329 | length = X_PFX (list_length) (lst); 330 | 331 | return list_sort_1 (lst, length, less); 332 | } 333 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Please read this License carefully before downloading this software. 2 | By downloading or using this software, you are agreeing to be bound by 3 | the terms of this License. If you do not or cannot agree to the terms 4 | of this License, please do not download or use the software. 5 | 6 | 1. General; Definitions. This License applies to any program or other 7 | work which Apple Computer, Inc. ("Apple") makes publicly available and 8 | which contains a notice placed by Apple identifying such program or 9 | work as "Original Code" and stating that it is subject to the terms of 10 | this Apple Public Source License version 2.0 ("License"). As used in 11 | this License: 12 | 13 | 1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is 14 | the grantor of rights, (i) claims of patents that are now or hereafter 15 | acquired, owned by or assigned to Apple and (ii) that cover subject 16 | matter contained in the Original Code, but only to the extent 17 | necessary to use, reproduce and/or distribute the Original Code 18 | without infringement; and (b) in the case where You are the grantor of 19 | rights, (i) claims of patents that are now or hereafter acquired, 20 | owned by or assigned to You and (ii) that cover subject matter in Your 21 | Modifications, taken alone or in combination with Original Code. 22 | 23 | 1.2 "Contributor" means any person or entity that creates or 24 | contributes to the creation of Modifications. 25 | 26 | 1.3 "Covered Code" means the Original Code, Modifications, the 27 | combination of Original Code and any Modifications, and/or any 28 | respective portions thereof. 29 | 30 | 1.4 "Externally Deploy" means: (a) to sublicense, distribute or 31 | otherwise make Covered Code available, directly or indirectly, to 32 | anyone other than You; and/or (b) to use Covered Code, alone or as 33 | part of a Larger Work, in any way to provide a service, including but 34 | not limited to delivery of content, through electronic communication 35 | with a client other than You. 36 | 37 | 1.5 "Larger Work" means a work which combines Covered Code or portions 38 | thereof with code not governed by the terms of this License. 39 | 40 | 1.6 "Modifications" mean any addition to, deletion from, and/or change 41 | to, the substance and/or structure of the Original Code, any previous 42 | Modifications, the combination of Original Code and any previous 43 | Modifications, and/or any respective portions thereof. When code is 44 | released as a series of files, a Modification is: (a) any addition to 45 | or deletion from the contents of a file containing Covered Code; 46 | and/or (b) any new file or other representation of computer program 47 | statements that contains any part of Covered Code. 48 | 49 | 1.7 "Original Code" means (a) the Source Code of a program or other 50 | work as originally made available by Apple under this License, 51 | including the Source Code of any updates or upgrades to such programs 52 | or works made available by Apple under this License, and that has been 53 | expressly identified by Apple as such in the header file(s) of such 54 | work; and (b) the object code compiled from such Source Code and 55 | originally made available by Apple under this License. 56 | 57 | 1.8 "Source Code" means the human readable form of a program or other 58 | work that is suitable for making modifications to it, including all 59 | modules it contains, plus any associated interface definition files, 60 | scripts used to control compilation and installation of an executable 61 | (object code). 62 | 63 | 1.9 "You" or "Your" means an individual or a legal entity exercising 64 | rights under this License. For legal entities, "You" or "Your" 65 | includes any entity which controls, is controlled by, or is under 66 | common control with, You, where "control" means (a) the power, direct 67 | or indirect, to cause the direction or management of such entity, 68 | whether by contract or otherwise, or (b) ownership of fifty percent 69 | (50%) or more of the outstanding shares or beneficial ownership of 70 | such entity. 71 | 72 | 2. Permitted Uses; Conditions & Restrictions. Subject to the terms 73 | and conditions of this License, Apple hereby grants You, effective on 74 | the date You accept this License and download the Original Code, a 75 | world-wide, royalty-free, non-exclusive license, to the extent of 76 | Apple's Applicable Patent Rights and copyrights covering the Original 77 | Code, to do the following: 78 | 79 | 2.1 Unmodified Code. You may use, reproduce, display, perform, 80 | internally distribute within Your organization, and Externally Deploy 81 | verbatim, unmodified copies of the Original Code, for commercial or 82 | non-commercial purposes, provided that in each instance: 83 | 84 | (a) You must retain and reproduce in all copies of Original Code the 85 | copyright and other proprietary notices and disclaimers of Apple as 86 | they appear in the Original Code, and keep intact all notices in the 87 | Original Code that refer to this License; and 88 | 89 | (b) You must include a copy of this License with every copy of Source 90 | Code of Covered Code and documentation You distribute or Externally 91 | Deploy, and You may not offer or impose any terms on such Source Code 92 | that alter or restrict this License or the recipients' rights 93 | hereunder, except as permitted under Section 6. 94 | 95 | 2.2 Modified Code. You may modify Covered Code and use, reproduce, 96 | display, perform, internally distribute within Your organization, and 97 | Externally Deploy Your Modifications and Covered Code, for commercial 98 | or non-commercial purposes, provided that in each instance You also 99 | meet all of these conditions: 100 | 101 | (a) You must satisfy all the conditions of Section 2.1 with respect to 102 | the Source Code of the Covered Code; 103 | 104 | (b) You must duplicate, to the extent it does not already exist, the 105 | notice in Exhibit A in each file of the Source Code of all Your 106 | Modifications, and cause the modified files to carry prominent notices 107 | stating that You changed the files and the date of any change; and 108 | 109 | (c) If You Externally Deploy Your Modifications, You must make 110 | Source Code of all Your Externally Deployed Modifications either 111 | available to those to whom You have Externally Deployed Your 112 | Modifications, or publicly available. Source Code of Your Externally 113 | Deployed Modifications must be released under the terms set forth in 114 | this License, including the license grants set forth in Section 3 115 | below, for as long as you Externally Deploy the Covered Code or twelve 116 | (12) months from the date of initial External Deployment, whichever is 117 | longer. You should preferably distribute the Source Code of Your 118 | Externally Deployed Modifications electronically (e.g. download from a 119 | web site). 120 | 121 | 2.3 Distribution of Executable Versions. In addition, if You 122 | Externally Deploy Covered Code (Original Code and/or Modifications) in 123 | object code, executable form only, You must include a prominent 124 | notice, in the code itself as well as in related documentation, 125 | stating that Source Code of the Covered Code is available under the 126 | terms of this License with information on how and where to obtain such 127 | Source Code. 128 | 129 | 2.4 Third Party Rights. You expressly acknowledge and agree that 130 | although Apple and each Contributor grants the licenses to their 131 | respective portions of the Covered Code set forth herein, no 132 | assurances are provided by Apple or any Contributor that the Covered 133 | Code does not infringe the patent or other intellectual property 134 | rights of any other entity. Apple and each Contributor disclaim any 135 | liability to You for claims brought by any other entity based on 136 | infringement of intellectual property rights or otherwise. As a 137 | condition to exercising the rights and licenses granted hereunder, You 138 | hereby assume sole responsibility to secure any other intellectual 139 | property rights needed, if any. For example, if a third party patent 140 | license is required to allow You to distribute the Covered Code, it is 141 | Your responsibility to acquire that license before distributing the 142 | Covered Code. 143 | 144 | 3. Your Grants. In consideration of, and as a condition to, the 145 | licenses granted to You under this License, You hereby grant to any 146 | person or entity receiving or distributing Covered Code under this 147 | License a non-exclusive, royalty-free, perpetual, irrevocable license, 148 | under Your Applicable Patent Rights and other intellectual property 149 | rights (other than patent) owned or controlled by You, to use, 150 | reproduce, display, perform, modify, sublicense, distribute and 151 | Externally Deploy Your Modifications of the same scope and extent as 152 | Apple's licenses under Sections 2.1 and 2.2 above. 153 | 154 | 4. Larger Works. You may create a Larger Work by combining Covered 155 | Code with other code not governed by the terms of this License and 156 | distribute the Larger Work as a single product. In each such instance, 157 | You must make sure the requirements of this License are fulfilled for 158 | the Covered Code or any portion thereof. 159 | 160 | 5. Limitations on Patent License. Except as expressly stated in 161 | Section 2, no other patent rights, express or implied, are granted by 162 | Apple herein. Modifications and/or Larger Works may require additional 163 | patent licenses from Apple which Apple may grant in its sole 164 | discretion. 165 | 166 | 6. Additional Terms. You may choose to offer, and to charge a fee for, 167 | warranty, support, indemnity or liability obligations and/or other 168 | rights consistent with the scope of the license granted herein 169 | ("Additional Terms") to one or more recipients of Covered Code. 170 | However, You may do so only on Your own behalf and as Your sole 171 | responsibility, and not on behalf of Apple or any Contributor. You 172 | must obtain the recipient's agreement that any such Additional Terms 173 | are offered by You alone, and You hereby agree to indemnify, defend 174 | and hold Apple and every Contributor harmless for any liability 175 | incurred by or claims asserted against Apple or such Contributor by 176 | reason of any such Additional Terms. 177 | 178 | 7. Versions of the License. Apple may publish revised and/or new 179 | versions of this License from time to time. Each version will be given 180 | a distinguishing version number. Once Original Code has been published 181 | under a particular version of this License, You may continue to use it 182 | under the terms of that version. You may also choose to use such 183 | Original Code under the terms of any subsequent version of this 184 | License published by Apple. No one other than Apple has the right to 185 | modify the terms applicable to Covered Code created under this 186 | License. 187 | 188 | 8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in 189 | part pre-release, untested, or not fully tested works. The Covered 190 | Code may contain errors that could cause failures or loss of data, and 191 | may be incomplete or contain inaccuracies. You expressly acknowledge 192 | and agree that use of the Covered Code, or any portion thereof, is at 193 | Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND 194 | WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND 195 | APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE 196 | PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM 197 | ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT 198 | NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF 199 | MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR 200 | PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD 201 | PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST 202 | INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE 203 | FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, 204 | THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR 205 | ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO 206 | ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE 207 | AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. 208 | You acknowledge that the Covered Code is not intended for use in the 209 | operation of nuclear facilities, aircraft navigation, communication 210 | systems, or air traffic control machines in which case the failure of 211 | the Covered Code could lead to death, personal injury, or severe 212 | physical or environmental damage. 213 | 214 | 9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO 215 | EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, 216 | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING 217 | TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR 218 | ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, 219 | TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF 220 | APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 221 | DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY 222 | REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF 223 | INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY 224 | TO YOU. In no event shall Apple's total liability to You for all 225 | damages (other than as may be required by applicable law) under this 226 | License exceed the amount of fifty dollars ($50.00). 227 | 228 | 10. Trademarks. This License does not grant any rights to use the 229 | trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", 230 | "QuickTime", "QuickTime Streaming Server" or any other trademarks, 231 | service marks, logos or trade names belonging to Apple (collectively 232 | "Apple Marks") or to any trademark, service mark, logo or trade name 233 | belonging to any Contributor. You agree not to use any Apple Marks in 234 | or as part of the name of products derived from the Original Code or 235 | to endorse or promote products derived from the Original Code other 236 | than as expressly permitted by and in strict compliance at all times 237 | with Apple's third party trademark usage guidelines which are posted 238 | at http://www.apple.com/legal/guidelinesfor3rdparties.html. 239 | 240 | 11. Ownership. Subject to the licenses granted under this License, 241 | each Contributor retains all rights, title and interest in and to any 242 | Modifications made by such Contributor. Apple retains all rights, 243 | title and interest in and to the Original Code and any Modifications 244 | made by or on behalf of Apple ("Apple Modifications"), and such Apple 245 | Modifications will not be automatically subject to this License. Apple 246 | may, at its sole discretion, choose to license such Apple 247 | Modifications under this License, or on different terms from those 248 | contained in this License or may choose not to license them at all. 249 | 250 | 12. Termination. 251 | 252 | 12.1 Termination. This License and the rights granted hereunder will 253 | terminate: 254 | 255 | (a) automatically without notice from Apple if You fail to comply with 256 | any term(s) of this License and fail to cure such breach within 30 257 | days of becoming aware of such breach; 258 | 259 | (b) immediately in the event of the circumstances described in Section 260 | 13.5(b); or 261 | 262 | (c) automatically without notice from Apple if You, at any time during 263 | the term of this License, commence an action for patent infringement 264 | against Apple; provided that Apple did not first commence 265 | an action for patent infringement against You in that instance. 266 | 267 | 12.2 Effect of Termination. Upon termination, You agree to immediately 268 | stop any further use, reproduction, modification, sublicensing and 269 | distribution of the Covered Code. All sublicenses to the Covered Code 270 | which have been properly granted prior to termination shall survive 271 | any termination of this License. Provisions which, by their nature, 272 | should remain in effect beyond the termination of this License shall 273 | survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, 274 | 12.2 and 13. No party will be liable to any other for compensation, 275 | indemnity or damages of any sort solely as a result of terminating 276 | this License in accordance with its terms, and termination of this 277 | License will be without prejudice to any other right or remedy of 278 | any party. 279 | 280 | 13. Miscellaneous. 281 | 282 | 13.1 Government End Users. The Covered Code is a "commercial item" as 283 | defined in FAR 2.101. Government software and technical data rights in 284 | the Covered Code include only those rights customarily provided to the 285 | public as defined in this License. This customary commercial license 286 | in technical data and software is provided in accordance with FAR 287 | 12.211 (Technical Data) and 12.212 (Computer Software) and, for 288 | Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- 289 | Commercial Items) and 227.7202-3 (Rights in Commercial Computer 290 | Software or Computer Software Documentation). Accordingly, all U.S. 291 | Government End Users acquire Covered Code with only those rights set 292 | forth herein. 293 | 294 | 13.2 Relationship of Parties. This License will not be construed as 295 | creating an agency, partnership, joint venture or any other form of 296 | legal association between or among You, Apple or any Contributor, and 297 | You will not represent to the contrary, whether expressly, by 298 | implication, appearance or otherwise. 299 | 300 | 13.3 Independent Development. Nothing in this License will impair 301 | Apple's right to acquire, license, develop, have others develop for 302 | it, market and/or distribute technology or products that perform the 303 | same or similar functions as, or otherwise compete with, 304 | Modifications, Larger Works, technology or products that You may 305 | develop, produce, market or distribute. 306 | 307 | 13.4 Waiver; Construction. Failure by Apple or any Contributor to 308 | enforce any provision of this License will not be deemed a waiver of 309 | future enforcement of that or any other provision. Any law or 310 | regulation which provides that the language of a contract shall be 311 | construed against the drafter will not apply to this License. 312 | 313 | 13.5 Severability. (a) If for any reason a court of competent 314 | jurisdiction finds any provision of this License, or portion thereof, 315 | to be unenforceable, that provision of the License will be enforced to 316 | the maximum extent permissible so as to effect the economic benefits 317 | and intent of the parties, and the remainder of this License will 318 | continue in full force and effect. (b) Notwithstanding the foregoing, 319 | if applicable law prohibits or restricts You from fully and/or 320 | specifically complying with Sections 2 and/or 3 or prevents the 321 | enforceability of either of those Sections, this License will 322 | immediately terminate and You must immediately discontinue any use of 323 | the Covered Code and destroy all copies of it that are in your 324 | possession or control. 325 | 326 | 13.6 Dispute Resolution. Any litigation or other dispute resolution 327 | between You and Apple relating to this License shall take place in the 328 | Northern District of California, and You and Apple hereby consent to 329 | the personal jurisdiction of, and venue in, the state and federal 330 | courts within that District with respect to this License. The 331 | application of the United Nations Convention on Contracts for the 332 | International Sale of Goods is expressly excluded. 333 | 334 | 13.7 Entire Agreement; Governing Law. This License constitutes the 335 | entire agreement between the parties with respect to the subject 336 | matter hereof. This License shall be governed by the laws of the 337 | United States and the State of California, except that body of 338 | California law concerning conflicts of law. 339 | 340 | Where You are located in the province of Quebec, Canada, the following 341 | clause applies: The parties hereby confirm that they have requested 342 | that this License and all related documents be drafted in English. Les 343 | parties ont exige que le present contrat et tous les documents 344 | connexes soient rediges en anglais. 345 | 346 | EXHIBIT A. 347 | 348 | "Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights 349 | Reserved. 350 | 351 | This file contains Original Code and/or Modifications of Original Code 352 | as defined in and that are subject to the Apple Public Source License 353 | Version 2.0 (the 'License'). You may not use this file except in 354 | compliance with the License. Please obtain a copy of the License at 355 | http://www.opensource.apple.com/apsl/ and read it before using this 356 | file. 357 | 358 | The Original Code and all software distributed under the License are 359 | distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 360 | EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 361 | INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 362 | FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 363 | Please see the License for the specific language governing rights and 364 | limitations under the License." 365 | -------------------------------------------------------------------------------- /src/x-input.m: -------------------------------------------------------------------------------- 1 | /* x-input.m -- event handling 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include "quartz-wm.h" 30 | #import "x-screen.h" 31 | #import "x-window.h" 32 | #include "frame.h" 33 | #include "utils.h" 34 | 35 | #include 36 | #include 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | 45 | extern BOOL _proxy_pb; 46 | 47 | /* FIXME: .. */ 48 | #define DOUBLE_CLICK_TIME 250 49 | 50 | #define BUTTON_MASK \ 51 | (Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask) 52 | 53 | CFRunLoopSourceRef x_dpy_source; 54 | 55 | static struct { 56 | Window down_id; 57 | Time down_time; /* milliseconds */ 58 | X11Point down_location; 59 | X11Point offset; 60 | int click_count; 61 | unsigned int down_attrs; 62 | unsigned dragging :1; 63 | unsigned clicking :1; 64 | unsigned resizing :1; 65 | } pointer_state; 66 | 67 | /* Timestamp when the X server last told us it's active */ 68 | static Time last_activation_time; 69 | 70 | static float 71 | point_distance (X11Point a, X11Point b) 72 | { 73 | float dx, dy; 74 | 75 | dx = b.x - a.x; 76 | dy = b.y - a.y; 77 | 78 | return sqrt (dx * dx + dy * dy); 79 | } 80 | 81 | static inline int 82 | count_bits (uint32_t x) 83 | { 84 | x = x - ((x >> 1) & 0x55555555); 85 | x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 86 | x = (x + (x >> 4)) & 0x0f0f0f0f; 87 | x = x + (x >> 8); 88 | x = x + (x >> 16); 89 | return x & 63; 90 | } 91 | 92 | static inline int 93 | buttons_pressed (unsigned int state) 94 | { 95 | return count_bits (state & BUTTON_MASK); 96 | } 97 | 98 | static void * 99 | list_next (x_list *lst, void *item) 100 | { 101 | x_list *node; 102 | 103 | node = x_list_find (lst, item); 104 | 105 | if (node != NULL) 106 | { 107 | node = node->next; 108 | if (node == NULL) 109 | node = lst; 110 | } 111 | 112 | if (node != NULL && node->data != item) 113 | return node->data; 114 | 115 | return NULL; 116 | } 117 | 118 | static void 119 | next_window (Time timestamp, Bool reversed) 120 | { 121 | x_window *w, *x; 122 | x_list *lst; 123 | 124 | w = x_get_active_window (); 125 | if (w != nil) 126 | { 127 | lst = x_list_copy (w->_screen->_window_list); 128 | if (reversed) 129 | lst = x_list_reverse (lst); 130 | 131 | x = list_next (lst, w); 132 | 133 | /* Skip minimized windows. */ 134 | while (x != nil && x != w && x->_minimized) 135 | x = list_next (lst, x); 136 | 137 | [x activate:timestamp]; 138 | 139 | x_list_free (lst); 140 | } 141 | } 142 | 143 | static void 144 | x_event_button (XButtonEvent *e) 145 | { 146 | x_window *w = x_get_window (e->window); 147 | 148 | if (w == nil) 149 | return; 150 | 151 | if (e->window == w->_id) 152 | { 153 | /* Swallow the first activating click. Since the X server activates 154 | us we need to look at timestamps to handle the case where the 155 | user activated X by clicking on the already focused window. Use 156 | a 100ms window for this. */ 157 | 158 | if ((!w->_focused || (e->time - last_activation_time) < 100) 159 | && [w focus:e->time]) 160 | { 161 | if (w->_always_click_through || focus_click_through) 162 | { 163 | XAllowEvents (x_dpy, ReplayPointer, e->time); 164 | XUngrabPointer (x_dpy, e->time); 165 | } 166 | else 167 | { 168 | XAllowEvents (x_dpy, AsyncPointer, e->time); 169 | } 170 | } 171 | else 172 | { 173 | [w raise]; 174 | XAllowEvents (x_dpy, ReplayPointer, e->time); 175 | XUngrabPointer (x_dpy, e->time); 176 | } 177 | } 178 | else if (e->button <= 3 179 | && (e->window == w->_frame_id || e->window == w->_growbox_id)) 180 | { 181 | unsigned int old_attrs = w->_frame_attr; 182 | X11Point p = X11PointMake (e->x, e->y); 183 | 184 | if (e->window == w->_growbox_id) 185 | { 186 | p.x += w->_growbox_rect.x; 187 | p.y += w->_growbox_rect.y; 188 | } 189 | 190 | if (e->type == ButtonPress) 191 | { 192 | if (buttons_pressed (e->state) == 0) 193 | { 194 | /* First button press */ 195 | 196 | /* FIXME: wrap around? */ 197 | if (e->time - pointer_state.down_time < DOUBLE_CLICK_TIME) 198 | pointer_state.click_count++; 199 | else 200 | pointer_state.click_count = 1; 201 | 202 | pointer_state.down_location.x = e->x_root; 203 | pointer_state.down_location.y = e->y_root; 204 | pointer_state.down_id = e->window; 205 | pointer_state.down_time = e->time; 206 | pointer_state.down_attrs = [w hit_test_frame:p]; 207 | 208 | if ((pointer_state.down_attrs 209 | & (w->_frame_attr & XP_FRAME_ATTRS_ANY_BUTTON)) != 0) 210 | { 211 | pointer_state.clicking = YES; 212 | XP_FRAME_ATTR_SET_CLICKED (w->_frame_attr, 213 | pointer_state.down_attrs 214 | & XP_FRAME_ATTRS_ANY_BUTTON); 215 | } 216 | else 217 | { 218 | [w focus:e->time raise:!(e->state & x_meta_mod)]; 219 | } 220 | } 221 | } 222 | else if (e->type == ButtonRelease) 223 | { 224 | if (buttons_pressed (e->state) == 1) 225 | { 226 | /* Releasing last button */ 227 | 228 | if (pointer_state.dragging) 229 | { 230 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 231 | qwm_dock_drag_end([w get_osx_id]); 232 | #endif 233 | pointer_state.dragging = NO; 234 | } 235 | else if (pointer_state.resizing) 236 | { 237 | pointer_state.resizing = NO; 238 | [w remove_resizing_title]; 239 | } 240 | else if (pointer_state.clicking) 241 | { 242 | unsigned int attrs; 243 | 244 | /* Test the release location */ 245 | attrs = [w hit_test_frame:p]; 246 | 247 | /* Only if it went pressed the same button it came released on */ 248 | attrs &= pointer_state.down_attrs; 249 | 250 | if (attrs & XP_FRAME_ATTR_CLOSE_BOX) 251 | [w do_close:e->time]; 252 | else if (attrs & XP_FRAME_ATTR_COLLAPSE) 253 | [w do_collapse]; 254 | else if (attrs & XP_FRAME_ATTR_ZOOM) 255 | [w do_zoom]; 256 | 257 | XP_FRAME_ATTR_UNSET_CLICKED (w->_frame_attr, 258 | XP_FRAME_ATTRS_ANY_BUTTON); 259 | 260 | /* Update prelight bit, we ignored tracking events 261 | while clickiing. */ 262 | w->_frame_attr &= ~XP_FRAME_ATTR_PRELIGHT; 263 | w->_frame_attr |= attrs & XP_FRAME_ATTR_PRELIGHT; 264 | 265 | pointer_state.clicking = NO; 266 | } 267 | else if (pointer_state.click_count == 2) 268 | { 269 | if (w->_shadable && window_shading) 270 | [w do_toggle_shaded:e->time]; 271 | else if ((w->_frame_attr & XP_FRAME_ATTR_COLLAPSE) && 272 | minimize_on_double_click) 273 | [w do_collapse]; 274 | } 275 | 276 | pointer_state.down_id = 0; 277 | } 278 | } 279 | 280 | if (w->_frame_attr != old_attrs) 281 | { 282 | [w decorate]; 283 | } 284 | } 285 | } 286 | 287 | static void 288 | x_event_motion_notify (XMotionEvent *e) 289 | { 290 | x_window *w = x_get_window (e->window); 291 | 292 | if (w == nil) 293 | return; 294 | 295 | #if 0 296 | if (e->window == w->_id) 297 | { 298 | XAllowEvents (x_dpy, ReplayPointer, e->time); 299 | XUngrabPointer (x_dpy, e->time); 300 | } 301 | else 302 | #endif 303 | if (e->window == pointer_state.down_id) 304 | { 305 | X11Point p, wp; 306 | X11Rect r; 307 | unsigned int old_attrs = w->_frame_attr, attrs; 308 | 309 | Window tem_w; 310 | unsigned int tem_i; 311 | int x, y, wx, wy; 312 | 313 | XQueryPointer (x_dpy, e->window, &tem_w, &tem_w, 314 | &x, &y, &wx, &wy, &tem_i); 315 | 316 | p = X11PointMake(x, y); 317 | wp = X11PointMake(wx, wy); 318 | 319 | if (buttons_pressed (e->state) == 0) 320 | { 321 | /* We must have missed the button-release */ 322 | if(pointer_state.dragging) { 323 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 324 | qwm_dock_drag_end([w get_osx_id]); 325 | #endif 326 | pointer_state.dragging = NO; 327 | } 328 | if (pointer_state.resizing) { 329 | pointer_state.resizing = NO; 330 | [w remove_resizing_title]; 331 | } 332 | } 333 | 334 | if (pointer_state.dragging) 335 | { 336 | do_drag: 337 | r = X11RectMake(p.x + pointer_state.offset.x, p.y + pointer_state.offset.y, 338 | w->_current_frame.width, w->_current_frame.height); 339 | r = [w->_screen validate_window_position:r titlebar_height:w->_frame_title_height]; 340 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 341 | qwm_dock_drag_begin([w get_osx_id]); 342 | #endif 343 | [w resize_frame:r]; 344 | } 345 | else if (pointer_state.resizing) 346 | { 347 | do_resize: 348 | r = X11RectMake(w->_current_frame.x, w->_current_frame.y, 349 | pointer_state.offset.x + (p.x - pointer_state.down_location.x), 350 | pointer_state.offset.y + (p.y - pointer_state.down_location.y)); 351 | if (r.width > 0 && r.height > 0) 352 | { 353 | r = [w validate_frame_rect:r from_user:YES]; 354 | [w resize_frame:r]; 355 | [w set_resizing_title:r]; 356 | } 357 | } 358 | else if (pointer_state.clicking) 359 | { 360 | attrs = [w hit_test_frame:wp]; 361 | 362 | if ((attrs & XP_FRAME_ATTRS_ANY_BUTTON) 363 | != (pointer_state.down_attrs & XP_FRAME_ATTRS_ANY_BUTTON)) 364 | { 365 | /* Moved off the button we clicked on, change its state. */ 366 | 367 | XP_FRAME_ATTR_UNSET_CLICKED (w->_frame_attr, XP_FRAME_ATTRS_ANY_BUTTON); 368 | } 369 | else 370 | { 371 | XP_FRAME_ATTR_SET_CLICKED (w->_frame_attr, 372 | pointer_state.down_attrs 373 | & XP_FRAME_ATTRS_ANY_BUTTON); 374 | } 375 | } 376 | else 377 | { 378 | /* See if we moved far enough to start dragging the window. */ 379 | 380 | if ((e->state & BUTTON_MASK) != 0 381 | && point_distance (pointer_state.down_location, p) >= DRAG_THRESHOLD) 382 | { 383 | if (e->window == w->_growbox_id) 384 | { 385 | pointer_state.offset.x = w->_current_frame.width; 386 | pointer_state.offset.y = w->_current_frame.height; 387 | pointer_state.resizing = YES; 388 | goto do_resize; 389 | } 390 | else if (e->window == w->_frame_id 391 | && w->_movable && e->subwindow == None) 392 | { 393 | pointer_state.offset.x = w->_current_frame.x - pointer_state.down_location.x; 394 | pointer_state.offset.y = w->_current_frame.y - pointer_state.down_location.y; 395 | pointer_state.dragging = YES; 396 | goto do_drag; 397 | } 398 | } 399 | } 400 | 401 | if (w->_frame_attr != old_attrs) 402 | { 403 | [w decorate]; 404 | } 405 | } 406 | } 407 | 408 | static void 409 | x_event_key (XKeyEvent *e) 410 | { 411 | int grave_code = XKeysymToKeycode (x_dpy, XK_grave); 412 | 413 | if(grave_code != 0 && grave_code == e->keycode && x_meta_mod != 0) 414 | { 415 | if(e->state == (ShiftMask | x_meta_mod)) { 416 | if(e->type == KeyPress) 417 | next_window (e->time, TRUE); 418 | XAllowEvents (x_dpy, AsyncKeyboard, e->time); 419 | return; 420 | } else if(e->state == x_meta_mod) { 421 | if(e->type == KeyPress) 422 | next_window (e->time, FALSE); 423 | XAllowEvents (x_dpy, AsyncKeyboard, e->time); 424 | return; 425 | } 426 | } 427 | XAllowEvents (x_dpy, ReplayKeyboard, e->time); 428 | XUngrabKeyboard (x_dpy, e->time); 429 | } 430 | 431 | static void 432 | x_event_property_notify (XPropertyEvent *e) 433 | { 434 | x_window *w = x_get_window (e->window); 435 | 436 | if (w == nil || e->window != w->_id) 437 | return; 438 | 439 | [w property_changed:e->atom]; 440 | } 441 | 442 | static void x_event_client_message (XClientMessageEvent *e) { 443 | x_window *w = x_get_window(e->window); 444 | 445 | if (w == nil || e->format != 32) 446 | return; 447 | 448 | if(e->message_type == atoms.wm_change_state) { 449 | if (e->data.l[0] == IconicState) 450 | [w do_collapse]; 451 | } else if(e->message_type == atoms.net_active_window) { 452 | [w focus:x_current_timestamp ()]; 453 | } else if(e->message_type == atoms.net_close_window) { 454 | [w do_close:x_current_timestamp ()]; 455 | } else if(e->message_type == atoms.net_wm_state) { 456 | if (e->data.l[1] != 0) 457 | [w do_net_wm_state_change:e->data.l[0] atom:e->data.l[1]]; 458 | if (e->data.l[2] != 0) 459 | [w do_net_wm_state_change:e->data.l[0] atom:e->data.l[2]]; 460 | } 461 | } 462 | 463 | static void 464 | x_event_destroy_notify (XDestroyWindowEvent *e) 465 | { 466 | x_window *w = x_get_window (e->window); 467 | 468 | if (w == nil || e->window != w->_id) 469 | return; 470 | 471 | [w->_screen remove_window:w]; 472 | } 473 | 474 | static void 475 | x_event_map_request (XMapRequestEvent *e) 476 | { 477 | x_window *w = x_get_window (e->window); 478 | 479 | if (w == nil) 480 | { 481 | XWindowAttributes attr; 482 | x_screen *s; 483 | 484 | XGetWindowAttributes (x_dpy, e->window, &attr); 485 | s = x_get_screen (attr.screen); 486 | if (s == nil) 487 | return; 488 | 489 | [s adopt_window:e->window initializing:NO]; 490 | } 491 | else 492 | { 493 | /* Remapping a window is the signal to make it become non-iconic. */ 494 | 495 | w->_unmapped = NO; 496 | [w activate:CurrentTime]; 497 | } 498 | } 499 | 500 | static void 501 | x_event_reparent_notify (XReparentEvent *e) 502 | { 503 | x_window *w = x_get_window (e->window); 504 | 505 | if (w == nil || w->_id != e->window || w->_id != e->event) 506 | return; 507 | 508 | [w->_screen remove_window:w]; 509 | 510 | XReparentWindow (x_dpy, e->window, e->parent, e->x, e->y); 511 | } 512 | 513 | static void 514 | x_event_unmap_notify (XUnmapEvent *e) 515 | { 516 | x_window *w = x_get_window (e->window); 517 | 518 | if (w == nil || w->_id != e->window 519 | || (e->event != w->_id && !e->send_event)) 520 | { 521 | return; 522 | } 523 | 524 | w->_unmapped = YES; 525 | [w->_screen remove_window:w]; 526 | 527 | XDeleteProperty (x_dpy, e->window, atoms.wm_state); 528 | } 529 | 530 | static void 531 | x_event_focus (XFocusChangeEvent *e) 532 | { 533 | x_window *w = x_get_window (e->window); 534 | 535 | if (e->detail == NotifyPointer || w == nil) 536 | return; 537 | 538 | if (e->type == FocusIn) 539 | { 540 | [w x_focus_in]; 541 | } 542 | else if (e->type == FocusOut) 543 | { 544 | if (e->detail != NotifyInferior) 545 | { 546 | [w x_focus_out]; 547 | } 548 | } 549 | } 550 | 551 | static void 552 | x_event_crossing (XCrossingEvent *e) 553 | { 554 | x_window *w = x_get_window (e->window); 555 | 556 | if (w == nil) 557 | return; 558 | 559 | if (e->window == w->_tracking_id) 560 | { 561 | if (pointer_state.clicking) 562 | return; 563 | 564 | if (e->type == EnterNotify) 565 | w->_frame_attr |= XP_FRAME_ATTR_PRELIGHT; 566 | else if (e->type == LeaveNotify) 567 | w->_frame_attr &= ~XP_FRAME_ATTR_PRELIGHT; 568 | 569 | [w decorate]; 570 | } 571 | else if (e->window == w->_frame_id && focus_follows_mouse) 572 | { 573 | if (e->type == EnterNotify) 574 | [w focus:e->time raise:NO]; 575 | } 576 | } 577 | 578 | static void 579 | x_event_configure_notify (XConfigureEvent *e) 580 | { 581 | x_window *w; 582 | x_screen *s; 583 | 584 | if (e->send_event) 585 | return; 586 | 587 | w = x_get_window (e->window); 588 | 589 | if (w != nil) 590 | { 591 | X11Rect r = X11RectMake (e->x, e->y, e->width, e->height); 592 | 593 | if (e->window == w->_frame_id) 594 | { 595 | [w report_frame_size:r]; 596 | } 597 | } 598 | else 599 | { 600 | s = x_get_screen_with_root (e->window); 601 | 602 | if (s != nil) 603 | { 604 | if(!XRRUpdateConfiguration((XEvent *)e)) { 605 | asl_log(aslc, NULL, ASL_LEVEL_WARNING, "XRRUpdateConfiguration failed."); 606 | } 607 | 608 | [s update_geometry]; 609 | [s foreach_window:@selector (validate_position)]; 610 | } 611 | } 612 | } 613 | 614 | static void x_event_configure_request(XConfigureRequestEvent *e) { 615 | x_window *w = x_get_window (e->window); 616 | 617 | XWindowChanges client_changes, real_frame_changes, *frame_changes; 618 | unsigned long client_mask, real_frame_mask, *frame_mask; 619 | 620 | if(w != nil && e->window != w->_id) 621 | w = nil; 622 | 623 | if(w == nil) { 624 | /* whatever.. */ 625 | 626 | client_changes.stack_mode = e->detail; 627 | client_changes.sibling = e->above; 628 | client_changes.x = e->x; 629 | client_changes.y = e->y; 630 | client_changes.width = e->width; 631 | client_changes.height = e->height; 632 | 633 | XConfigureWindow (x_dpy, e->window, e->value_mask, &client_changes); 634 | 635 | return; 636 | } 637 | 638 | if(e->value_mask & CWBorderWidth) 639 | w->_xattr.border_width = e->border_width; 640 | 641 | //[w update_shaped]; 642 | 643 | client_mask = real_frame_mask = 0; 644 | 645 | frame_changes = w->_reparented ? &real_frame_changes : &client_changes; 646 | frame_mask = w->_reparented ? &real_frame_mask : &client_mask; 647 | 648 | if (e->value_mask & CWStackMode) { 649 | frame_changes->stack_mode = e->detail; 650 | *frame_mask |= CWStackMode; 651 | 652 | if(e->value_mask & CWSibling) { 653 | frame_changes->sibling = e->above; 654 | *frame_mask |= CWSibling; 655 | } 656 | } 657 | 658 | if(e->value_mask & (CWX | CWY | CWWidth | CWHeight)) { 659 | X11Rect client_rect = X11RectMake(w->_xattr.x, w->_xattr.y, 660 | w->_xattr.width, w->_xattr.height); 661 | if (e->value_mask & CWX) 662 | client_rect.x = e->x; 663 | if (e->value_mask & CWY) 664 | client_rect.y = e->y; 665 | if (e->value_mask & CWWidth) 666 | client_rect.width = e->width; 667 | if (e->value_mask & CWHeight) 668 | client_rect.height = e->height; 669 | 670 | [w resize_client:client_rect]; 671 | } 672 | 673 | if(real_frame_mask) { 674 | XConfigureWindow(x_dpy, w->_frame_id, 675 | real_frame_mask, &real_frame_changes); 676 | } 677 | 678 | if(client_mask) { 679 | XConfigureWindow(x_dpy, w->_id, client_mask, &client_changes); 680 | } 681 | } 682 | 683 | static void 684 | x_event_shape_notify (XShapeEvent *e) 685 | { 686 | x_window *w = x_get_window (e->window); 687 | 688 | if (w == nil || w->_id != e->window || e->kind != ShapeBounding) 689 | return; 690 | 691 | w->_shaped = e->shaped ? YES : NO; 692 | w->_shaped_empty = (e->shaped && (e->width <= 0 || e->height <= 0)); 693 | 694 | [w update_shape]; 695 | } 696 | 697 | static void 698 | x_event_expose (XExposeEvent *e) 699 | { 700 | x_window *w = x_get_window (e->window); 701 | 702 | if (w == nil || w->_frame_id != e->window) 703 | return; 704 | 705 | if (e->count == 0) 706 | [w expose]; 707 | } 708 | 709 | static void 710 | x_event_colormap_notify (XColormapEvent *e) 711 | { 712 | x_window *w = x_get_window (e->window); 713 | 714 | if (w == nil || w->_id != e->window || e->new == 0) 715 | return; 716 | 717 | if (w->_focused) 718 | [w install_colormaps]; 719 | } 720 | 721 | static void 722 | x_event_mapping_notify (XMappingEvent *e) 723 | { 724 | x_update_keymap (); 725 | } 726 | 727 | static void 728 | x_event_apple_wm_notify (XAppleWMNotifyEvent *e) 729 | { 730 | static const char *controller_kinds[] = { 731 | "Minimizewindow", "ZoomWindow", "CloseWindow", 732 | "BringAllToFront", "HideWindow", "HideAll", "ShowAll", 733 | "Unknown", "Unknown", "WindowMenuItem", "WindowMenuNotify", 734 | "NextWindow", "PreviousWindow", 735 | }; 736 | 737 | static const char *activation_kinds[] = { 738 | "IsActive", "IsInactive", "ReloadPreferences" 739 | }; 740 | 741 | switch (e->type - x_apple_wm_event_base) 742 | { 743 | case AppleWMControllerNotify: 744 | if (e->kind >= 0 && e->kind < (int) (sizeof (controller_kinds) 745 | / sizeof (controller_kinds[0]))) 746 | { 747 | DB("kind %s arg %d", controller_kinds[e->kind], e->arg); 748 | } 749 | else 750 | { 751 | DB("kind %d arg %d", e->kind, e->arg); 752 | } 753 | 754 | switch (e->kind) 755 | { 756 | x_window *w; 757 | 758 | case AppleWMMinimizeWindow: 759 | case AppleWMZoomWindow: 760 | case AppleWMCloseWindow: 761 | case AppleWMHideWindow: 762 | w = x_get_active_window (); 763 | if (w != nil) 764 | { 765 | if (e->kind == AppleWMMinimizeWindow) 766 | [w do_collapse]; 767 | else if (e->kind == AppleWMZoomWindow) 768 | [w do_zoom]; 769 | else if (e->kind == AppleWMCloseWindow) 770 | [w do_close:e->time]; 771 | else if (e->kind == AppleWMHideWindow) 772 | [w do_hide]; 773 | } 774 | break; 775 | 776 | case AppleWMBringAllToFront: 777 | x_show_all (e->time, NO); 778 | x_bring_all_to_front (e->time); 779 | break; 780 | 781 | case AppleWMHideAll: 782 | x_hide_all (e->time); 783 | break; 784 | 785 | case AppleWMShowAll: 786 | x_show_all (e->time, NO); 787 | break; 788 | 789 | case AppleWMWindowMenuItem: 790 | x_activate_window_in_menu (e->arg, e->time); 791 | break; 792 | 793 | case AppleWMWindowMenuNotify: 794 | /* FIXME: do something? */ 795 | break; 796 | 797 | case AppleWMNextWindow: 798 | next_window (e->time, FALSE); 799 | break; 800 | 801 | case AppleWMPreviousWindow: 802 | next_window (e->time, TRUE); 803 | break; 804 | } 805 | break; 806 | 807 | case AppleWMActivationNotify: 808 | if (e->kind >= 0 && e->kind < (int) (sizeof (activation_kinds) 809 | / sizeof (activation_kinds[0]))) 810 | { 811 | DB("kind %s arg %d", activation_kinds[e->kind], e->arg); 812 | } 813 | else 814 | { 815 | DB("kind %d arg %d", e->kind, e->arg); 816 | } 817 | 818 | switch (e->kind) 819 | { 820 | case AppleWMIsActive: 821 | last_activation_time = e->time; 822 | x_set_is_active (YES); 823 | break; 824 | 825 | case AppleWMIsInactive: 826 | x_set_is_active (NO); 827 | break; 828 | 829 | case AppleWMReloadPreferences: 830 | prefs_reload = YES; 831 | break; 832 | } 833 | break; 834 | } 835 | } 836 | 837 | static const char * 838 | event_name (int type) 839 | { 840 | switch (type) 841 | { 842 | static char buf[64]; 843 | 844 | case KeyPress: return "KeyPress"; 845 | case KeyRelease: return "KeyRelease"; 846 | case ButtonPress: return "ButtonPress"; 847 | case ButtonRelease: return "ButtonRelease"; 848 | case MotionNotify: return "MotionNotify"; 849 | case EnterNotify: return "EnterNotify"; 850 | case LeaveNotify: return "LeaveNotify"; 851 | case FocusIn: return "FocusIn"; 852 | case FocusOut: return "FocusOut"; 853 | case KeymapNotify: return "KeymapNotify"; 854 | case Expose: return "Expose"; 855 | case GraphicsExpose: return "GraphicsExpose"; 856 | case NoExpose: return "NoExpose"; 857 | case VisibilityNotify: return "VisibilityNotify"; 858 | case CreateNotify: return "CreateNotify"; 859 | case DestroyNotify: return "DestroyNotify"; 860 | case UnmapNotify: return "UnmapNotify"; 861 | case MapNotify: return "MapNotify"; 862 | case MapRequest: return "MapRequest"; 863 | case ReparentNotify: return "ReparentNotify"; 864 | case ConfigureNotify: return "ConfigureNotify"; 865 | case ConfigureRequest: return "ConfigureRequest"; 866 | case GravityNotify: return "GravityNotify"; 867 | case ResizeRequest: return "ResizeRequest"; 868 | case CirculateNotify: return "CirculateNotify"; 869 | case CirculateRequest: return "CirculateRequest"; 870 | case PropertyNotify: return "PropertyNotify"; 871 | case SelectionClear: return "SelectionClear"; 872 | case SelectionRequest: return "SelectionRequest"; 873 | case SelectionNotify: return "SelectionNotify"; 874 | case ColormapNotify: return "ColormapNotify"; 875 | case ClientMessage: return "ClientMessage"; 876 | case MappingNotify: return "MappingNotify"; 877 | 878 | default: 879 | if (type == x_shape_event_base + ShapeNotify) 880 | return "ShapeNotify"; 881 | else if (type == x_apple_wm_event_base + AppleWMControllerNotify) 882 | return "AppleWMControllerNotify"; 883 | sprintf (buf, "Unknown:%d", type); 884 | return buf; 885 | } 886 | } 887 | 888 | void 889 | x_input_run (void) 890 | { 891 | while (XPending (x_dpy) != 0) 892 | { 893 | XEvent e; 894 | 895 | XNextEvent (x_dpy, &e); 896 | 897 | DB("<%s window:%lx>", event_name (e.type), e.xany.window); 898 | 899 | switch (e.type) 900 | { 901 | case KeyPress: 902 | case KeyRelease: 903 | x_event_key (&e.xkey); 904 | break; 905 | 906 | case ButtonPress: 907 | case ButtonRelease: 908 | x_event_button (&e.xbutton); 909 | break; 910 | 911 | case MotionNotify: 912 | x_event_motion_notify (&e.xmotion); 913 | break; 914 | 915 | case FocusIn: 916 | case FocusOut: 917 | x_event_focus (&e.xfocus); 918 | break; 919 | 920 | case EnterNotify: 921 | case LeaveNotify: 922 | x_event_crossing (&e.xcrossing); 923 | break; 924 | 925 | case DestroyNotify: 926 | x_event_destroy_notify (&e.xdestroywindow); 927 | break; 928 | 929 | case UnmapNotify: 930 | x_event_unmap_notify (&e.xunmap); 931 | break; 932 | 933 | case MapRequest: 934 | x_event_map_request (&e.xmaprequest); 935 | break; 936 | 937 | case ReparentNotify: 938 | x_event_reparent_notify (&e.xreparent); 939 | break; 940 | 941 | case ConfigureRequest: 942 | x_event_configure_request (&e.xconfigurerequest); 943 | break; 944 | 945 | case ConfigureNotify: 946 | x_event_configure_notify (&e.xconfigure); 947 | break; 948 | 949 | case PropertyNotify: 950 | x_event_property_notify (&e.xproperty); 951 | break; 952 | 953 | case ClientMessage: 954 | x_event_client_message (&e.xclient); 955 | break; 956 | 957 | case Expose: 958 | x_event_expose (&e.xexpose); 959 | break; 960 | 961 | case ColormapNotify: 962 | x_event_colormap_notify (&e.xcolormap); 963 | break; 964 | 965 | case MappingNotify: 966 | x_event_mapping_notify (&e.xmapping); 967 | break; 968 | 969 | default: 970 | if (e.type == x_shape_event_base + ShapeNotify) 971 | x_event_shape_notify ((XShapeEvent *) &e); 972 | else if (e.type - x_apple_wm_event_base >= 0 973 | && e.type - x_apple_wm_event_base < AppleWMNumberEvents) 974 | { 975 | x_event_apple_wm_notify ((XAppleWMNotifyEvent *) &e); 976 | } 977 | break; 978 | } 979 | 980 | #ifdef CHECK_WINDOWS 981 | x_check_windows (); 982 | #endif 983 | } 984 | } 985 | 986 | static int 987 | add_input_socket (int sock, CFOptionFlags callback_types, 988 | CFSocketCallBack callback, const CFSocketContext *ctx, 989 | CFRunLoopSourceRef *cf_source) 990 | { 991 | CFSocketRef cf_sock; 992 | 993 | cf_sock = CFSocketCreateWithNative (kCFAllocatorDefault, sock, 994 | callback_types, callback, ctx); 995 | if (cf_sock == NULL) 996 | { 997 | close (sock); 998 | return FALSE; 999 | } 1000 | 1001 | *cf_source = CFSocketCreateRunLoopSource (kCFAllocatorDefault, 1002 | cf_sock, 0); 1003 | CFRelease (cf_sock); 1004 | 1005 | if (*cf_source == NULL) 1006 | return FALSE; 1007 | 1008 | CFRunLoopAddSource (CFRunLoopGetCurrent (), 1009 | *cf_source, kCFRunLoopDefaultMode); 1010 | return TRUE; 1011 | } 1012 | 1013 | static void 1014 | x_input_callback (CFSocketRef sock, CFSocketCallBackType type, 1015 | CFDataRef address, const void *data, void *info) 1016 | { 1017 | x_input_run (); 1018 | } 1019 | 1020 | void 1021 | x_input_register (void) 1022 | { 1023 | if (!add_input_socket (ConnectionNumber (x_dpy), kCFSocketReadCallBack, 1024 | x_input_callback, NULL, &x_dpy_source)) 1025 | { 1026 | exit (1); 1027 | } 1028 | } 1029 | -------------------------------------------------------------------------------- /src/x-screen.m: -------------------------------------------------------------------------------- 1 | /* x-screen.m 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include "quartz-wm.h" 30 | #include "utils.h" 31 | #import "x-screen.h" 32 | #import "x-window.h" 33 | 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | @interface x_screen (local) 41 | - (void) net_wm_init; 42 | @end 43 | 44 | @implementation x_screen 45 | 46 | static XID default_cursor; 47 | 48 | // To rebuild this list: 49 | // 50 | // $ grep _NET_ *.m | sed -e 's/.*\("_NET_[A-Z_]*"\).*/ \1,/' | sort | uniq 51 | 52 | static const char *net_wm_supported[] = { 53 | "_NET_ACTIVE_WINDOW", 54 | "_NET_CLIENT_LIST", 55 | "_NET_CLIENT_LIST_STACKING", 56 | "_NET_CLOSE_WINDOW", 57 | "_NET_SUPPORTED", 58 | "_NET_SUPPORTING_WM_CHECK", 59 | "_NET_WM_ACTION_CLOSE", 60 | "_NET_WM_ACTION_FULLSCREEN", 61 | "_NET_WM_ACTION_MAXIMIZE_HORZ", 62 | "_NET_WM_ACTION_MAXIMIZE_VERT", 63 | "_NET_WM_ACTION_MINIMIZE", 64 | "_NET_WM_ACTION_MOVE", 65 | "_NET_WM_ACTION_RESIZE", 66 | "_NET_WM_ACTION_SHADE", 67 | "_NET_WM_ALLOWED_ACTIONS", 68 | "_NET_WM_NAME", 69 | "_NET_WM_STATE", 70 | "_NET_WM_STATE_FULLSCREEN", 71 | "_NET_WM_STATE_HIDDEN", 72 | "_NET_WM_STATE_MAXIMIZED_HORZ", 73 | "_NET_WM_STATE_MAXIMIZED_VERT", 74 | "_NET_WM_STATE_MODAL", 75 | "_NET_WM_STATE_SHADED", 76 | "_NET_WM_STATE_SKIP_PAGER", 77 | "_NET_WM_STATE_SKIP_TASKBAR", 78 | "_NET_WM_STATE_STICKY", 79 | "_NET_WM_WINDOW_TYPE", 80 | "_NET_WM_WINDOW_TYPE_COMBO", 81 | "_NET_WM_WINDOW_TYPE_DESKTOP", 82 | "_NET_WM_WINDOW_TYPE_DIALOG", 83 | "_NET_WM_WINDOW_TYPE_DND", 84 | "_NET_WM_WINDOW_TYPE_DOCK", 85 | "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", 86 | "_NET_WM_WINDOW_TYPE_MENU", 87 | "_NET_WM_WINDOW_TYPE_NORMAL", 88 | "_NET_WM_WINDOW_TYPE_NOTIFICATION", 89 | "_NET_WM_WINDOW_TYPE_POPUP_MENU", 90 | "_NET_WM_WINDOW_TYPE_SPLASH", 91 | "_NET_WM_WINDOW_TYPE_TOOLBAR", 92 | "_NET_WM_WINDOW_TYPE_TOOLTIP", 93 | "_NET_WM_WINDOW_TYPE_UTILITY", 94 | }; 95 | 96 | #ifdef CHECK_WINDOWS 97 | static void *check_window (void *w, void *data) 98 | { 99 | assert ([((x_window *) w) isKindOfClass:[x_window class]]); 100 | return w; 101 | } 102 | 103 | - (void) check_window_lists 104 | { 105 | x_list_map (_window_list, check_window, NULL); 106 | x_list_map (_stacking_list, check_window, NULL); 107 | } 108 | #endif 109 | 110 | static inline BOOL 111 | adoptable (Window xwindow_id) 112 | { 113 | XWindowAttributes attr; 114 | 115 | XGetWindowAttributes (x_dpy, xwindow_id, &attr); 116 | 117 | return attr.map_state != IsUnmapped && attr.override_redirect != True; 118 | } 119 | 120 | - (void) set_property:(Window)xwindow_id name:(const char *)name 121 | type:(const char *)type length:(int)length data:(const long *)data 122 | { 123 | Atom name_atom, type_atom; 124 | 125 | name_atom = XInternAtom (x_dpy, name, False); 126 | type_atom = XInternAtom (x_dpy, type, False); 127 | 128 | XChangeProperty (x_dpy, xwindow_id, name_atom, type_atom, 32, 129 | PropModeReplace, (const unsigned char *) data, length); 130 | } 131 | 132 | - (void) set_root_property:(const char *)name type:(const char *)type 133 | length:(int)length data:(const long *)data 134 | { 135 | [self set_property:_root name:name type:type length:length data:data]; 136 | } 137 | 138 | - (void) update_geometry 139 | { 140 | long data[2]; 141 | int i; 142 | X11Region region_temp; 143 | 144 | TRACE (); 145 | 146 | if (x_get_property (_root, atoms.native_screen_origin, data, 2, 2)) 147 | { 148 | _x = data[0]; 149 | _y = data[1]; 150 | } 151 | 152 | _width = WidthOfScreen (_screen); 153 | _height = HeightOfScreen (_screen); 154 | 155 | DB("Screen: %dx%d", _width, _height); 156 | 157 | /* Release the region we had before */ 158 | if(_screen_region != NULL) { 159 | pixman_region32_fini(_screen_region); 160 | free(_screen_region); 161 | _screen_region = NULL; 162 | } 163 | 164 | if (XineramaIsActive (x_dpy)) 165 | { 166 | XineramaScreenInfo *info; 167 | 168 | info = XineramaQueryScreens (x_dpy, &_head_count); 169 | 170 | if (info != NULL && _head_count >= 1) 171 | { 172 | _heads = realloc (_heads, sizeof (_heads[0]) * _head_count); 173 | 174 | if (_heads != NULL) 175 | { 176 | for (i = 0; i < _head_count; i++) 177 | { 178 | DB("head %d: %d,%d %dx%d", i, 179 | info[i].x_org, info[i].y_org, 180 | info[i].width, info[i].height); 181 | 182 | _heads[i] = X11RectMake(info[i].x_org, info[i].y_org, 183 | info[i].width, info[i].height); 184 | 185 | if (_screen_region == NULL) { 186 | _screen_region = (X11Region *)malloc(sizeof(X11Region)); 187 | if(!_screen_region) { 188 | asl_log(aslc, NULL, ASL_LEVEL_ERR, "Memory allocation error."); 189 | abort(); 190 | } 191 | 192 | pixman_region32_init_rect(_screen_region, 193 | info[i].x_org, info[i].y_org, 194 | info[i].width, info[i].height); 195 | } else { 196 | pixman_region32_init(®ion_temp); 197 | pixman_region32_union_rect(®ion_temp, _screen_region, 198 | info[i].x_org, info[i].y_org, 199 | info[i].width, info[i].height); 200 | pixman_region32_fini(_screen_region); 201 | *_screen_region = region_temp; 202 | } 203 | } 204 | } 205 | else 206 | _head_count = 0; 207 | } 208 | else 209 | { 210 | if (_heads != NULL) 211 | { 212 | free (_heads); 213 | _heads = NULL; 214 | } 215 | _head_count = 0; 216 | } 217 | 218 | if (info != NULL) 219 | XFree (info); 220 | } 221 | 222 | if (_head_count == 0) { 223 | _main_head = X11RectMake(_x, _y, _width, _height); 224 | _screen_region = (X11Region *)malloc(sizeof(X11Region)); 225 | if(!_screen_region) { 226 | asl_log(aslc, NULL, ASL_LEVEL_ERR, "Memory allocation error."); 227 | abort(); 228 | } 229 | pixman_region32_init_rect(_screen_region, _x, _y, _width, _height); 230 | } else { 231 | /* find head nearest to native 0,0 */ 232 | 233 | int nearest_i = -1, nearest_d = INT_MAX; 234 | 235 | for (i = 0; i < _head_count; i++) 236 | { 237 | int dx, dy, d; 238 | 239 | dx = _heads[i].x + _x; 240 | dy = _heads[i].y + _y; 241 | d = dx * dx + dy * dy; 242 | 243 | if (d < nearest_d) 244 | { 245 | nearest_d = d; 246 | nearest_i = i; 247 | } 248 | } 249 | 250 | assert (nearest_i >= 0); 251 | _main_head = _heads[nearest_i]; 252 | 253 | DB("main head has index %d", nearest_i); 254 | } 255 | } 256 | 257 | - (void) update_client_list:(x_list *)lst prop:(const char *)name 258 | { 259 | long *ids = NULL; 260 | int n_ids, i; 261 | x_list *node; 262 | x_window *w; 263 | 264 | n_ids = x_list_length (lst); 265 | 266 | if (n_ids > 0) 267 | { 268 | ids = alloca (sizeof (*ids) * n_ids); 269 | 270 | for (i = 0, node = lst; node != NULL; node = node->next, i++) 271 | { 272 | w = node->data; 273 | ids[i] = w->_id; 274 | } 275 | } 276 | 277 | [self set_root_property:name type:"WINDOW" length:n_ids data:ids]; 278 | } 279 | 280 | - (void) update_net_client_list 281 | { 282 | [self update_client_list:_window_list prop:"_NET_CLIENT_LIST"]; 283 | } 284 | 285 | - (void) update_net_client_list_stacking 286 | { 287 | [self update_client_list:_stacking_list prop:"_NET_CLIENT_LIST_STACKING"]; 288 | } 289 | 290 | static int 291 | stacking_order_pred (void *item, void *data) 292 | { 293 | return x_list_find (data, item) != NULL; 294 | } 295 | 296 | - (x_list *) stacking_order:(x_list *)group 297 | { 298 | return x_list_filter (_stacking_list, stacking_order_pred, group); 299 | } 300 | 301 | static int 302 | window_level_less (const void *a, const void *b) 303 | { 304 | static const int phys[AppleWMNumWindowLevels] = {0, 1, 2, -1, -2}; 305 | const x_window *x = a, *y = b; 306 | 307 | return phys[x->_level] > phys[y->_level]; 308 | } 309 | 310 | - (void) raise_windows:(id *)array count:(size_t)n 311 | { 312 | size_t i, j, seen; 313 | Window *ids; 314 | x_list *node; 315 | 316 | #ifdef CHECK_WINDOWS 317 | [self check_window_lists]; 318 | #endif 319 | 320 | if (n == 0) 321 | return; 322 | 323 | /* 1. Move all windows being raised to the head of the stacking list. */ 324 | 325 | for (i = n - 1; ; i--) 326 | { 327 | _stacking_list = x_list_remove (_stacking_list, array[i]); 328 | _stacking_list = x_list_prepend (_stacking_list, array[i]); 329 | 330 | if(i == 0) 331 | break; 332 | } 333 | 334 | /* 2. Sort the new stacking list by window level. */ 335 | 336 | _stacking_list = x_list_sort (_stacking_list, window_level_less); 337 | 338 | /* 3. Scan the resulting list for each of the raised windows (ugh), 339 | raising each below their predecessor. Luckily we'll only ever 340 | have a small N here. However, we also have to raise all the 341 | other windows down to the bottommost changed window, to be sure 342 | that X actually moves the ones we moved to where we want.. */ 343 | 344 | ids = alloca (sizeof (Window) * x_list_length (_stacking_list)); 345 | seen = 0; 346 | 347 | for (i = 0, node = _stacking_list; 348 | seen < n && node != NULL; i++, node = node->next) 349 | { 350 | x_window *w = node->data; 351 | 352 | ids[i] = [w toplevel_id]; 353 | 354 | for (j = 0; j < n; j++) 355 | { 356 | if (node->data == array[j]) 357 | { 358 | seen++; 359 | break; 360 | } 361 | } 362 | } 363 | 364 | if(_stacking_list != NULL) 365 | XRaiseWindow (x_dpy, ids[0]); 366 | if (i > 1) 367 | XRestackWindows (x_dpy, ids, i); 368 | 369 | [self update_net_client_list_stacking]; 370 | } 371 | 372 | - init_with_screen_id:(int)xscreen_id 373 | { 374 | self = [super init]; 375 | if (self == nil) 376 | return nil; 377 | 378 | _id = xscreen_id; 379 | _screen = ScreenOfDisplay (x_dpy, _id); 380 | _root = RootWindowOfScreen (_screen); 381 | _depth = DefaultDepthOfScreen (_screen); 382 | _visual = DefaultVisualOfScreen (_screen); 383 | _colormap = DefaultColormapOfScreen (_screen); 384 | _black_pixel = BlackPixelOfScreen (_screen); 385 | 386 | [self update_geometry]; 387 | 388 | DB("%d, %dx%dx%d, root:%lx, %d heads", 389 | xscreen_id, _width, _height, _depth, _root, _head_count); 390 | 391 | XSelectInput (x_dpy, _root, X_ROOT_WINDOW_EVENTS); 392 | 393 | [self net_wm_init]; 394 | 395 | return self; 396 | } 397 | 398 | - (void) dealloc 399 | { 400 | if (_head_count > 0) 401 | free (_heads); 402 | 403 | if(_screen_region != NULL) { 404 | pixman_region32_fini(_screen_region); 405 | free(_screen_region); 406 | } 407 | 408 | [super dealloc]; 409 | } 410 | 411 | - (void) net_wm_init 412 | { 413 | long data, *supported_atoms; 414 | 415 | if (_net_wm_window != 0) 416 | return; 417 | 418 | _net_wm_window = XCreateSimpleWindow (x_dpy, _root, 0, 0, 1, 1, 0, 0, 0); 419 | 420 | if (_net_wm_window != 0) 421 | { 422 | int i, n; 423 | 424 | data = _net_wm_window; 425 | 426 | [self set_property:_net_wm_window name:"_NET_SUPPORTING_WM_CHECK" 427 | type:"WINDOW" length:1 data:&data]; 428 | [self set_root_property:"_NET_SUPPORTING_WM_CHECK" 429 | type:"WINDOW" length:1 data:&data]; 430 | 431 | n = sizeof (net_wm_supported) / sizeof (net_wm_supported[0]); 432 | supported_atoms = alloca (n * sizeof (long)); 433 | 434 | for (i = 0; i < n; i++) 435 | supported_atoms[i] = XInternAtom (x_dpy, net_wm_supported[i], False); 436 | 437 | [self set_root_property:"_NET_SUPPORTED" 438 | type:"ATOM" length:n data:supported_atoms]; 439 | } 440 | } 441 | 442 | - (void) focus_topmost:(Time)timestamp 443 | { 444 | x_window *w; 445 | x_list *sl; 446 | CGError err; 447 | xp_bool isVisible; 448 | 449 | for(sl = _stacking_list; sl; sl = sl->next) { 450 | w = sl->data; 451 | err = qwm_dock_is_window_visible([w get_osx_id], &isVisible); 452 | if(!err && isVisible) { 453 | [w focus:timestamp]; 454 | return; 455 | } 456 | } 457 | } 458 | 459 | - (void) adopt_window:(Window)xwindow_id initializing:(BOOL)flag 460 | { 461 | x_window *w; 462 | 463 | DB("id: %lx initializing: %s", xwindow_id, flag ? "YES" : "NO"); 464 | 465 | w = [[x_window alloc] init_with_id:xwindow_id screen:self initializing:flag]; 466 | 467 | /* Need to preserve oldest-first order. */ 468 | _window_list = x_list_append (_window_list, w); 469 | _stacking_list = x_list_append (_stacking_list, w); 470 | 471 | if (!flag) 472 | [self update_net_client_list]; 473 | 474 | x_change_window_count (+1); 475 | } 476 | 477 | - (void) remove_window:(x_window *)w safe:(BOOL)safe 478 | { 479 | DB("w:%lx safe:%s", w->_id, safe ? "YES" : "NO"); 480 | 481 | #ifdef CHECK_WINDOWS 482 | [self check_window_lists]; 483 | #endif 484 | 485 | if (!safe) 486 | { 487 | /* Being called from somewhere where we can't make X protocol 488 | request. (the error handler) */ 489 | 490 | if (!w->_removed) 491 | { 492 | [NSTimer scheduledTimerWithTimeInterval:0.01 493 | target:self selector:@selector(remove_callback:) 494 | userInfo:w repeats:NO]; 495 | 496 | w->_removed = YES; 497 | } 498 | } 499 | else if (!w->_deleted) 500 | { 501 | _stacking_list = x_list_remove (_stacking_list, w); 502 | 503 | w->_removed = YES; 504 | [w reparent_out]; 505 | 506 | if (w->_focused) 507 | [self focus_topmost:CurrentTime]; 508 | 509 | x_remove_window_from_menu (w); 510 | 511 | /* Don't remove the window from the list until after successfully 512 | removing it from the display. If an X I/O error occurs while 513 | removing it, we want to have it in the list when exiting, so 514 | that its dock icon can be removed it necessary. */ 515 | 516 | _window_list = x_list_remove (_window_list, w); 517 | w->_deleted = YES; 518 | [w release]; 519 | 520 | [self update_net_client_list]; 521 | 522 | x_change_window_count (-1); 523 | } 524 | 525 | #ifdef CHECK_WINDOWS 526 | [self check_window_lists]; 527 | #endif 528 | } 529 | 530 | - (void) remove_window:(x_window *)w 531 | { 532 | [self remove_window:w safe:YES]; 533 | } 534 | 535 | - (void) remove_callback:(NSTimer *)timer 536 | { 537 | [self remove_window:[timer userInfo] safe:YES]; 538 | 539 | XFlush (x_dpy); 540 | } 541 | 542 | - (void) window_hidden:(x_window *)w 543 | { 544 | if (!w->_removed) 545 | { 546 | _stacking_list = x_list_remove (_stacking_list, w); 547 | _stacking_list = x_list_append (_stacking_list, w); 548 | 549 | if (w->_focused) 550 | [self focus_topmost:CurrentTime]; 551 | } 552 | } 553 | 554 | - (void) adopt_windows 555 | { 556 | Window root, parent, *children; 557 | unsigned n_children, i; 558 | 559 | x_grab_server (True); 560 | 561 | n_children = 0; 562 | XQueryTree (x_dpy, _root, &root, &parent, &children, &n_children); 563 | 564 | for (i = 0; i < n_children; i++) 565 | { 566 | if (adoptable (children[i])) 567 | { 568 | [self adopt_window:children[i] initializing:YES]; 569 | } 570 | } 571 | 572 | if (n_children > 0) 573 | XFree (children); 574 | 575 | x_ungrab_server (); 576 | 577 | [self update_net_client_list]; 578 | 579 | if (default_cursor == 0) 580 | default_cursor = XCreateFontCursor (x_dpy, XC_left_ptr); 581 | 582 | XDefineCursor (x_dpy, _root, default_cursor); 583 | } 584 | 585 | - (void) unadopt_windows 586 | { 587 | x_list *copy, *node; 588 | 589 | copy = x_list_copy (_window_list); 590 | 591 | for (node = copy; node != NULL; node = node->next) 592 | { 593 | x_window *w = node->data; 594 | 595 | [self remove_window:w]; 596 | } 597 | 598 | x_list_free (copy); 599 | } 600 | 601 | - (void) error_shutdown 602 | { 603 | x_list *node; 604 | 605 | for (node = _window_list; node != NULL; node = node->next) 606 | { 607 | x_window *w = node->data; 608 | 609 | [w error_shutdown]; 610 | } 611 | } 612 | 613 | - get_window:(Window)xwindow_id 614 | { 615 | x_list *node; 616 | 617 | for (node = _window_list; node != NULL; node = node->next) 618 | { 619 | x_window *w = node->data; 620 | 621 | if (w->_id == xwindow_id) 622 | return w; 623 | 624 | if (!w->_deleted && (w->_frame_id == xwindow_id 625 | || w->_tracking_id == xwindow_id 626 | || w->_growbox_id == xwindow_id)) 627 | { 628 | return w; 629 | } 630 | } 631 | 632 | return nil; 633 | } 634 | 635 | - get_window_by_osx_id:(xp_native_window_id)osxwindow_id 636 | { 637 | x_list *node; 638 | 639 | for (node = _window_list; node != NULL; node = node->next) 640 | { 641 | x_window *w = node->data; 642 | xp_native_window_id wid; 643 | 644 | if (w->_deleted) 645 | continue; 646 | 647 | wid = [w get_osx_id]; 648 | if (osxwindow_id == wid) 649 | return w; 650 | } 651 | 652 | return nil; 653 | } 654 | 655 | - (X11Rect) validate_window_position:(X11Rect)win_rect titlebar_height:(size_t)titlebar_height { 656 | X11Region tem; 657 | X11Region win_int, title_int; 658 | X11Region win_region, title_region, dock_region; 659 | X11Region screen_region_no_dock; 660 | X11Rect title_rect, title_int_rect; 661 | X11Rect ret, dock_rect; 662 | pixman_box32_t *e; 663 | xp_box dock_box; 664 | 665 | TRACE(); 666 | 667 | // Figure out where the dock is to handle 668 | // X11 window can get lost under the dock 669 | // http://xquartz.macosforge.org/trac/ticket/329 670 | dock_box = qwm_dock_get_rect(); 671 | dock_rect = [self CGToX11Rect:CGRectMake(dock_box.x1, dock_box.y1, 672 | dock_box.x2 - dock_box.x1, 673 | dock_box.y2 - dock_box.y1)]; 674 | 675 | ret = title_rect = win_rect; 676 | title_rect.height = titlebar_height; 677 | 678 | // make a region of just the dock, window, and titlebar 679 | pixman_region32_init_rect(&dock_region, dock_rect.x, dock_rect.y, 680 | dock_rect.width, dock_rect.height); 681 | pixman_region32_init_rect(&win_region, win_rect.x, win_rect.y, 682 | win_rect.width, win_rect.height); 683 | pixman_region32_init_rect(&title_region, title_rect.x, title_rect.y, 684 | title_rect.width, title_rect.height); 685 | 686 | // Make a region of our screen without the dock 687 | pixman_region32_init(&screen_region_no_dock); 688 | pixman_region32_init(&tem); 689 | // This should always be dock_region, but we're being careful 690 | pixman_region32_intersect(&tem, _screen_region, &dock_region); 691 | pixman_region32_subtract(&screen_region_no_dock, _screen_region, &tem); 692 | pixman_region32_fini(&tem); 693 | 694 | // Make win_int the region of our window that is on our display and not 695 | // in the dock 696 | pixman_region32_init(&win_int); 697 | pixman_region32_intersect(&win_int, &screen_region_no_dock, &win_region); 698 | 699 | // Make title_int the region of our titlebar that is on our display and not 700 | // in the dock 701 | pixman_region32_init(&title_int); 702 | pixman_region32_intersect(&title_int, &screen_region_no_dock, &title_region); 703 | 704 | // Get a rect of the bounding box for the internal titlebar. 705 | e = pixman_region32_extents(&title_int); 706 | title_int_rect = X11RectMake(e->x1, e->y1, e->x2 - e->x1, e->y2 - e->y1); 707 | pixman_region32_fini(&title_int); 708 | 709 | DB(" win_rect: %d,%d %dx%d", win_rect.x, win_rect.y, win_rect.width, win_rect.height); 710 | DB(" dock_rect: %d,%d %dx%d", dock_rect.x, dock_rect.y, dock_rect.width, dock_rect.height); 711 | e = pixman_region32_extents(_screen_region); 712 | DB(" screen_rect: %d,%d %dx%d", e->x1, e->y1, e->x2 - e->x1, e->y2 - e->y1); 713 | e = pixman_region32_extents(&screen_region_no_dock); 714 | DB(" screen_no_dock: %d,%d %dx%d", e->x1, e->y1, e->x2 - e->x1, e->y2 - e->y1); 715 | DB(" title_rect: %d,%d %dx%d", title_rect.x, title_rect.y, title_rect.width, title_rect.height); 716 | DB(" title_int_rect: %d,%d %dx%d", title_int_rect.x, title_int_rect.y, title_int_rect.width, title_int_rect.height); 717 | e = pixman_region32_extents(&win_int); 718 | DB(" win_int_rect: %d,%d %dx%d", e->x1, e->y1, e->x2 - e->x1, e->y2 - e->y1); 719 | 720 | // Done with our screen_region_no_dock 721 | pixman_region32_fini(&screen_region_no_dock); 722 | 723 | if (!pixman_region32_not_empty(&win_int)) { 724 | X11Region win_dock_int; 725 | 726 | /* Check if we're behind the dock or offscreen */ 727 | pixman_region32_init(&win_dock_int); 728 | pixman_region32_intersect(&win_dock_int, _screen_region, &win_region); 729 | 730 | if(!pixman_region32_not_empty(&win_dock_int) || titlebar_height == 0) { 731 | /* Window wouldn't be on any display, so put it at top-left of 732 | * the main head. 733 | */ 734 | ret.y = _main_head.y; 735 | } else { 736 | /* Window is partially behind our dock. */ 737 | switch(qwm_dock_get_orientation()) { 738 | case XP_DOCK_ORIENTATION_BOTTOM: 739 | ret.y = dock_rect.y - titlebar_height; 740 | break; 741 | case XP_DOCK_ORIENTATION_LEFT: 742 | ret.x = dock_rect.x + dock_rect.width - ret.width + 40; 743 | break; 744 | case XP_DOCK_ORIENTATION_RIGHT: 745 | ret.x = dock_rect.x - 40; 746 | break; 747 | default: 748 | asl_log(aslc, NULL, ASL_LEVEL_WARNING, "Invalid response from qwm_dock_get_orientation()"); 749 | break; 750 | } 751 | } 752 | pixman_region32_fini(&win_dock_int); 753 | 754 | /* Try to preserve X position */ 755 | pixman_region32_init(&tem); 756 | pixman_region32_intersect(&tem, _screen_region, &title_region); 757 | 758 | if (!pixman_region32_not_empty(&tem)) { 759 | ret.x = _main_head.x; 760 | ret.y = _main_head.y; 761 | } 762 | 763 | pixman_region32_fini(&tem); 764 | } else if(title_int_rect.height < titlebar_height) { 765 | // The titlebar needs to have its full height on-screen 766 | int i; 767 | 768 | for (i = 0; i < _head_count; i++) { 769 | X11Rect dpy_rect, intersection; 770 | int dock_bottom_height = 0; 771 | 772 | dpy_rect = _heads[i]; 773 | 774 | if(qwm_dock_get_orientation() == XP_DOCK_ORIENTATION_BOTTOM && 775 | X11RectContainsPoint(dpy_rect, X11PointMake(dock_rect.x, dock_rect.y))) 776 | dock_bottom_height = dock_rect.height; 777 | 778 | /* Does it touch this display? */ 779 | intersection = X11RectIntersection(win_rect, dpy_rect); 780 | if(X11RectIsEmpty(intersection)) 781 | continue; 782 | 783 | if (ret.y < dpy_rect.y) { 784 | ret.y = dpy_rect.y; 785 | break; 786 | } 787 | 788 | if (ret.y + title_rect.height > dpy_rect.y + dpy_rect.height - dock_bottom_height) { 789 | ret.y = (dpy_rect.y + dpy_rect.height - title_rect.height - dock_bottom_height); 790 | break; 791 | } 792 | } 793 | } 794 | 795 | pixman_region32_fini(&win_int); 796 | pixman_region32_fini(&win_region); 797 | pixman_region32_fini(&title_region); 798 | pixman_region32_fini(&dock_region); 799 | 800 | DB(" ret: %d,%d %dx%d", ret.x, ret.y, ret.width, ret.height); 801 | return ret; 802 | } 803 | 804 | - (X11Rect) head_containing_point:(X11Point)p 805 | { 806 | int i; 807 | 808 | if (_head_count == 0) 809 | return X11RectMake(0, 0, _width, _height); 810 | 811 | for (i = 0; i < _head_count; i++) { 812 | if (X11RectContainsPoint(_heads[i], p)) 813 | return _heads[i]; 814 | } 815 | 816 | return _main_head; 817 | } 818 | 819 | /* NSPointInRect seems to follow the standard graphics ownership model which is 820 | * that the borders are owned by the region by taking an epsilon step in +x (and 821 | * if still a border, another epsilon step in +y)... that would work for us 822 | * if we didn't have an inverted Y. 823 | */ 824 | static inline BOOL MyNSPointInRect(NSPoint p, NSRect r) { 825 | // Move us to the origin to eliminate headaches 826 | p.y -= r.origin.y; 827 | r.origin.y = 0; 828 | 829 | // Mirror y across the center of the rect 830 | p.y = r.size.height - p.y; 831 | 832 | // Now use the normal check 833 | return NSPointInRect(p, r); 834 | } 835 | 836 | - (X11Rect) zoomed_rect:(X11Point)xp { 837 | NSPoint nsp; 838 | NSRect NSvisibleFrame; 839 | #if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 840 | NSEnumerator *screenEnumerator; 841 | #endif 842 | X11Rect ret; 843 | 844 | /* If the server is in rootless mode, we need to trim off the menu bar and dock */ 845 | if(!rootless) { 846 | /* We need to jump out early here becasue of: 847 | * [NSScreen visibleFrame] subtracts dock and menubar even when hidden by another app 848 | */ 849 | ret = [self head_containing_point:xp]; 850 | DB("ret: (%d,%d %dx%d)", ret.x, ret.y, ret.width, ret.height); 851 | return ret; 852 | } 853 | 854 | nsp = [self X11ToNSPoint:xp]; 855 | NSvisibleFrame = [[NSScreen mainScreen] visibleFrame]; 856 | 857 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 858 | for(id screen in [NSScreen screens]) { 859 | #else 860 | screenEnumerator = [[NSScreen screens] objectEnumerator]; 861 | id screen; 862 | while((screen = [screenEnumerator nextObject])) { 863 | #endif 864 | if(MyNSPointInRect(nsp, [screen frame])) { 865 | NSvisibleFrame = [screen visibleFrame]; 866 | break; 867 | } 868 | } 869 | 870 | ret = [self NSToX11Rect:NSvisibleFrame]; 871 | DB("ret: (%d,%d %dx%d)", ret.x, ret.y, ret.width, ret.height); 872 | return ret; 873 | } 874 | 875 | - (X11Rect) zoomed_rect 876 | { 877 | return [self zoomed_rect:X11RectOrigin(_main_head)]; 878 | } 879 | 880 | - (X11Point) center_on_head:(X11Point)p 881 | { 882 | X11Point q; 883 | int i; 884 | 885 | q.x = _width / 2; 886 | q.y = _height / 3; 887 | 888 | for (i = 0; i < _head_count; i++) 889 | { 890 | if (X11RectContainsPoint (_heads[i], p)) 891 | { 892 | q.x = _heads[i].x + _heads[i].width / 2; 893 | q.y = _heads[i].y + _heads[i].height / 3; 894 | break; 895 | } 896 | } 897 | 898 | return q; 899 | } 900 | 901 | - (void) disable_update 902 | { 903 | if (_updates_disabled) 904 | return; 905 | 906 | XAppleWMDisableUpdate (x_dpy, _id); 907 | 908 | _updates_disabled = YES; 909 | } 910 | 911 | - (void) reenable_update 912 | { 913 | if (!_updates_disabled) 914 | return; 915 | 916 | XAppleWMReenableUpdate (x_dpy, _id); 917 | 918 | _updates_disabled = NO; 919 | } 920 | 921 | - (void) raise_all 922 | { 923 | x_list *node; 924 | Window *ids; 925 | int id_count, i; 926 | 927 | id_count = x_list_length (_window_list); 928 | ids = alloca (id_count * sizeof (Window)); 929 | 930 | for (i = 0, node = _window_list; node != NULL; node = node->next) 931 | { 932 | x_window *w = node->data; 933 | 934 | if (!w->_deleted && i < id_count) 935 | ids[i++] = [w toplevel_id]; 936 | } 937 | 938 | if (i > 0) 939 | { 940 | XRaiseWindow (x_dpy, ids[0]); 941 | if (i > 1) 942 | XRestackWindows (x_dpy, ids, i); 943 | } 944 | } 945 | 946 | - (void) hide_all 947 | { 948 | [self foreach_window:@selector (do_hide)]; 949 | } 950 | 951 | - (void) show_all:(BOOL)flag 952 | { 953 | if (!flag) 954 | [self foreach_window:@selector (do_unhide)]; 955 | else 956 | [self foreach_window:@selector (show)]; 957 | } 958 | 959 | - (void) foreach_window:(SEL)selector 960 | { 961 | x_list *node; 962 | x_window *w; 963 | 964 | for (node = _window_list; node != NULL; node = node->next) 965 | { 966 | w = node->data; 967 | [w performSelector:selector]; 968 | } 969 | } 970 | 971 | - (id) find_window_at:(X11Point)p slop:(int)epsilon 972 | { 973 | int epsilon_squared = epsilon * epsilon; 974 | x_list *node; 975 | x_window *w; 976 | int dx, dy; 977 | 978 | for (node = _window_list; node != NULL; node = node->next) 979 | { 980 | w = node->data; 981 | 982 | dx = p.x - w->_current_frame.x; 983 | dy = p.y - w->_current_frame.y; 984 | 985 | if (dx * dx + dy * dy <= epsilon_squared) 986 | return w; 987 | } 988 | 989 | return nil; 990 | } 991 | 992 | /* OK, This is straight up hell for incompatible coordinate systems. 993 | * 994 | * [NSScreen visibleFrame] and [NSScreen frame] return rects with origins in the 995 | * lower left (y increases upward) of the mainScreen (menu bar). 996 | * 997 | * CG's screen origin is the upper-left (y increases downward) of the mainScreen (menubar) 998 | * 999 | * X11's screen origin is the upper-left of the upper-left-most screen 1000 | * 1001 | * X11Rect's origin point is the upper-left 1002 | * CGRect's origin point is the upper-left 1003 | * NSRect's origin point is the lower-left 1004 | */ 1005 | 1006 | - (X11Point) CGToX11Point:(CGPoint)p { 1007 | X11Point ret; 1008 | ret.x = p.x - _x; 1009 | ret.y = p.y - _y; 1010 | return ret; 1011 | } 1012 | 1013 | - (X11Point) NSToX11Point:(NSPoint)p { 1014 | NSRect fr = [[NSScreen mainScreen] frame]; 1015 | X11Point ret; 1016 | ret.x = p.x - _x; 1017 | ret.y = (fr.size.height - p.y) - _y; 1018 | return ret; 1019 | } 1020 | 1021 | - (X11Rect) CGToX11Rect:(CGRect)r { 1022 | X11Rect ret; 1023 | ret.x = r.origin.x - _x; 1024 | ret.y = r.origin.y - _y; 1025 | ret.width = r.size.width; 1026 | ret.height = r.size.height; 1027 | return ret; 1028 | } 1029 | 1030 | - (X11Rect) NSToX11Rect:(NSRect)r { 1031 | NSRect fr = [[NSScreen mainScreen] frame]; 1032 | X11Rect ret; 1033 | ret.x = r.origin.x - _x; 1034 | ret.y = fr.size.height - (r.size.height + r.origin.y + _y); 1035 | ret.width = r.size.width; 1036 | ret.height = r.size.height; 1037 | return ret; 1038 | } 1039 | 1040 | - (CGPoint) X11ToCGPoint:(X11Point)p { 1041 | return CGPointMake(p.x + _x, p.y + _y); 1042 | } 1043 | 1044 | - (NSPoint) X11ToNSPoint:(X11Point)p { 1045 | NSRect fr = [[NSScreen mainScreen] frame]; 1046 | return NSMakePoint(p.x + _x, 1047 | fr.size.height - p.y - _y); 1048 | } 1049 | 1050 | - (CGRect) X11ToCGRect:(X11Rect)r { 1051 | return CGRectMake(r.x + _x, r.y + _y, r.width, r.height); 1052 | } 1053 | 1054 | - (NSRect) X11ToNSRect:(X11Rect)r { 1055 | NSRect fr = [[NSScreen mainScreen] frame]; 1056 | return NSMakeRect(r.x + _x, 1057 | fr.size.height - (r.height + r.y + _y), 1058 | r.width, 1059 | r.height); 1060 | } 1061 | 1062 | @end 1063 | -------------------------------------------------------------------------------- /src/main.m: -------------------------------------------------------------------------------- 1 | /* main.m 2 | * 3 | * Copyright (c) 2002-2011 Apple Inc. All Rights Reserved. 4 | * 5 | * @APPLE_LICENSE_HEADER_START@ 6 | * 7 | * This file contains Original Code and/or Modifications of Original Code 8 | * as defined in and that are subject to the Apple Public Source License 9 | * Version 2.0 (the 'License'). You may not use this file except in 10 | * compliance with the License. Please obtain a copy of the License at 11 | * http://www.opensource.apple.com/apsl/ and read it before using this 12 | * file. 13 | * 14 | * The Original Code and all software distributed under the License are 15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 | * Please see the License for the specific language governing rights and 20 | * limitations under the License. 21 | * 22 | * @APPLE_LICENSE_HEADER_END@ 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | #include "config.h" 27 | #endif 28 | 29 | #include "quartz-wm.h" 30 | #include "x-list.h" 31 | #include "frame.h" 32 | #import "x-screen.h" 33 | #import "x-window.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | #include 43 | #include 44 | 45 | Display *x_dpy; 46 | unsigned int x_meta_mod; 47 | int x_shape_event_base, x_shape_error_base; 48 | int x_apple_wm_event_base, x_apple_wm_error_base; 49 | int x_xinerama_event_base, x_xinerama_error_base; 50 | 51 | struct atoms_struct_t atoms; 52 | 53 | static int x_grab_count; 54 | static Bool x_grab_synced; 55 | 56 | x_list *screen_list; 57 | 58 | static x_window *_active_window; 59 | static BOOL _is_active = YES; /* FIXME: should query server */ 60 | 61 | static int _window_count; 62 | 63 | BOOL focus_follows_mouse = NO; 64 | BOOL focus_click_through = NO; 65 | BOOL limit_window_size = NO; 66 | BOOL focus_on_new_window = YES; 67 | BOOL window_shading = NO; 68 | BOOL rootless = YES; 69 | BOOL auto_quit = NO; 70 | int auto_quit_timeout = 3; /* Seconds to wait before auto-quiting */ 71 | BOOL minimize_on_double_click = YES; 72 | BOOL show_shortcut = NO; 73 | BOOL enable_key_equivalents = YES; /* quartz-wm doesn't use this per 74 | * se, but it queries it so it knows 75 | * not to display shortcuts when key 76 | * equivalents are disabled. */ 77 | 78 | aslclient aslc; 79 | 80 | XAppleWMSendPSNProcPtr _XAppleWMSendPSN; 81 | XAppleWMAttachTransientProcPtr _XAppleWMAttachTransient; 82 | 83 | /* X11 code */ 84 | _X_NORETURN 85 | static void x_error_shutdown(void); 86 | 87 | static const char *app_prefs_domain = BUNDLE_ID_PREFIX".X11"; 88 | static CFStringRef app_prefs_domain_cfstr = NULL; 89 | 90 | void 91 | x_grab_server (Bool do_sync) 92 | { 93 | if (x_grab_count++ == 0) 94 | { 95 | XGrabServer (x_dpy); 96 | } 97 | 98 | if (do_sync && !x_grab_synced) 99 | { 100 | XSync (x_dpy, False); 101 | x_grab_synced = True; 102 | } 103 | } 104 | 105 | void 106 | x_ungrab_server (void) 107 | { 108 | if (--x_grab_count == 0) 109 | { 110 | XUngrabServer (x_dpy); 111 | XFlush (x_dpy); 112 | x_grab_synced = False; 113 | } 114 | } 115 | 116 | static int 117 | x_init_error_handler (Display *dpy, XErrorEvent *e) 118 | { 119 | asl_log(aslc, NULL, ASL_LEVEL_ERR, "another window manager is running; exiting"); 120 | exit(EXIT_FAILURE); 121 | } 122 | 123 | #ifdef __clang__ 124 | #pragma clang diagnostic push 125 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 126 | #endif 127 | 128 | static int 129 | x_error_handler (Display *dpy, XErrorEvent *e) 130 | { 131 | char bufferA[512]; 132 | char bufferB[512]; 133 | x_window *w; 134 | 135 | XGetErrorText(dpy, e->error_code, bufferB, sizeof(bufferB)); 136 | XGetErrorDatabaseText(dpy, "XlibMessage", "XError", "X Error", bufferA, sizeof(bufferA)); 137 | DB ("%s: %s", bufferA, bufferB); 138 | 139 | XGetErrorDatabaseText(dpy, "XlibMessage", "MajorCode", "Request Major code %d", bufferB, sizeof(bufferB)); 140 | snprintf(bufferA, sizeof(bufferA), bufferB, e->request_code); 141 | 142 | if (e->request_code < 128) { 143 | char number[32]; 144 | sprintf(number, "%d", e->request_code); 145 | XGetErrorDatabaseText(dpy, "XRequest", number, "", bufferB, sizeof(bufferB)); 146 | DB("%s (%s)", bufferA, bufferB); 147 | } else { 148 | DB("%s", bufferA); 149 | 150 | XGetErrorDatabaseText(dpy, "XlibMessage", "MinorCode", "Request Minor code %d", bufferA, sizeof(bufferA)); 151 | DB(bufferA, e->minor_code); 152 | } 153 | 154 | if (e->resourceid == 0) 155 | return 0; 156 | 157 | if (e->error_code == BadWindow || e->error_code == BadDrawable) 158 | { 159 | w = x_get_window (e->resourceid); 160 | 161 | if (w != nil && ! w->_removed) 162 | [w->_screen remove_window:w safe:NO]; 163 | } 164 | 165 | return 0; 166 | } 167 | 168 | #ifdef __clang__ 169 | #pragma clang diagnostic pop 170 | #endif 171 | 172 | void 173 | x_update_meta_modifier (void) 174 | { 175 | int min_code, max_code; 176 | XModifierKeymap *mods; 177 | int syms_per_code, row, col, code_col, sym; 178 | KeySym *syms; 179 | KeyCode code; 180 | 181 | x_meta_mod = 0; 182 | 183 | XDisplayKeycodes (x_dpy, &min_code, &max_code); 184 | 185 | syms = XGetKeyboardMapping (x_dpy, min_code, max_code - min_code + 1, 186 | &syms_per_code); 187 | mods = XGetModifierMapping (x_dpy); 188 | 189 | for (row = 3; row < 8; row++) 190 | { 191 | for (col = 0; col < mods->max_keypermod; col++) 192 | { 193 | code = mods->modifiermap[(row * mods->max_keypermod) + col]; 194 | if(code == 0) 195 | continue; 196 | for (code_col = 0; code_col < syms_per_code; code_col++) 197 | { 198 | sym = syms[((code - min_code) * syms_per_code) + code_col]; 199 | if (sym == XK_Meta_L || sym == XK_Meta_R) 200 | { 201 | x_meta_mod = 1 << row; 202 | goto done; 203 | } 204 | } 205 | } 206 | } 207 | 208 | done: 209 | XFree((char *)syms); 210 | XFreeModifiermap(mods); 211 | } 212 | 213 | void 214 | x_update_keymap (void) 215 | { 216 | x_list *node; 217 | 218 | for (node = screen_list; node != NULL; node = node->next) 219 | { 220 | x_screen *s = node->data; 221 | [s foreach_window:@selector(ungrab_events)]; 222 | } 223 | 224 | x_update_meta_modifier (); 225 | 226 | for (node = screen_list; node != NULL; node = node->next) 227 | { 228 | x_screen *s = node->data; 229 | [s foreach_window:@selector(grab_events)]; 230 | } 231 | } 232 | 233 | static int 234 | x_io_error_handler (Display *dpy) 235 | { 236 | /* We lost our connection to the server. */ 237 | 238 | TRACE (); 239 | 240 | x_error_shutdown (); 241 | 242 | return 0; 243 | } 244 | 245 | static void 246 | x_init (void) 247 | { 248 | int i; 249 | int AppleWMMajorVersion, AppleWMMinorVersion, AppleWMPatchVersion; 250 | x_list *node; 251 | unsigned applewm_mask; 252 | 253 | x_dpy = XOpenDisplay (NULL); 254 | if (x_dpy == NULL) 255 | { 256 | asl_log(aslc, NULL, ASL_LEVEL_ERR, "can't open default display"); 257 | exit(EXIT_FAILURE); 258 | } 259 | 260 | XSetErrorHandler (x_error_handler); 261 | XSetIOErrorHandler (x_io_error_handler); 262 | 263 | atoms.apple_no_order_in = XInternAtom (x_dpy, "_APPLE_NO_ORDER_IN", False); 264 | atoms.atom = XInternAtom (x_dpy, "ATOM", False); 265 | atoms.clipboard = XInternAtom (x_dpy, "CLIPBOARD", False); 266 | atoms.cstring = XInternAtom (x_dpy, "CSTRING", False); 267 | atoms.motif_wm_hints = XInternAtom (x_dpy, "_MOTIF_WM_HINTS", False); 268 | atoms.multiple = XInternAtom (x_dpy, "MULTIPLE", False); 269 | atoms.native_screen_origin = XInternAtom (x_dpy, "_NATIVE_SCREEN_ORIGIN", False); 270 | atoms.native_window_id = XInternAtom (x_dpy, "_NATIVE_WINDOW_ID", False); 271 | atoms.net_active_window = XInternAtom (x_dpy, "_NET_ACTIVE_WINDOW", False); 272 | atoms.net_close_window = XInternAtom (x_dpy, "_NET_CLOSE_WINDOW", False); 273 | atoms.net_wm_action_close = XInternAtom (x_dpy, "_NET_WM_ACTION_CLOSE", False); 274 | atoms.net_wm_action_fullscreen = XInternAtom (x_dpy, "_NET_WM_ACTION_FULLSCREEN", False); 275 | atoms.net_wm_action_maximize_horz = XInternAtom (x_dpy, "_NET_WM_ACTION_MAXIMIZE_HORZ", False); 276 | atoms.net_wm_action_maximize_vert = XInternAtom (x_dpy, "_NET_WM_ACTION_MAXIMIZE_VERT", False); 277 | atoms.net_wm_action_minimize = XInternAtom (x_dpy, "_NET_WM_ACTION_MINIMIZE", False); 278 | atoms.net_wm_action_move = XInternAtom (x_dpy, "_NET_WM_ACTION_MOVE", False); 279 | atoms.net_wm_action_resize = XInternAtom (x_dpy, "_NET_WM_ACTION_RESIZE", False); 280 | atoms.net_wm_action_shade = XInternAtom (x_dpy, "_NET_WM_ACTION_SHADE", False); 281 | atoms.net_wm_allowed_actions = XInternAtom (x_dpy, "_NET_WM_ALLOWED_ACTIONS", False); 282 | atoms.net_wm_name = XInternAtom (x_dpy, "_NET_WM_NAME", False); 283 | atoms.net_wm_state = XInternAtom (x_dpy, "_NET_WM_STATE", False); 284 | atoms.net_wm_state_fullscreen = XInternAtom (x_dpy, "_NET_WM_STATE_FULLSCREEN", False); 285 | atoms.net_wm_state_hidden = XInternAtom (x_dpy, "_NET_WM_STATE_HIDDEN", False); 286 | atoms.net_wm_state_maximized_horz = XInternAtom (x_dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", False); 287 | atoms.net_wm_state_maximized_vert = XInternAtom (x_dpy, "_NET_WM_STATE_MAXIMIZED_VERT", False); 288 | atoms.net_wm_state_modal = XInternAtom (x_dpy, "_NET_WM_STATE_MODAL", False); 289 | atoms.net_wm_state_shaded = XInternAtom (x_dpy, "_NET_WM_STATE_SHADED", False); 290 | atoms.net_wm_state_skip_pager = XInternAtom (x_dpy, "_NET_WM_STATE_SKIP_PAGER", False); 291 | atoms.net_wm_state_skip_taskbar = XInternAtom (x_dpy, "_NET_WM_STATE_SKIP_TASKBAR", False); 292 | atoms.net_wm_state_sticky = XInternAtom (x_dpy, "_NET_WM_STATE_STICKY", False); 293 | atoms.net_wm_window_type = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE", False); 294 | atoms.net_wm_window_type_combo = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_COMBO", False); 295 | atoms.net_wm_window_type_desktop = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False); 296 | atoms.net_wm_window_type_dialog = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); 297 | atoms.net_wm_window_type_dock = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); 298 | atoms.net_wm_window_type_dnd = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_DND", False); 299 | atoms.net_wm_window_type_dropdown_menu = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False); 300 | atoms.net_wm_window_type_menu = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_MENU", False); 301 | atoms.net_wm_window_type_normal = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False); 302 | atoms.net_wm_window_type_notification = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_NOTIFICATION", False); 303 | atoms.net_wm_window_type_popup_menu = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False); 304 | atoms.net_wm_window_type_splash = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False); 305 | atoms.net_wm_window_type_tooltip = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_TOOLTIP", False); 306 | atoms.net_wm_window_type_toolbar = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False); 307 | atoms.net_wm_window_type_utility = XInternAtom (x_dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False); 308 | atoms.primary = XInternAtom (x_dpy, "PRIMARY", False);; 309 | atoms.targets = XInternAtom (x_dpy, "STRING", False); 310 | atoms.targets = XInternAtom (x_dpy, "TARGETS", False); 311 | atoms.text = XInternAtom (x_dpy, "TEXT", False); 312 | atoms.utf8_string = XInternAtom (x_dpy, "UTF8_STRING", False); 313 | atoms.wm_change_state = XInternAtom (x_dpy, "WM_CHANGE_STATE", False); 314 | atoms.wm_colormap_windows = XInternAtom (x_dpy, "WM_COLORMAP_WINDOWS", False); 315 | atoms.wm_delete_window = XInternAtom (x_dpy, "WM_DELETE_WINDOW", False); 316 | atoms.wm_hints = XInternAtom (x_dpy, "WM_HINTS", False); 317 | atoms.wm_name = XInternAtom (x_dpy, "WM_NAME", False); 318 | atoms.wm_normal_hints = XInternAtom (x_dpy, "WM_NORMAL_HINTS", False); 319 | atoms.wm_protocols = XInternAtom (x_dpy, "WM_PROTOCOLS", False); 320 | atoms.wm_state = XInternAtom (x_dpy, "WM_STATE", False); 321 | atoms.wm_take_focus = XInternAtom (x_dpy, "WM_TAKE_FOCUS", False); 322 | atoms.wm_transient_for = XInternAtom (x_dpy, "WM_TRANSIENT_FOR", False); 323 | 324 | if (!XShapeQueryExtension (x_dpy, &x_shape_event_base, 325 | &x_shape_error_base)) 326 | { 327 | asl_log(aslc, NULL, ASL_LEVEL_ERR, "can't open SHAPE server extension"); 328 | exit(EXIT_FAILURE); 329 | } 330 | 331 | if (!XAppleWMQueryExtension (x_dpy, &x_apple_wm_event_base, 332 | &x_apple_wm_error_base)) 333 | { 334 | asl_log(aslc, NULL, ASL_LEVEL_ERR, "can't open AppleWM server extension"); 335 | exit(EXIT_FAILURE); 336 | } 337 | 338 | XineramaQueryExtension (x_dpy, &x_xinerama_event_base, 339 | &x_xinerama_error_base); 340 | 341 | x_update_meta_modifier (); 342 | 343 | XAppleWMQueryVersion(x_dpy, &AppleWMMajorVersion, &AppleWMMinorVersion, &AppleWMPatchVersion); 344 | 345 | /* We do this with dlsym() to help support Codeweavers' wine which may 346 | * override libAppleWM with an older version of the library 347 | */ 348 | _XAppleWMSendPSN = dlsym(RTLD_DEFAULT, "XAppleWMSendPSN"); 349 | _XAppleWMAttachTransient = dlsym(RTLD_DEFAULT, "XAppleWMAttachTransient"); 350 | 351 | /* Let the server know our Canonical PSN */ 352 | if(_XAppleWMSendPSN) 353 | _XAppleWMSendPSN(x_dpy); 354 | 355 | applewm_mask = AppleWMActivationNotifyMask | AppleWMControllerNotifyMask; 356 | 357 | XAppleWMSelectInput (x_dpy, applewm_mask); 358 | XSync (x_dpy, False); 359 | XSetErrorHandler (x_init_error_handler); 360 | 361 | for (i = 0; i < ScreenCount (x_dpy); i++) { 362 | x_screen *s = [[x_screen alloc] init_with_screen_id:i]; 363 | if(s == nil) { 364 | asl_log(aslc, NULL, ASL_LEVEL_ERR, "Memory allocation error"); 365 | exit(EXIT_FAILURE); 366 | } 367 | 368 | screen_list = x_list_prepend (screen_list, s); 369 | } 370 | 371 | XSync (x_dpy, False); 372 | XSetErrorHandler (x_error_handler); 373 | 374 | /* Let X11 quit without dialog box confirmation until we have a window */ 375 | XAppleWMSetCanQuit (x_dpy, True); 376 | 377 | for (node = screen_list; node != NULL; node = node->next) { 378 | x_screen *s = node->data; 379 | [s adopt_windows]; 380 | } 381 | 382 | x_input_register (); 383 | x_input_run (); 384 | } 385 | 386 | _X_NORETURN 387 | static void x_shutdown (void) { 388 | x_list *node; 389 | 390 | for (node = screen_list; node != NULL; node = node->next) { 391 | x_screen *s = node->data; 392 | [s unadopt_windows]; 393 | } 394 | 395 | /* Leave focus in a usable state. */ 396 | XSetInputFocus (x_dpy, PointerRoot, RevertToPointerRoot, CurrentTime); 397 | 398 | /* Reenable can-quit dialog */ 399 | XAppleWMSetCanQuit (x_dpy, False); 400 | 401 | XCloseDisplay (x_dpy); 402 | x_dpy = NULL; 403 | exit(EXIT_SUCCESS); 404 | } 405 | 406 | _X_NORETURN 407 | static void x_error_shutdown (void) { 408 | x_list *node; 409 | 410 | for (node = screen_list; node != NULL; node = node->next) { 411 | x_screen *s = node->data; 412 | [s error_shutdown]; 413 | } 414 | exit(EXIT_FAILURE); 415 | } 416 | 417 | Time 418 | x_current_timestamp (void) 419 | { 420 | /* FIXME: may want to fetch a timestamp from the server.. */ 421 | 422 | return CurrentTime; 423 | } 424 | 425 | 426 | /* Window menu management */ 427 | 428 | static x_list *window_menu; 429 | 430 | static void 431 | x_update_window_menu_focused (void) 432 | { 433 | int n, m; 434 | 435 | n = x_list_length (window_menu); 436 | if (_is_active) 437 | m = x_list_length (x_list_find (window_menu, _active_window)); 438 | else 439 | m = 0; 440 | 441 | if (m > 0) 442 | XAppleWMSetWindowMenuCheck (x_dpy, n - m); 443 | else 444 | XAppleWMSetWindowMenuCheck (x_dpy, -1); 445 | } 446 | 447 | static void 448 | x_update_window_menu (void) 449 | { 450 | int nitems, i; 451 | const char **items = NULL; 452 | char *shortcuts = NULL; 453 | x_list *node; 454 | 455 | nitems = x_list_length (window_menu); 456 | if (nitems > 0) 457 | { 458 | items = alloca (sizeof (char *) * nitems); 459 | shortcuts = alloca (sizeof (char) * nitems); 460 | 461 | for (i = 0, node = window_menu; node != NULL; node = node->next) 462 | { 463 | x_window *w = node->data; 464 | 465 | if (w->_title != nil) 466 | { 467 | items[i] = [w->_title UTF8String]; 468 | shortcuts[i] = w->_shortcut_index; 469 | i++; 470 | } 471 | else 472 | nitems--; 473 | } 474 | } 475 | 476 | XAppleWMSetWindowMenuWithShortcuts (x_dpy, nitems, items, shortcuts); 477 | 478 | x_update_window_menu_focused (); 479 | } 480 | 481 | void 482 | x_update_window_in_menu (id w) 483 | { 484 | if (x_list_find (window_menu, w)) 485 | { 486 | x_update_window_menu (); 487 | } 488 | } 489 | 490 | void 491 | x_add_window_to_menu (id w) 492 | { 493 | if (!x_list_find (window_menu, w)) 494 | { 495 | window_menu = x_list_append (window_menu, [w retain]); 496 | } 497 | 498 | x_update_window_menu (); 499 | } 500 | 501 | void 502 | x_remove_window_from_menu (id w) 503 | { 504 | if (x_list_find (window_menu, w)) 505 | { 506 | window_menu = x_list_remove (window_menu, w); 507 | [w release]; 508 | x_update_window_menu (); 509 | } 510 | } 511 | 512 | void 513 | x_activate_window_in_menu (int n, Time timestamp) 514 | { 515 | x_list *node; 516 | x_window *w; 517 | 518 | node = x_list_nth (window_menu, n); 519 | if (node != nil) 520 | { 521 | w = node->data; 522 | [w activate:timestamp]; 523 | } 524 | } 525 | 526 | 527 | /* Finding things */ 528 | 529 | id 530 | x_get_screen (Screen *xs) 531 | { 532 | x_list *node; 533 | 534 | for (node = screen_list; node != NULL; node = node->next) 535 | { 536 | x_screen *s = node->data; 537 | 538 | if (s->_screen == xs) 539 | return s; 540 | } 541 | 542 | return nil; 543 | } 544 | 545 | id 546 | x_get_screen_with_root (Window xwindow_id) 547 | { 548 | x_list *node; 549 | 550 | for (node = screen_list; node != NULL; node = node->next) 551 | { 552 | x_screen *s = node->data; 553 | 554 | if (s->_root == xwindow_id) 555 | return s; 556 | } 557 | 558 | return nil; 559 | } 560 | 561 | id 562 | x_get_window (Window xwindow_id) 563 | { 564 | x_list *node; 565 | 566 | for (node = screen_list; node != NULL; node = node->next) 567 | { 568 | x_screen *s = node->data; 569 | x_window *w; 570 | 571 | w = [s get_window:xwindow_id]; 572 | if (w != nil) 573 | return w; 574 | } 575 | 576 | return nil; 577 | } 578 | 579 | id 580 | x_get_window_by_osx_id (xp_native_window_id osxwindow_id) 581 | { 582 | x_list *node; 583 | 584 | for (node = screen_list; node != NULL; node = node->next) 585 | { 586 | x_screen *s = node->data; 587 | x_window *w; 588 | 589 | w = [s get_window_by_osx_id:osxwindow_id]; 590 | if (w != nil) 591 | return w; 592 | } 593 | 594 | return nil; 595 | } 596 | 597 | id 598 | x_get_active_window (void) 599 | { 600 | if (_active_window != nil && _active_window->_deleted) 601 | { 602 | [_active_window release]; 603 | _active_window = nil; 604 | } 605 | 606 | return _active_window; 607 | } 608 | 609 | void 610 | x_set_active_window (id w) 611 | { 612 | if (_active_window == w) 613 | return; 614 | 615 | /* When X11 becomes inactive, we unfocus the active window.. but we 616 | want to remember which window was focused for later reactivation */ 617 | 618 | if (!_is_active && w == nil) 619 | return; 620 | 621 | if (_active_window != nil) 622 | { 623 | if (_is_active) 624 | [_active_window set_is_active:NO]; 625 | 626 | [_active_window release]; 627 | _active_window = nil; 628 | } 629 | 630 | if (w != nil) 631 | { 632 | _active_window = [w retain]; 633 | 634 | if (_is_active) 635 | [_active_window set_is_active:YES]; 636 | 637 | x_update_window_menu_focused (); 638 | } 639 | } 640 | 641 | BOOL 642 | x_get_is_active (void) 643 | { 644 | return _is_active; 645 | } 646 | 647 | void 648 | x_set_is_active (BOOL state) 649 | { 650 | x_window *active; 651 | 652 | if (_is_active == state) 653 | return; 654 | 655 | active = x_get_active_window (); 656 | if (active != nil) 657 | { 658 | if (!state) 659 | { 660 | [active set_is_active:state]; 661 | XSetInputFocus (x_dpy, None, RevertToNone, CurrentTime); 662 | } 663 | else 664 | { 665 | /* Don't redraw the window immediately, the activation 666 | may have been caused by clicking on a non-focused 667 | window, in which case we don't want the previously 668 | focused window to be drawn active then inactive. */ 669 | 670 | [NSTimer scheduledTimerWithTimeInterval:0.1 671 | target:active selector:@selector (update_state:) 672 | userInfo:nil repeats:NO]; 673 | } 674 | } 675 | 676 | _is_active = state; 677 | 678 | x_update_window_menu_focused (); 679 | } 680 | 681 | void 682 | x_bring_one_to_front (Time timestamp) 683 | { 684 | x_window *w = x_get_active_window (); 685 | 686 | if (w != nil) 687 | { 688 | [w activate:timestamp]; 689 | } 690 | } 691 | 692 | void 693 | x_bring_all_to_front (Time timestamp) 694 | { 695 | x_list *node; 696 | 697 | for (node = screen_list; node != NULL; node = node->next) 698 | { 699 | x_screen *s = node->data; 700 | 701 | [s raise_all]; 702 | } 703 | } 704 | 705 | void 706 | x_hide_all (Time timestamp) 707 | { 708 | x_list *node; 709 | 710 | for (node = screen_list; node != NULL; node = node->next) 711 | { 712 | x_screen *s = node->data; 713 | 714 | [s hide_all]; 715 | } 716 | } 717 | 718 | void 719 | x_show_all (Time timestamp, BOOL minimized) 720 | { 721 | x_list *node; 722 | 723 | for (node = screen_list; node != NULL; node = node->next) 724 | { 725 | x_screen *s = node->data; 726 | 727 | [s show_all:minimized]; 728 | [s focus_topmost:timestamp]; 729 | } 730 | } 731 | 732 | /* wm_auto_quit support */ 733 | CFRunLoopTimerRef auto_quit_timer = NULL; 734 | 735 | /* Cancel the auto-quit timer */ 736 | static void cancel_auto_quit(void) { 737 | if(auto_quit_timer) { 738 | if(CFRunLoopTimerIsValid(auto_quit_timer)) { 739 | CFRunLoopTimerInvalidate(auto_quit_timer); 740 | } 741 | CFRelease(auto_quit_timer); 742 | auto_quit_timer = NULL; 743 | } 744 | } 745 | 746 | /* Shutdown now */ 747 | static void auto_quit_callback(CFRunLoopTimerRef timer __attribute__((unused)), void *info __attribute__((unused))) { 748 | if(_window_count == 0) { 749 | x_shutdown(); 750 | } else { 751 | cancel_auto_quit(); 752 | } 753 | } 754 | 755 | /* Start the auto-quit timer */ 756 | static void start_auto_quit(void) { 757 | CFAbsoluteTime fireDate; 758 | 759 | /* If we have a negative or zero timeout, just quit now */ 760 | if(auto_quit_timeout <= 0) { 761 | x_shutdown(); 762 | } 763 | 764 | if(auto_quit_timer) { 765 | cancel_auto_quit(); 766 | } 767 | 768 | /* Now */ 769 | fireDate = CFAbsoluteTimeGetCurrent(); 770 | fireDate += (double)auto_quit_timeout; 771 | 772 | auto_quit_timer = CFRunLoopTimerCreate(kCFAllocatorDefault, fireDate, 0, 0, 0, auto_quit_callback, NULL); 773 | 774 | if(auto_quit_timer) { 775 | CFRunLoopAddTimer(CFRunLoopGetCurrent(), auto_quit_timer, kCFRunLoopCommonModes); 776 | } else { 777 | asl_log(aslc, NULL, ASL_LEVEL_WARNING, "couldn't create a shutdown timer, quitting now."); 778 | x_shutdown(); 779 | } 780 | } 781 | 782 | void 783 | x_change_window_count (int delta) 784 | { 785 | BOOL old_state, new_state; 786 | 787 | 788 | old_state = _window_count == 0; 789 | 790 | _window_count += delta; 791 | 792 | new_state = _window_count == 0; 793 | 794 | if (new_state != old_state) { 795 | XAppleWMSetCanQuit (x_dpy, new_state); 796 | 797 | if (auto_quit) { 798 | if(new_state) { 799 | start_auto_quit(); 800 | } else { 801 | cancel_auto_quit(); 802 | } 803 | } 804 | } 805 | } 806 | 807 | #ifdef CHECK_WINDOWS 808 | void 809 | x_check_windows (void) 810 | { 811 | x_list *node; 812 | 813 | for (node = screen_list; node != NULL; node = node->next) 814 | { 815 | x_screen *s = node->data; 816 | 817 | [s check_window_lists]; 818 | } 819 | } 820 | #endif 821 | 822 | 823 | /* Window shortcut management */ 824 | 825 | static unsigned int _shortcut_map; 826 | 827 | int 828 | x_allocate_window_shortcut (void) 829 | { 830 | int i; 831 | 832 | for (i = 1; i < 10; i++) 833 | { 834 | if (!(_shortcut_map & (1 << i))) 835 | { 836 | _shortcut_map |= (1 << i); 837 | return i; 838 | } 839 | } 840 | 841 | return 0; 842 | } 843 | 844 | void 845 | x_release_window_shortcut (int x) 846 | { 847 | _shortcut_map = _shortcut_map & ~(1 << x); 848 | } 849 | 850 | /* Preferences */ 851 | 852 | BOOL prefs_reload = NO; 853 | static BOOL do_shutdown = NO; 854 | 855 | static BOOL prefs_get_bool (CFStringRef key, BOOL def) { 856 | int ret; 857 | Boolean ok; 858 | 859 | ret = CFPreferencesGetAppBooleanValue (key, app_prefs_domain_cfstr, &ok); 860 | 861 | return ok ? (BOOL) ret : def; 862 | } 863 | 864 | static int prefs_get_int (CFStringRef key, BOOL def) { 865 | int ret; 866 | Boolean ok; 867 | 868 | ret = CFPreferencesGetAppIntegerValue (key, app_prefs_domain_cfstr, &ok); 869 | 870 | return ok ? (BOOL) ret : def; 871 | } 872 | 873 | static inline void prefs_read(void) { 874 | CFPreferencesAppSynchronize(app_prefs_domain_cfstr); 875 | focus_follows_mouse = prefs_get_bool (CFSTR (PREFS_FFM), focus_follows_mouse); 876 | focus_on_new_window = prefs_get_bool (CFSTR (PREFS_FOCUS_ON_NEW_WINDOW), focus_on_new_window); 877 | focus_click_through = prefs_get_bool (CFSTR (PREFS_CLICK_THROUGH), focus_click_through); 878 | limit_window_size = prefs_get_bool (CFSTR (PREFS_LIMIT_SIZE), limit_window_size); 879 | window_shading = prefs_get_bool (CFSTR (PREFS_WINDOW_SHADING), window_shading); 880 | rootless = prefs_get_bool (CFSTR (PREFS_ROOTLESS), rootless); 881 | auto_quit = prefs_get_bool (CFSTR (PREFS_AUTO_QUIT), auto_quit); 882 | auto_quit_timeout = prefs_get_int (CFSTR (PREFS_AUTO_QUIT_TIMEOUT), auto_quit_timeout); 883 | minimize_on_double_click = prefs_get_bool (CFSTR(PREFS_MINIMIZE_ON_DOUBLE_CLICK), minimize_on_double_click); 884 | show_shortcut = prefs_get_bool (CFSTR (PREFS_SHOW_SHORTCUT), show_shortcut); 885 | enable_key_equivalents = prefs_get_bool (CFSTR (PREFS_ENABLE_KEY_EQUIVALENTS), enable_key_equivalents); 886 | } 887 | 888 | static void signal_handler_cb(CFRunLoopObserverRef observer, 889 | CFRunLoopActivity activity, void *info) { 890 | 891 | if(do_shutdown) 892 | x_shutdown(); 893 | 894 | if(prefs_reload) { 895 | x_list *s_node, *w_node; 896 | x_window *w; 897 | x_screen *s; 898 | 899 | prefs_reload = NO; 900 | prefs_read(); 901 | 902 | /* We need to update the click_through/shading policy on our windows */ 903 | for (s_node = screen_list; s_node != NULL; s_node = s_node->next) { 904 | s = s_node->data; 905 | for(w_node = s->_window_list; w_node != NULL; w_node = w_node->next) { 906 | w = w_node->data; 907 | if(w->_shadable) { 908 | if(!window_shading) 909 | [w do_unshade:CurrentTime]; 910 | [w update_net_wm_action_property]; 911 | } 912 | 913 | [w decorate]; 914 | } 915 | } 916 | } 917 | } 918 | 919 | static void signal_handler_cb_init(void) { 920 | CFRunLoopObserverContext context = {0}; 921 | CFRunLoopObserverRef ref; 922 | 923 | ref = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, 924 | true, 0, signal_handler_cb, &context); 925 | 926 | CFRunLoopAddObserver(CFRunLoopGetCurrent(), ref, kCFRunLoopDefaultMode); 927 | } 928 | 929 | static void appearance_pref_changed_cb(CFNotificationCenterRef center, void *observer, 930 | CFStringRef name, const void *object, CFDictionaryRef userInfo) 931 | { 932 | prefs_read(); 933 | } 934 | 935 | 936 | /* Startup */ 937 | 938 | static void signal_handler (int sig) { 939 | switch(sig) { 940 | case SIGHUP: 941 | prefs_reload = YES; 942 | break; 943 | default: 944 | do_shutdown = YES; 945 | break; 946 | } 947 | } 948 | 949 | int main (int argc, const char *argv[]) { 950 | NSAutoreleasePool *pool; 951 | int i; 952 | const char *s; 953 | char *asl_facility; 954 | uint32_t asl_opts; 955 | 956 | pool = [[NSAutoreleasePool alloc] init]; 957 | 958 | if((s = getenv("X11_PREFS_DOMAIN"))) 959 | app_prefs_domain = s; 960 | 961 | for (i = 1; i < argc; i++) 962 | { 963 | if (strcmp (argv[i], "--version") == 0) { 964 | printf("%s\n", VERSION); 965 | return 0; 966 | } else if(strcmp (argv[i], "--prefs-domain") == 0 && i+1 < argc) { 967 | app_prefs_domain = argv[++i]; 968 | } else if(strcmp (argv[i], "--display") == 0 && i+1 < argc) { 969 | setenv("DISPLAY", argv[++i], 1); 970 | } else if(strcmp (argv[i], "-display") == 0 && i+1 < argc) { 971 | setenv("DISPLAY", argv[++i], 1); 972 | } else if (strcmp (argv[i], "--synchronous") == 0) { 973 | _Xdebug = 1; 974 | } else if (strcmp (argv[i], "--help") == 0) { 975 | printf("usage: quartz-wm OPTIONS\n" 976 | "Aqua window manager for X11.\n\n" 977 | "--version Print the version string\n" 978 | "--prefs-domain Change the domain used for reading preferences\n" 979 | " (default: %s)\n", app_prefs_domain); 980 | return 0; 981 | } else { 982 | fprintf(stderr, "usage: quartz-wm OPTIONS...\n" 983 | "Try 'quartz-wm --help' for more information.\n"); 984 | return 1; 985 | } 986 | } 987 | 988 | app_prefs_domain_cfstr = CFStringCreateWithCString(NULL, app_prefs_domain, kCFStringEncodingUTF8); 989 | 990 | prefs_read(); 991 | 992 | asl_facility = strdup(app_prefs_domain); 993 | assert(asl_facility); 994 | if(strcmp(asl_facility + strlen(asl_facility) - 4, ".X11") == 0) 995 | asl_facility[strlen(asl_facility) - 4] = '\0'; 996 | 997 | asl_opts = ASL_OPT_NO_DELAY; 998 | if(getenv("DEBUG")) 999 | asl_opts |= ASL_OPT_STDERR; 1000 | 1001 | aslc = asl_open("quartz-wm", asl_facility, asl_opts); 1002 | 1003 | signal_handler_cb_init(); 1004 | CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), 1005 | NULL, appearance_pref_changed_cb, CFSTR("AppleNoRedisplayAppearancePreferenceChanged"), 1006 | NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 1007 | qwm_dock_event_set_handler(dock_event_handler); 1008 | qwm_dock_init(0); 1009 | x_init (); 1010 | 1011 | signal (SIGINT, signal_handler); 1012 | signal (SIGTERM, signal_handler); 1013 | signal (SIGHUP, signal_handler); 1014 | signal (SIGPIPE, SIG_IGN); 1015 | 1016 | while (1) { 1017 | NS_DURING 1018 | CFRunLoopRun (); 1019 | NS_HANDLER 1020 | NSString *str = [NSString stringWithFormat:@"%@ - %@", 1021 | [localException name], [localException reason]]; 1022 | asl_log(aslc, NULL, ASL_LEVEL_ERR, "caught exception: %s", [str UTF8String]); 1023 | NS_ENDHANDLER 1024 | } 1025 | 1026 | return 0; 1027 | } 1028 | 1029 | // for atom in $(grep XInternAtom main.m | grep \" | cut -f2 -d\" | sort -u); do printf " if(atom == atoms.$(echo ${atom} | sed 's/^_//' | tr [:upper:] [:lower:]))\n return \"${atom}\";\n"; done 1030 | const char *str_for_atom(Atom atom) { 1031 | if(atom == atoms.atom) 1032 | return "ATOM"; 1033 | if(atom == atoms.clipboard) 1034 | return "CLIPBOARD"; 1035 | if(atom == atoms.cstring) 1036 | return "CSTRING"; 1037 | if(atom == atoms.multiple) 1038 | return "MULTIPLE"; 1039 | if(atom == atoms.primary) 1040 | return "PRIMARY"; 1041 | if(atom == atoms.string) 1042 | return "STRING"; 1043 | if(atom == atoms.targets) 1044 | return "TARGETS"; 1045 | if(atom == atoms.text) 1046 | return "TEXT"; 1047 | if(atom == atoms.utf8_string) 1048 | return "UTF8_STRING"; 1049 | if(atom == atoms.wm_change_state) 1050 | return "WM_CHANGE_STATE"; 1051 | if(atom == atoms.wm_colormap_windows) 1052 | return "WM_COLORMAP_WINDOWS"; 1053 | if(atom == atoms.wm_delete_window) 1054 | return "WM_DELETE_WINDOW"; 1055 | if(atom == atoms.wm_hints) 1056 | return "WM_HINTS"; 1057 | if(atom == atoms.wm_name) 1058 | return "WM_NAME"; 1059 | if(atom == atoms.wm_normal_hints) 1060 | return "WM_NORMAL_HINTS"; 1061 | if(atom == atoms.wm_protocols) 1062 | return "WM_PROTOCOLS"; 1063 | if(atom == atoms.wm_state) 1064 | return "WM_STATE"; 1065 | if(atom == atoms.wm_take_focus) 1066 | return "WM_TAKE_FOCUS"; 1067 | if(atom == atoms.wm_transient_for) 1068 | return "WM_TRANSIENT_FOR"; 1069 | if(atom == atoms.apple_no_order_in) 1070 | return "_APPLE_NO_ORDER_IN"; 1071 | if(atom == atoms.motif_wm_hints) 1072 | return "_MOTIF_WM_HINTS"; 1073 | if(atom == atoms.native_screen_origin) 1074 | return "_NATIVE_SCREEN_ORIGIN"; 1075 | if(atom == atoms.native_window_id) 1076 | return "_NATIVE_WINDOW_ID"; 1077 | if(atom == atoms.net_active_window) 1078 | return "_NET_ACTIVE_WINDOW"; 1079 | if(atom == atoms.net_close_window) 1080 | return "_NET_CLOSE_WINDOW"; 1081 | if(atom == atoms.net_wm_action_close) 1082 | return "_NET_WM_ACTION_CLOSE"; 1083 | if(atom == atoms.net_wm_action_fullscreen) 1084 | return "_NET_WM_ACTION_FULLSCREEN"; 1085 | if(atom == atoms.net_wm_action_maximize_horz) 1086 | return "_NET_WM_ACTION_MAXIMIZE_HORZ"; 1087 | if(atom == atoms.net_wm_action_maximize_vert) 1088 | return "_NET_WM_ACTION_MAXIMIZE_VERT"; 1089 | if(atom == atoms.net_wm_action_minimize) 1090 | return "_NET_WM_ACTION_MINIMIZE"; 1091 | if(atom == atoms.net_wm_action_move) 1092 | return "_NET_WM_ACTION_MOVE"; 1093 | if(atom == atoms.net_wm_action_resize) 1094 | return "_NET_WM_ACTION_RESIZE"; 1095 | if(atom == atoms.net_wm_action_shade) 1096 | return "_NET_WM_ACTION_SHADE"; 1097 | if(atom == atoms.net_wm_allowed_actions) 1098 | return "_NET_WM_ALLOWED_ACTIONS"; 1099 | if(atom == atoms.net_wm_name) 1100 | return "_NET_WM_NAME"; 1101 | if(atom == atoms.net_wm_state) 1102 | return "_NET_WM_STATE"; 1103 | if(atom == atoms.net_wm_state_fullscreen) 1104 | return "_NET_WM_STATE_FULLSCREEN"; 1105 | if(atom == atoms.net_wm_state_hidden) 1106 | return "_NET_WM_STATE_HIDDEN"; 1107 | if(atom == atoms.net_wm_state_maximized_horz) 1108 | return "_NET_WM_STATE_MAXIMIZED_HORZ"; 1109 | if(atom == atoms.net_wm_state_maximized_vert) 1110 | return "_NET_WM_STATE_MAXIMIZED_VERT"; 1111 | if(atom == atoms.net_wm_state_modal) 1112 | return "_NET_WM_STATE_MODAL"; 1113 | if(atom == atoms.net_wm_state_shaded) 1114 | return "_NET_WM_STATE_SHADED"; 1115 | if(atom == atoms.net_wm_state_skip_pager) 1116 | return "_NET_WM_STATE_SKIP_PAGER"; 1117 | if(atom == atoms.net_wm_state_skip_taskbar) 1118 | return "_NET_WM_STATE_SKIP_TASKBAR"; 1119 | if(atom == atoms.net_wm_state_sticky) 1120 | return "_NET_WM_STATE_STICKY"; 1121 | if(atom == atoms.net_wm_window_type) 1122 | return "_NET_WM_WINDOW_TYPE"; 1123 | if(atom == atoms.net_wm_window_type_combo) 1124 | return "_NET_WM_WINDOW_TYPE_COMBO"; 1125 | if(atom == atoms.net_wm_window_type_desktop) 1126 | return "_NET_WM_WINDOW_TYPE_DESKTOP"; 1127 | if(atom == atoms.net_wm_window_type_dialog) 1128 | return "_NET_WM_WINDOW_TYPE_DIALOG"; 1129 | if(atom == atoms.net_wm_window_type_dnd) 1130 | return "_NET_WM_WINDOW_TYPE_DND"; 1131 | if(atom == atoms.net_wm_window_type_dock) 1132 | return "_NET_WM_WINDOW_TYPE_DOCK"; 1133 | if(atom == atoms.net_wm_window_type_dropdown_menu) 1134 | return "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"; 1135 | if(atom == atoms.net_wm_window_type_menu) 1136 | return "_NET_WM_WINDOW_TYPE_MENU"; 1137 | if(atom == atoms.net_wm_window_type_normal) 1138 | return "_NET_WM_WINDOW_TYPE_NORMAL"; 1139 | if(atom == atoms.net_wm_window_type_notification) 1140 | return "_NET_WM_WINDOW_TYPE_NOTIFICATION"; 1141 | if(atom == atoms.net_wm_window_type_popup_menu) 1142 | return "_NET_WM_WINDOW_TYPE_POPUP_MENU"; 1143 | if(atom == atoms.net_wm_window_type_splash) 1144 | return "_NET_WM_WINDOW_TYPE_SPLASH"; 1145 | if(atom == atoms.net_wm_window_type_toolbar) 1146 | return "_NET_WM_WINDOW_TYPE_TOOLBAR"; 1147 | if(atom == atoms.net_wm_window_type_tooltip) 1148 | return "_NET_WM_WINDOW_TYPE_TOOLTIP"; 1149 | if(atom == atoms.net_wm_window_type_utility) 1150 | return "_NET_WM_WINDOW_TYPE_UTILITY"; 1151 | return "(unknown atom)"; 1152 | } 1153 | 1154 | void debug_asl (const char *file, const char *function, int line, const char *fmt, ...) { 1155 | va_list args; 1156 | aslmsg msg = asl_new(ASL_TYPE_MSG); 1157 | 1158 | if(msg) { 1159 | char *_line; 1160 | 1161 | asl_set(msg, "File", file); 1162 | asl_set(msg, "Function", function); 1163 | asprintf(&_line, "%d", line); 1164 | if(_line) { 1165 | asl_set(msg, "Line", _line); 1166 | free(_line); 1167 | } 1168 | } 1169 | 1170 | va_start(args, fmt); 1171 | asl_vlog(aslc, msg, ASL_LEVEL_DEBUG, fmt, args); 1172 | va_end(args); 1173 | 1174 | if(msg) 1175 | asl_free(msg); 1176 | } 1177 | 1178 | /* debug_printf is kept around for compatibility with older dock-support.o */ 1179 | void 1180 | debug_printf (const char *fmt, ...) 1181 | { 1182 | va_list args; 1183 | va_start(args, fmt); 1184 | asl_vlog(aslc, NULL, ASL_LEVEL_DEBUG, fmt, args); 1185 | va_end(args); 1186 | } 1187 | --------------------------------------------------------------------------------