diff options
author | Thomas James Alexander Thurman <tthurman@src.gnome.org> | 2009-01-22 05:14:00 +0000 |
---|---|---|
committer | Thomas James Alexander Thurman <tthurman@src.gnome.org> | 2009-01-22 05:14:00 +0000 |
commit | 3945cdefdaad26979226be0940a7758fad41874e (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src | |
parent | 1b35154e2baec3f0a6854a2f5538444bcebac1d0 (diff) | |
download | metacity-git-migration-mbus.tar.gz |
Fix typogit-migration-mbus
svn path=/tags/git-migration-mbus; revision=4083
Diffstat (limited to 'src')
248 files changed, 0 insertions, 84503 deletions
diff --git a/src/.cvsignore b/src/.cvsignore deleted file mode 100644 index f62415b3..00000000 --- a/src/.cvsignore +++ /dev/null @@ -1,15 +0,0 @@ -.libs -Makefile.in -Makefile -.deps -metacity -metacity-theme-viewer -metacity-dialog -testboxes -testgradient -inlinepixbufs.h -metacity.desktop -metacity-wm.desktop -metacity.schemas -libmetacity-private.pc -testasyncgetprop diff --git a/src/50-metacity-desktop-key.xml.in b/src/50-metacity-desktop-key.xml.in deleted file mode 100644 index dbd5d75a..00000000 --- a/src/50-metacity-desktop-key.xml.in +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<KeyListEntries _name="Desktop" wm_name="Metacity" package="metacity"> - - <KeyListEntry - name="/apps/metacity/global_keybindings/panel_run_dialog" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/panel_main_menu" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/run_command_screenshot" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/run_command_window_screenshot" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/run_command_terminal" /> - -</KeyListEntries> - diff --git a/src/50-metacity-key.xml.in b/src/50-metacity-key.xml.in deleted file mode 100644 index d6113a29..00000000 --- a/src/50-metacity-key.xml.in +++ /dev/null @@ -1,269 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<KeyListEntries _name="Window Management" wm_name="Metacity" package="metacity"> - - <KeyListEntry - name="/apps/metacity/window_keybindings/activate_window_menu" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/toggle_fullscreen" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/toggle_maximized" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/maximize" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/unmaximize" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/toggle_shaded" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/close" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/minimize" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/begin_move" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/begin_resize" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/toggle_on_all_workspaces" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/raise_or_lower" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/raise" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/lower" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/maximize_vertically" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/maximize_horizontally" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_1" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_2" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_3" - value="2" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_4" - value="3" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_5" - value="4" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_6" - value="5" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_7" - value="6" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_8" - value="7" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_9" - value="8" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_10" - value="9" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_11" - value="10" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_12" - value="11" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_left" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_right" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_up" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/window_keybindings/move_to_workspace_down" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_windows" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_group" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_panels" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/cycle_windows" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/cycle_group" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/cycle_panels" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/show_desktop" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_1" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_2" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_3" - value="2" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_4" - value="3" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_5" - value="4" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_6" - value="5" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_7" - value="6" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_8" - value="7" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_9" - value="8" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_10" - value="9" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_11" - value="10" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_12" - value="11" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_left" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_right" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_up" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - - <KeyListEntry - name="/apps/metacity/global_keybindings/switch_to_workspace_down" - value="1" - key="/apps/metacity/general/num_workspaces" - comparison="gt" /> - -</KeyListEntries> - diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 4c9e39cc..00000000 --- a/src/Makefile.am +++ /dev/null @@ -1,221 +0,0 @@ -lib_LTLIBRARIES = libmetacity-private.la - -SUBDIRS=wm-tester tools themes - -INCLUDES=-I$(srcdir)/include -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMETACITY_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMETACITY_PKGDATADIR=\"$(pkgdatadir)\" -DMETACITY_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"metacity\" -DSN_API_NOT_YET_FROZEN=1 @METACITY_CFLAGS@ - -metacity_SOURCES= \ - core/async-getprop.c \ - core/async-getprop.h \ - core/atomnames.h \ - core/bell.c \ - core/bell.h \ - core/boxes.c \ - include/boxes.h \ - compositor/compositor.c \ - compositor/compositor-private.h \ - compositor/compositor-xrender.c \ - compositor/compositor-xrender.h \ - include/compositor.h \ - core/constraints.c \ - core/constraints.h \ - core/core.c \ - core/delete.c \ - core/display.c \ - core/display-private.h \ - include/display.h \ - ui/draw-workspace.c \ - ui/draw-workspace.h \ - core/edge-resistance.c \ - core/edge-resistance.h \ - core/effects.c \ - core/effects.h \ - core/errors.c \ - include/errors.h \ - core/eventqueue.c \ - core/eventqueue.h \ - core/frame.c \ - core/frame-private.h \ - include/frame.h \ - ui/gradient.c \ - ui/gradient.h \ - core/group-private.h \ - core/group-props.c \ - core/group-props.h \ - core/group.c \ - core/group.h \ - core/iconcache.c \ - core/iconcache.h \ - core/keybindings.c \ - core/keybindings.h \ - core/main.c \ - include/main.h \ - core/metacity-Xatomtype.h \ - core/place.c \ - core/place.h \ - core/prefs.c \ - include/prefs.h \ - core/screen.c \ - core/screen-private.h \ - include/screen.h \ - include/types.h \ - core/session.c \ - core/session.h \ - core/stack.c \ - core/stack.h \ - core/util.c \ - include/util.h \ - core/window-props.c \ - core/window-props.h \ - core/window.c \ - core/window-private.h \ - include/window.h \ - core/workspace.c \ - core/workspace.h \ - core/xprops.c \ - include/xprops.h \ - include/common.h \ - include/core.h \ - include/ui.h \ - inlinepixbufs.h \ - ui/fixedtip.c \ - ui/fixedtip.h \ - ui/frames.c \ - ui/frames.h \ - ui/menu.c \ - ui/menu.h \ - ui/metaaccellabel.c \ - ui/metaaccellabel.h \ - ui/resizepopup.c \ - include/resizepopup.h \ - ui/tabpopup.c \ - include/tabpopup.h \ - ui/theme-parser.c \ - ui/theme-parser.h \ - ui/theme.c \ - ui/theme.h \ - ui/themewidget.c \ - ui/themewidget.h \ - ui/ui.c \ - include/all-keybindings.h - -# by setting libmetacity_private_la_CFLAGS, the files shared with -# metacity proper will be compiled with different names. -libmetacity_private_la_CFLAGS = -libmetacity_private_la_SOURCES= \ - core/boxes.c \ - include/boxes.h \ - ui/gradient.c \ - ui/gradient.h \ - core/util.c \ - include/util.h \ - include/common.h \ - ui/preview-widget.c \ - ui/preview-widget.h \ - ui/theme-parser.c \ - ui/theme-parser.h \ - ui/theme.c \ - ui/theme.h - -libmetacity_private_la_LDFLAGS = -no-undefined -libmetacity_private_la_LIBADD = @METACITY_LIBS@ - -libmetacityincludedir = $(includedir)/metacity-1/metacity-private - -libmetacityinclude_HEADERS = \ - include/boxes.h \ - ui/gradient.h \ - include/util.h \ - include/common.h \ - ui/preview-widget.h \ - ui/theme-parser.h \ - ui/theme.h - -metacity_theme_viewer_SOURCES= \ - ui/theme-viewer.c - -metacity_dialog_SOURCES= \ - ui/metacity-dialog.c - -schema_bindings_SOURCES = \ - core/schema-bindings.c \ - metacity.schemas.in.in - -schema_bindings_LDADD = @METACITY_LIBS@ -metacity.schemas.in: schema_bindings ${srcdir}/metacity.schemas.in.in - @echo Generating keybinding schemas... ${srcdir}/metacity.schemas.in.in - ${builddir}/schema_bindings ${srcdir}/metacity.schemas.in.in ${builddir}/metacity.schemas.in - -bin_PROGRAMS=metacity metacity-theme-viewer -libexec_PROGRAMS=metacity-dialog - -EFENCE= -metacity_LDADD=@METACITY_LIBS@ $(EFENCE) -metacity_theme_viewer_LDADD= @METACITY_LIBS@ libmetacity-private.la -metacity_dialog_LDADD=@METACITY_LIBS@ - -testboxes_SOURCES=include/util.h core/util.c include/boxes.h core/boxes.c core/testboxes.c -testgradient_SOURCES=ui/gradient.h ui/gradient.c ui/testgradient.c -testasyncgetprop_SOURCES=core/async-getprop.h core/async-getprop.c core/testasyncgetprop.c - -noinst_PROGRAMS=testboxes testgradient testasyncgetprop schema_bindings - -testboxes_LDADD= @METACITY_LIBS@ -testgradient_LDADD= @METACITY_LIBS@ -testasyncgetprop_LDADD= @METACITY_LIBS@ - -@INTLTOOL_DESKTOP_RULE@ - -desktopfilesdir=$(datadir)/applications -desktopfiles_in_files=metacity.desktop.in -desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop) -desktopfiles_DATA = $(desktopfiles_files) - -wmpropertiesdir=$(datadir)/gnome/wm-properties -wmproperties_in_files=metacity-wm.desktop.in -wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop) -wmproperties_DATA = $(wmproperties_files) - -schemadir = @GCONF_SCHEMA_FILE_DIR@ -schema_in_files = metacity.schemas.in -schema_DATA = $(schema_in_files:.schemas.in=.schemas) - -@INTLTOOL_XML_NOMERGE_RULE@ - -xmldir = @GNOME_KEYBINDINGS_KEYSDIR@ -xml_in_files = 50-metacity-desktop-key.xml.in 50-metacity-key.xml.in -xml_DATA = $(xml_in_files:.xml.in=.xml) - -@INTLTOOL_SCHEMAS_RULE@ - -if GCONF_SCHEMAS_INSTALL -install-data-local: - GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA) -else -install-data-local: -endif - -IMAGES=stock_maximize.png stock_minimize.png stock_delete.png -VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \ - stock_minimize_data $(srcdir)/stock_minimize.png \ - stock_delete_data $(srcdir)/stock_delete.png - -BUILT_SOURCES = inlinepixbufs.h -CLEANFILES = inlinepixbufs.h metacity.desktop metacity-wm.desktop metacity.schemas metacity.schemas.in 50-metacity-desktop-key.xml 50-metacity-key.xml - -inlinepixbufs.h: $(IMAGES) - $(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h - -pkgconfigdir = $(libdir)/pkgconfig - -pkgconfig_DATA = libmetacity-private.pc - -EXTRA_DIST=$(desktopfiles_files) \ - $(wmproperties_files) \ - $(IMAGES) $(schema_DATA) \ - $(desktopfiles_in_files) \ - $(wmproperties_in_files) \ - $(schema_in_files) \ - $(xml_in_files) \ - libmetacity-private.pc.in - diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h deleted file mode 100644 index ef9f8023..00000000 --- a/src/compositor/compositor-private.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_COMPOSITOR_PRIVATE_H -#define META_COMPOSITOR_PRIVATE_H - -#include "compositor.h" - -struct _MetaCompositor -{ - void (* destroy) (MetaCompositor *compositor); - - void (*manage_screen) (MetaCompositor *compositor, - MetaScreen *screen); - void (*unmanage_screen) (MetaCompositor *compositor, - MetaScreen *screen); - void (*add_window) (MetaCompositor *compositor, - MetaWindow *window, - Window xwindow, - XWindowAttributes *attrs); - void (*remove_window) (MetaCompositor *compositor, - Window xwindow); - void (*set_updates) (MetaCompositor *compositor, - MetaWindow *window, - gboolean update); - void (*process_event) (MetaCompositor *compositor, - XEvent *event, - MetaWindow *window); - Pixmap (*get_window_pixmap) (MetaCompositor *compositor, - MetaWindow *window); - void (*set_active_window) (MetaCompositor *compositor, - MetaScreen *screen, - MetaWindow *window); -}; - -#endif diff --git a/src/compositor/compositor-xrender.c b/src/compositor/compositor-xrender.c deleted file mode 100644 index 8c06d1f7..00000000 --- a/src/compositor/compositor-xrender.c +++ /dev/null @@ -1,3078 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2007 Iain Holmes - * Based on xcompmgr - (c) 2003 Keith Packard - * xfwm4 - (c) 2005-2007 Olivier Fourdan - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#define _GNU_SOURCE -#define _XOPEN_SOURCE 500 /* for usleep() */ - -#include <config.h> - -#ifdef HAVE_COMPOSITE_EXTENSIONS - -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include <unistd.h> - -#include <gdk/gdk.h> - -#include "display.h" -#include "screen.h" -#include "frame.h" -#include "errors.h" -#include "window.h" -#include "compositor-private.h" -#include "compositor-xrender.h" -#include "xprops.h" -#include <X11/Xatom.h> -#include <X11/extensions/shape.h> -#include <X11/extensions/Xcomposite.h> -#include <X11/extensions/Xdamage.h> -#include <X11/extensions/Xfixes.h> -#include <X11/extensions/Xrender.h> - -#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 -#define HAVE_NAME_WINDOW_PIXMAP 1 -#endif - -#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 3 -#define HAVE_COW 1 -#else -/* Don't have a cow man...HAAHAAHAA */ -#endif - -#define USE_IDLE_REPAINT 1 - -#ifdef HAVE_COMPOSITE_EXTENSIONS -static inline gboolean -composite_at_least_version (MetaDisplay *display, - int maj, int min) -{ - static int major = -1; - static int minor = -1; - - if (major == -1) - meta_display_get_compositor_version (display, &major, &minor); - - return (major > maj || (major == maj && minor >= min)); -} - -#define have_name_window_pixmap(display) \ - composite_at_least_version (display, 0, 2) -#define have_cow(display) \ - composite_at_least_version (display, 0, 3) - -#endif - -typedef enum _MetaCompWindowType -{ - META_COMP_WINDOW_NORMAL, - META_COMP_WINDOW_DND, - META_COMP_WINDOW_DESKTOP, - META_COMP_WINDOW_DOCK, - META_COMP_WINDOW_MENU, - META_COMP_WINDOW_DROP_DOWN_MENU, - META_COMP_WINDOW_TOOLTIP, -} MetaCompWindowType; - -typedef enum _MetaShadowType -{ - META_SHADOW_SMALL, - META_SHADOW_MEDIUM, - META_SHADOW_LARGE, - LAST_SHADOW_TYPE -} MetaShadowType; - -typedef struct _MetaCompositorXRender -{ - MetaCompositor compositor; - - MetaDisplay *display; - - Atom atom_x_root_pixmap; - Atom atom_x_set_root; - Atom atom_net_wm_window_opacity; - Atom atom_net_wm_window_type_dnd; - - Atom atom_net_wm_window_type; - Atom atom_net_wm_window_type_desktop; - Atom atom_net_wm_window_type_dock; - Atom atom_net_wm_window_type_menu; - Atom atom_net_wm_window_type_dialog; - Atom atom_net_wm_window_type_normal; - Atom atom_net_wm_window_type_utility; - Atom atom_net_wm_window_type_splash; - Atom atom_net_wm_window_type_toolbar; - Atom atom_net_wm_window_type_dropdown_menu; - Atom atom_net_wm_window_type_tooltip; - -#ifdef USE_IDLE_REPAINT - guint repaint_id; -#endif - guint enabled : 1; - guint show_redraw : 1; - guint debug : 1; -} MetaCompositorXRender; - -typedef struct _conv -{ - int size; - double *data; -} conv; - -typedef struct _shadow -{ - conv *gaussian_map; - guchar *shadow_corner; - guchar *shadow_top; -} shadow; - -typedef struct _MetaCompScreen -{ - MetaScreen *screen; - GList *windows; - GHashTable *windows_by_xid; - - MetaWindow *focus_window; - - Window output; - - gboolean have_shadows; - shadow *shadows[LAST_SHADOW_TYPE]; - - Picture root_picture; - Picture root_buffer; - Picture black_picture; - Picture trans_black_picture; - Picture root_tile; - XserverRegion all_damage; - - guint overlays; - gboolean compositor_active; - gboolean clip_changed; - - GSList *dock_windows; -} MetaCompScreen; - -typedef struct _MetaCompWindow -{ - MetaScreen *screen; - MetaWindow *window; /* May be NULL if this window isn't managed by Metacity */ - Window id; - XWindowAttributes attrs; - -#ifdef HAVE_NAME_WINDOW_PIXMAP - Pixmap back_pixmap; - - /* When the window is shaded back_pixmap will be replaced with the pixmap - for the shaded window. This is a copy of the original unshaded window - so that we can still see what the window looked like when it is needed - for the _get_window_pixmap function */ - Pixmap shaded_back_pixmap; -#endif - - int mode; - - gboolean damaged; - gboolean shaped; - - MetaCompWindowType type; - - Damage damage; - Picture picture; - Picture alpha_pict; - - gboolean needs_shadow; - MetaShadowType shadow_type; - Picture shadow_pict; - - XserverRegion border_size; - XserverRegion extents; - - Picture shadow; - int shadow_dx; - int shadow_dy; - int shadow_width; - int shadow_height; - - guint opacity; - - XserverRegion border_clip; - - gboolean updates_frozen; - gboolean update_pending; -} MetaCompWindow; - -#define OPAQUE 0xffffffff - -#define WINDOW_SOLID 0 -#define WINDOW_ARGB 1 - -#define SHADOW_SMALL_RADIUS 3.0 -#define SHADOW_MEDIUM_RADIUS 6.0 -#define SHADOW_LARGE_RADIUS 12.0 - -#define SHADOW_SMALL_OFFSET_X (SHADOW_SMALL_RADIUS * -3 / 2) -#define SHADOW_SMALL_OFFSET_Y (SHADOW_SMALL_RADIUS * -3 / 2) -#define SHADOW_MEDIUM_OFFSET_X (SHADOW_MEDIUM_RADIUS * -3 / 2) -#define SHADOW_MEDIUM_OFFSET_Y (SHADOW_MEDIUM_RADIUS * -5 / 4) -#define SHADOW_LARGE_OFFSET_X -15 -#define SHADOW_LARGE_OFFSET_Y -15 - -#define SHADOW_OPACITY 0.66 - -#define TRANS_OPACITY 0.75 - -#define DISPLAY_COMPOSITOR(display) ((MetaCompositorXRender *) meta_display_get_compositor (display)) - -/* Gaussian stuff for creating the shadows */ -static double -gaussian (double r, - double x, - double y) -{ - return ((1 / (sqrt (2 * G_PI * r))) * - exp ((- (x * x + y * y)) / (2 * r * r))); -} - -static conv * -make_gaussian_map (double r) -{ - conv *c; - int size, centre; - int x, y; - double t, g; - - size = ((int) ceil ((r * 3)) + 1) & ~1; - centre = size / 2; - c = g_malloc (sizeof (conv) + size * size * sizeof (double)); - c->size = size; - c->data = (double *) (c + 1); - t = 0.0; - - for (y = 0; y < size; y++) - { - for (x = 0; x < size; x++) - { - g = gaussian (r, (double) (x - centre), (double) (y - centre)); - t += g; - c->data[y * size + x] = g; - } - } - - for (y = 0; y < size; y++) - { - for (x = 0; x < size; x++) - { - c->data[y * size + x] /= t; - } - } - - return c; -} - -static void -dump_xserver_region (const char *location, - MetaDisplay *display, - XserverRegion region) -{ - MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display); - Display *xdisplay = meta_display_get_xdisplay (display); - int nrects; - XRectangle *rects; - XRectangle bounds; - - if (!compositor->debug) - return; - - if (region) - { - rects = XFixesFetchRegionAndBounds (xdisplay, region, &nrects, &bounds); - if (nrects > 0) - { - int i; - fprintf (stderr, "%s (XSR): %d rects, bounds: %d,%d (%d,%d)\n", - location, nrects, bounds.x, bounds.y, bounds.width, bounds.height); - for (i = 1; i < nrects; i++) - fprintf (stderr, "\t%d,%d (%d,%d)\n", - rects[i].x, rects[i].y, rects[i].width, rects[i].height); - } - else - fprintf (stderr, "%s (XSR): empty\n", location); - XFree (rects); - } - else - fprintf (stderr, "%s (XSR): null\n", location); -} - -/* -* A picture will help -* -* -center 0 width width+center -* -center +-----+-------------------+-----+ -* | | | | -* | | | | -* 0 +-----+-------------------+-----+ -* | | | | -* | | | | -* | | | | -* height +-----+-------------------+-----+ -* | | | | -* height+ | | | | -* center +-----+-------------------+-----+ -*/ -static guchar -sum_gaussian (conv *map, - double opacity, - int x, - int y, - int width, - int height) -{ - double *g_data, *g_line; - double v; - int fx, fy; - int fx_start, fx_end; - int fy_start, fy_end; - int g_size, centre; - - g_line = map->data; - g_size = map->size; - centre = g_size / 2; - fx_start = centre - x; - if (fx_start < 0) - fx_start = 0; - - fx_end = width + centre - x; - if (fx_end > g_size) - fx_end = g_size; - - fy_start = centre - y; - if (fy_start < 0) - fy_start = 0; - - fy_end = height + centre - y; - if (fy_end > g_size) - fy_end = g_size; - - g_line = g_line + fy_start * g_size + fx_start; - - v = 0.0; - for (fy = fy_start; fy < fy_end; fy++) - { - g_data = g_line; - g_line += g_size; - - for (fx = fx_start; fx < fx_end; fx++) - v += *g_data++; - } - - if (v > 1.0) - v = 1.0; - - return ((guchar) (v * opacity * 255.0)); -} - -/* precompute shadow corners and sides to save time for large windows */ -static void -presum_gaussian (shadow *shad) -{ - int centre; - int opacity, x, y; - int msize; - conv *map; - - map = shad->gaussian_map; - msize = map->size; - centre = map->size / 2; - - if (shad->shadow_corner) - g_free (shad->shadow_corner); - if (shad->shadow_top) - g_free (shad->shadow_top); - - shad->shadow_corner = (guchar *)(g_malloc ((msize + 1) * (msize + 1) * 26)); - shad->shadow_top = (guchar *) (g_malloc ((msize + 1) * 26)); - - for (x = 0; x <= msize; x++) - { - - shad->shadow_top[25 * (msize + 1) + x] = - sum_gaussian (map, 1, x - centre, centre, msize * 2, msize * 2); - for (opacity = 0; opacity < 25; opacity++) - { - shad->shadow_top[opacity * (msize + 1) + x] = - shad->shadow_top[25 * (msize + 1) + x] * opacity / 25; - } - - for (y = 0; y <= x; y++) - { - shad->shadow_corner[25 * (msize + 1) * (msize + 1) - + y * (msize + 1) - + x] - = sum_gaussian (map, 1, x - centre, y - centre, - msize * 2, msize * 2); - - shad->shadow_corner[25 * (msize + 1) * (msize + 1) - + x * (msize + 1) + y] = - shad->shadow_corner[25 * (msize + 1) * (msize + 1) - + y * (msize + 1) + x]; - - for (opacity = 0; opacity < 25; opacity++) - { - shad->shadow_corner[opacity * (msize + 1) * (msize + 1) - + y * (msize + 1) + x] - = shad->shadow_corner[opacity * (msize + 1) * (msize + 1) - + x * (msize + 1) + y] - = shad->shadow_corner[25 * (msize + 1) * (msize + 1) - + y * (msize + 1) + x] * opacity / 25; - } - } - } -} - -static void -generate_shadows (MetaCompScreen *info) -{ - double radii[LAST_SHADOW_TYPE] = {SHADOW_SMALL_RADIUS, - SHADOW_MEDIUM_RADIUS, - SHADOW_LARGE_RADIUS}; - int i; - - for (i = 0; i < LAST_SHADOW_TYPE; i++) { - shadow *shad = g_new0 (shadow, 1); - - shad->gaussian_map = make_gaussian_map (radii[i]); - presum_gaussian (shad); - - info->shadows[i] = shad; - } -} - -static XImage * -make_shadow (MetaDisplay *display, - MetaScreen *screen, - MetaShadowType shadow_type, - double opacity, - int width, - int height) -{ - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XImage *ximage; - guchar *data; - shadow *shad; - int msize; - int ylimit, xlimit; - int swidth, sheight; - int centre; - int x, y; - guchar d; - int x_diff; - int opacity_int = (int)(opacity * 25); - int screen_number = meta_screen_get_screen_number (screen); - - if (info==NULL) - { - return NULL; - } - - shad = info->shadows[shadow_type]; - msize = shad->gaussian_map->size; - swidth = width + msize; - sheight = height + msize; - centre = msize / 2; - - data = g_malloc (swidth * sheight * sizeof (guchar)); - - ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, screen_number), - 8, ZPixmap, 0, (char *) data, - swidth, sheight, 8, swidth * sizeof (guchar)); - if (!ximage) - { - g_free (data); - return NULL; - } - - /* - * Build the gaussian in sections - */ - - /* - * centre (fill the complete data array - */ - if (msize > 0) - d = shad->shadow_top[opacity_int * (msize + 1) + msize]; - else - d = sum_gaussian (shad->gaussian_map, opacity, centre, - centre, width, height); - memset (data, d, sheight * swidth); - - /* - * corners - */ - ylimit = msize; - if (ylimit > sheight / 2) - ylimit = (sheight + 1) / 2; - - xlimit = msize; - if (xlimit > swidth / 2) - xlimit = (swidth + 1) / 2; - - for (y = 0; y < ylimit; y++) - { - for (x = 0; x < xlimit; x++) - { - - if (xlimit == msize && ylimit == msize) - d = shad->shadow_corner[opacity_int * (msize + 1) * (msize + 1) + y * (msize + 1) + x]; - else - d = sum_gaussian (shad->gaussian_map, opacity, x - centre, - y - centre, width, height); - - data[y * swidth + x] = d; - data[(sheight - y - 1) * swidth + x] = d; - data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d; - data[y * swidth + (swidth - x - 1)] = d; - } - } - - /* top/bottom */ - x_diff = swidth - (msize * 2); - if (x_diff > 0 && ylimit > 0) - { - for (y = 0; y < ylimit; y++) - { - if (ylimit == msize) - d = shad->shadow_top[opacity_int * (msize + 1) + y]; - else - d = sum_gaussian (shad->gaussian_map, opacity, centre, - y - centre, width, height); - - memset (&data[y * swidth + msize], d, x_diff); - memset (&data[(sheight - y - 1) * swidth + msize], d, x_diff); - } - } - - /* - * sides - */ - for (x = 0; x < xlimit; x++) - { - if (xlimit == msize) - d = shad->shadow_top[opacity_int * (msize + 1) + x]; - else - d = sum_gaussian (shad->gaussian_map, opacity, x - centre, - centre, width, height); - - for (y = msize; y < sheight - msize; y++) - { - data[y * swidth + x] = d; - data[y * swidth + (swidth - x - 1)] = d; - } - } - - return ximage; -} - -static Picture -shadow_picture (MetaDisplay *display, - MetaScreen *screen, - MetaShadowType shadow_type, - double opacity, - Picture alpha_pict, - int width, - int height, - int *wp, - int *hp) -{ - Display *xdisplay = meta_display_get_xdisplay (display); - XImage *shadow_image; - Pixmap shadow_pixmap; - Picture shadow_picture; - Window xroot = meta_screen_get_xroot (screen); - GC gc; - - shadow_image = make_shadow (display, screen, shadow_type, - opacity, width, height); - if (!shadow_image) - return None; - - shadow_pixmap = XCreatePixmap (xdisplay, xroot, - shadow_image->width, shadow_image->height, 8); - if (!shadow_pixmap) - { - XDestroyImage (shadow_image); - return None; - } - - shadow_picture = XRenderCreatePicture (xdisplay, shadow_pixmap, - XRenderFindStandardFormat (xdisplay, -PictStandardA8), - 0, 0); - if (!shadow_picture) - { - XDestroyImage (shadow_image); - XFreePixmap (xdisplay, shadow_pixmap); - return None; - } - - gc = XCreateGC (xdisplay, shadow_pixmap, 0, 0); - if (!gc) - { - XDestroyImage (shadow_image); - XFreePixmap (xdisplay, shadow_pixmap); - XRenderFreePicture (xdisplay, shadow_picture); - return None; - } - - XPutImage (xdisplay, shadow_pixmap, gc, shadow_image, 0, 0, 0, 0, - shadow_image->width, shadow_image->height); - *wp = shadow_image->width; - *hp = shadow_image->height; - - XFreeGC (xdisplay, gc); - XDestroyImage (shadow_image); - XFreePixmap (xdisplay, shadow_pixmap); - - return shadow_picture; -} - -static MetaCompWindow * -find_window_for_screen (MetaScreen *screen, - Window xwindow) -{ - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - - if (info == NULL) - return NULL; - - return g_hash_table_lookup (info->windows_by_xid, (gpointer) xwindow); -} - -static MetaCompWindow * -find_window_in_display (MetaDisplay *display, - Window xwindow) -{ - GSList *index; - - for (index = meta_display_get_screens (display); index; index = index->next) - { - MetaCompWindow *cw = find_window_for_screen (index->data, xwindow); - - if (cw != NULL) - return cw; - } - - return NULL; -} - -static MetaCompWindow * -find_window_for_child_window_in_display (MetaDisplay *display, - Window xwindow) -{ - Window ignored1, *ignored2; - Window parent; - guint ignored_children; - - XQueryTree (meta_display_get_xdisplay (display), xwindow, &ignored1, - &parent, &ignored2, &ignored_children); - - if (parent != None) - return find_window_in_display (display, parent); - - return NULL; -} - -static Picture -solid_picture (MetaDisplay *display, - MetaScreen *screen, - gboolean argb, - double a, - double r, - double g, - double b) -{ - Display *xdisplay = meta_display_get_xdisplay (display); - Pixmap pixmap; - Picture picture; - XRenderPictureAttributes pa; - XRenderPictFormat *render_format; - XRenderColor c; - Window xroot = meta_screen_get_xroot (screen); - - render_format = XRenderFindStandardFormat (xdisplay, - argb ? PictStandardARGB32 : PictStandardA8); - - pixmap = XCreatePixmap (xdisplay, xroot, 1, 1, argb ? 32 : 8); - g_return_val_if_fail (pixmap != None, None); - - pa.repeat = TRUE; - picture = XRenderCreatePicture (xdisplay, pixmap, render_format, - CPRepeat, &pa); - if (picture == None) - { - XFreePixmap (xdisplay, pixmap); - g_warning ("(picture != None) failed"); - return None; - } - - c.alpha = a * 0xffff; - c.red = r * 0xffff; - c.green = g * 0xffff; - c.blue = b * 0xffff; - - XRenderFillRectangle (xdisplay, PictOpSrc, picture, &c, 0, 0, 1, 1); - XFreePixmap (xdisplay, pixmap); - - return picture; -} - -static Picture -root_tile (MetaScreen *screen) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - Picture picture; - Pixmap pixmap; - gboolean fill = FALSE; - XRenderPictureAttributes pa; - XRenderPictFormat *format; - int p; - Atom background_atoms[2]; - Atom pixmap_atom; - int screen_number = meta_screen_get_screen_number (screen); - Window xroot = meta_screen_get_xroot (screen); - - pixmap = None; - background_atoms[0] = DISPLAY_COMPOSITOR (display)->atom_x_root_pixmap; - background_atoms[1] = DISPLAY_COMPOSITOR (display)->atom_x_set_root; - - pixmap_atom = XInternAtom (xdisplay, "PIXMAP", False); - for (p = 0; p < 2; p++) - { - Atom actual_type; - int actual_format; - gulong nitems, bytes_after; - guchar *prop; - - if (XGetWindowProperty (xdisplay, xroot, - background_atoms[p], - 0, 4, FALSE, AnyPropertyType, - &actual_type, &actual_format, - &nitems, &bytes_after, &prop) == Success) - { - if (actual_type == pixmap_atom && - actual_format == 32 && - nitems == 1) - { - memcpy (&pixmap, prop, 4); - XFree (prop); - fill = FALSE; - break; - } - } - } - - if (!pixmap) - { - pixmap = XCreatePixmap (xdisplay, xroot, 1, 1, - DefaultDepth (xdisplay, screen_number)); - g_return_val_if_fail (pixmap != None, None); - fill = TRUE; - } - - pa.repeat = TRUE; - format = XRenderFindVisualFormat (xdisplay, DefaultVisual (xdisplay, - screen_number)); - g_return_val_if_fail (format != NULL, None); - - picture = XRenderCreatePicture (xdisplay, pixmap, format, CPRepeat, &pa); - if ((picture != None) && (fill)) - { - XRenderColor c; - - /* Background default to just plain ugly grey */ - c.red = 0x8080; - c.green = 0x8080; - c.blue = 0x8080; - c.alpha = 0xffff; - - XRenderFillRectangle (xdisplay, PictOpSrc, picture, &c, 0, 0, 1, 1); - XFreePixmap (xdisplay, pixmap); - } - - return picture; -} - -static Picture -create_root_buffer (MetaScreen *screen) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - Picture pict; - XRenderPictFormat *format; - Pixmap root_pixmap; - Visual *visual; - int depth, screen_width, screen_height, screen_number; - - if (info == NULL) - { - return None; - } - - meta_screen_get_size (screen, &screen_width, &screen_height); - screen_number = meta_screen_get_screen_number (screen); - visual = DefaultVisual (xdisplay, screen_number); - depth = DefaultDepth (xdisplay, screen_number); - - format = XRenderFindVisualFormat (xdisplay, visual); - g_return_val_if_fail (format != NULL, None); - - root_pixmap = XCreatePixmap (xdisplay, info->output, - screen_width, screen_height, depth); - g_return_val_if_fail (root_pixmap != None, None); - - pict = XRenderCreatePicture (xdisplay, root_pixmap, format, 0, NULL); - XFreePixmap (xdisplay, root_pixmap); - - return pict; -} - -static void -paint_root (MetaScreen *screen, - Picture root_buffer) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - int width, height; - - if (info == NULL) - { - return; - } - - g_return_if_fail (root_buffer != None); - - if (info->root_tile == None) - { - info->root_tile = root_tile (screen); - g_return_if_fail (info->root_tile != None); - } - - meta_screen_get_size (screen, &width, &height); - XRenderComposite (xdisplay, PictOpSrc, info->root_tile, None, root_buffer, - 0, 0, 0, 0, 0, 0, width, height); -} - -static gboolean -window_has_shadow (MetaCompWindow *cw) -{ - MetaCompScreen *info = meta_screen_get_compositor_data (cw->screen); - - if (info == NULL || info->have_shadows == FALSE) - return FALSE; - - /* Always put a shadow around windows with a frame - This should override - the restriction about not putting a shadow around shaped windows - as the frame might be the reason the window is shaped */ - if (cw->window) - { - if (meta_window_get_frame (cw->window)) { - meta_verbose ("Window has shadow because it has a frame\n"); - return TRUE; - } - } - - /* Never put a shadow around shaped windows */ - if (cw->shaped) { - meta_verbose ("Window has no shadow as it is shaped\n"); - return FALSE; - } - - /* Don't put shadow around DND icon windows */ - if (cw->type == META_COMP_WINDOW_DND || - cw->type == META_COMP_WINDOW_DESKTOP) { - meta_verbose ("Window has no shadow as it is DND or Desktop\n"); - return FALSE; - } - - if (cw->mode != WINDOW_ARGB) { - meta_verbose ("Window has shadow as it is not ARGB\n"); - return TRUE; - } - - if (cw->type == META_COMP_WINDOW_MENU || - cw->type == META_COMP_WINDOW_DROP_DOWN_MENU) { - meta_verbose ("Window has shadow as it is a menu\n"); - return TRUE; - } - - if (cw->type == META_COMP_WINDOW_TOOLTIP) { - meta_verbose ("Window has shadow as it is a tooltip\n"); - return TRUE; - } - - meta_verbose ("Window has no shadow as it fell through\n"); - return FALSE; -} - -double shadow_offsets_x[LAST_SHADOW_TYPE] = {SHADOW_SMALL_OFFSET_X, - SHADOW_MEDIUM_OFFSET_X, - SHADOW_LARGE_OFFSET_X}; -double shadow_offsets_y[LAST_SHADOW_TYPE] = {SHADOW_SMALL_OFFSET_Y, - SHADOW_MEDIUM_OFFSET_Y, - SHADOW_LARGE_OFFSET_Y}; -static XserverRegion -win_extents (MetaCompWindow *cw) -{ - MetaScreen *screen = cw->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XRectangle r; - - r.x = cw->attrs.x; - r.y = cw->attrs.y; - r.width = cw->attrs.width + cw->attrs.border_width * 2; - r.height = cw->attrs.height + cw->attrs.border_width * 2; - - if (cw->needs_shadow) - { - XRectangle sr; - - cw->shadow_dx = shadow_offsets_x [cw->shadow_type]; - cw->shadow_dy = shadow_offsets_y [cw->shadow_type]; - - if (!cw->shadow) - { - double opacity = SHADOW_OPACITY; - if (cw->opacity != (guint) OPAQUE) - opacity = opacity * ((double) cw->opacity) / ((double) OPAQUE); - - cw->shadow = shadow_picture (display, screen, cw->shadow_type, - opacity, cw->alpha_pict, - cw->attrs.width + cw->attrs.border_width * 2, - cw->attrs.height + cw->attrs.border_width * 2, - &cw->shadow_width, &cw->shadow_height); - } - - sr.x = cw->attrs.x + cw->shadow_dx; - sr.y = cw->attrs.y + cw->shadow_dy; - sr.width = cw->shadow_width; - sr.height = cw->shadow_height; - - if (sr.x < r.x) - { - r.width = (r.x + r.width) - sr.x; - r.x = sr.x; - } - - if (sr.y < r.y) - { - r.height = (r.y + r.height) - sr.y; - r.y = sr.y; - } - - if (sr.x + sr.width > r.x + r.width) - r.width = sr.x + sr.width - r.x; - - if (sr.y + sr.height > r.y + r.height) - r.height = sr.y + sr.height - r.y; - } - - return XFixesCreateRegion (xdisplay, &r, 1); -} - -static XserverRegion -border_size (MetaCompWindow *cw) -{ - MetaScreen *screen = cw->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XserverRegion border; - - meta_error_trap_push (display); - border = XFixesCreateRegionFromWindow (xdisplay, cw->id, - WindowRegionBounding); - meta_error_trap_pop (display, FALSE); - - g_return_val_if_fail (border != None, None); - XFixesTranslateRegion (xdisplay, border, - cw->attrs.x + cw->attrs.border_width, - cw->attrs.y + cw->attrs.border_width); - return border; -} - -static XRenderPictFormat * -get_window_format (MetaCompWindow *cw) -{ - MetaScreen *screen = cw->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XRenderPictFormat *format; - int screen_number = meta_screen_get_screen_number (screen); - - format = XRenderFindVisualFormat (xdisplay, cw->attrs.visual); - if (!format) - format = XRenderFindVisualFormat (xdisplay, - DefaultVisual (xdisplay, screen_number)); - return format; -} - -static Picture -get_window_picture (MetaCompWindow *cw) -{ - MetaScreen *screen = cw->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XRenderPictureAttributes pa; - XRenderPictFormat *format; - Drawable draw; - - draw = cw->id; - - meta_error_trap_push (display); - -#ifdef HAVE_NAME_WINDOW_PIXMAP - if (have_name_window_pixmap (display)) - { - if (cw->back_pixmap == None) - cw->back_pixmap = XCompositeNameWindowPixmap (xdisplay, cw->id); - - if (cw->back_pixmap != None) - draw = cw->back_pixmap; - } -#endif - - format = get_window_format (cw); - if (format) - { - Picture pict; - - pa.subwindow_mode = IncludeInferiors; - - pict = XRenderCreatePicture (xdisplay, draw, format, CPSubwindowMode, &pa); - meta_error_trap_pop (display, FALSE); - - return pict; - } - - meta_error_trap_pop (display, FALSE); - return None; -} - -static void -paint_dock_shadows (MetaScreen *screen, - Picture root_buffer, - XserverRegion region) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - GSList *d; - - if (info == NULL) - { - return; - } - - for (d = info->dock_windows; d; d = d->next) - { - MetaCompWindow *cw = d->data; - XserverRegion shadow_clip; - - if (cw->shadow) - { - shadow_clip = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesIntersectRegion (xdisplay, shadow_clip, - cw->border_clip, region); - - XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, shadow_clip); - - XRenderComposite (xdisplay, PictOpOver, info->black_picture, - cw->shadow, root_buffer, - 0, 0, 0, 0, - cw->attrs.x + cw->shadow_dx, - cw->attrs.y + cw->shadow_dy, - cw->shadow_width, cw->shadow_height); - XFixesDestroyRegion (xdisplay, shadow_clip); - } - } -} - -static void -paint_windows (MetaScreen *screen, - GList *windows, - Picture root_buffer, - XserverRegion region) -{ - MetaDisplay *display = meta_screen_get_display (screen); - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - GList *index, *last; - int screen_width, screen_height, screen_number; - Window xroot; - MetaCompWindow *cw; - XserverRegion paint_region, desktop_region; - - if (info == NULL) - { - return; - } - - meta_screen_get_size (screen, &screen_width, &screen_height); - screen_number = meta_screen_get_screen_number (screen); - xroot = meta_screen_get_xroot (screen); - - if (region == None) - { - XRectangle r; - r.x = 0; - r.y = 0; - r.width = screen_width; - r.height = screen_height; - paint_region = XFixesCreateRegion (xdisplay, &r, 1); - } - else - { - paint_region = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesCopyRegion (xdisplay, paint_region, region); - } - - desktop_region = None; - - /* - * Painting from top to bottom, reducing the clipping area at - * each iteration. Only the opaque windows are painted 1st. - */ - last = NULL; - for (index = windows; index; index = index->next) - { - /* Store the last window we dealt with */ - last = index; - - cw = (MetaCompWindow *) index->data; - if (!cw->damaged) - { - /* Not damaged */ - continue; - } - -#if 0 - if ((cw->attrs.x + cw->attrs.width < 1) || - (cw->attrs.y + cw->attrs.height < 1) || - (cw->attrs.x >= screen_width) || (cw->attrs.y >= screen_height)) - { - /* Off screen */ - continue; - } -#endif - - if (cw->picture == None) - cw->picture = get_window_picture (cw); - - /* If the clip region of the screen has been changed - then we need to recreate the extents of the window */ - if (info->clip_changed) - { - if (cw->border_size) - { - XFixesDestroyRegion (xdisplay, cw->border_size); - cw->border_size = None; - } - -#if 0 - if (cw->extents) - { - XFixesDestroyRegion (xdisplay, cw->extents); - cw->extents = None; - } -#endif - } - - if (cw->border_size == None) - cw->border_size = border_size (cw); - - if (cw->extents == None) - cw->extents = win_extents (cw); - - if (cw->mode == WINDOW_SOLID) - { - int x, y, wid, hei; - -#ifdef HAVE_NAME_WINDOW_PIXMAP - if (have_name_window_pixmap (display)) - { - x = cw->attrs.x; - y = cw->attrs.y; - wid = cw->attrs.width + cw->attrs.border_width * 2; - hei = cw->attrs.height + cw->attrs.border_width * 2; - } - else -#endif - { - x = cw->attrs.x + cw->attrs.border_width; - y = cw->attrs.y + cw->attrs.border_width; - wid = cw->attrs.width; - hei = cw->attrs.height; - } - - XFixesSetPictureClipRegion (xdisplay, root_buffer, - 0, 0, paint_region); - XRenderComposite (xdisplay, PictOpSrc, cw->picture, - None, root_buffer, 0, 0, 0, 0, - x, y, wid, hei); - - if (cw->type == META_COMP_WINDOW_DESKTOP) - { - desktop_region = XFixesCreateRegion (xdisplay, 0, 0); - XFixesCopyRegion (xdisplay, desktop_region, paint_region); - } - - XFixesSubtractRegion (xdisplay, paint_region, - paint_region, cw->border_size); - } - - if (!cw->border_clip) - { - cw->border_clip = XFixesCreateRegion (xdisplay, 0, 0); - XFixesCopyRegion (xdisplay, cw->border_clip, paint_region); - } - } - - XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, paint_region); - paint_root (screen, root_buffer); - - paint_dock_shadows (screen, root_buffer, desktop_region == None ? - paint_region : desktop_region); - if (desktop_region != None) - XFixesDestroyRegion (xdisplay, desktop_region); - - /* - * Painting from bottom to top, translucent windows and shadows are painted - */ - for (index = last; index; index = index->prev) - { - cw = (MetaCompWindow *) index->data; - - if (cw->picture) - { - if (cw->shadow && cw->type != META_COMP_WINDOW_DOCK) - { - XserverRegion shadow_clip; - - shadow_clip = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesSubtractRegion (xdisplay, shadow_clip, cw->border_clip, - cw->border_size); - XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, - shadow_clip); - - XRenderComposite (xdisplay, PictOpOver, info->black_picture, - cw->shadow, root_buffer, - 0, 0, 0, 0, - cw->attrs.x + cw->shadow_dx, - cw->attrs.y + cw->shadow_dy, - cw->shadow_width, cw->shadow_height); - if (shadow_clip) - XFixesDestroyRegion (xdisplay, shadow_clip); - } - - if ((cw->opacity != (guint) OPAQUE) && !(cw->alpha_pict)) - { - cw->alpha_pict = solid_picture (display, screen, FALSE, - (double) cw->opacity / OPAQUE, - 0, 0, 0); - } - - XFixesIntersectRegion (xdisplay, cw->border_clip, cw->border_clip, - cw->border_size); - XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, - cw->border_clip); - if (cw->mode == WINDOW_ARGB) - { - int x, y, wid, hei; -#ifdef HAVE_NAME_WINDOW_PIXMAP - if (have_name_window_pixmap (display)) - { - x = cw->attrs.x; - y = cw->attrs.y; - wid = cw->attrs.width + cw->attrs.border_width * 2; - hei = cw->attrs.height + cw->attrs.border_width * 2; - } - else -#endif - { - x = cw->attrs.x + cw->attrs.border_width; - y = cw->attrs.y + cw->attrs.border_width; - wid = cw->attrs.width; - hei = cw->attrs.height; - } - - XRenderComposite (xdisplay, PictOpOver, cw->picture, - cw->alpha_pict, root_buffer, 0, 0, 0, 0, - x, y, wid, hei); - } - } - - if (cw->border_clip) - { - XFixesDestroyRegion (xdisplay, cw->border_clip); - cw->border_clip = None; - } - } - - XFixesDestroyRegion (xdisplay, paint_region); -} - -static void -paint_all (MetaScreen *screen, - XserverRegion region) -{ - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - int screen_width, screen_height; - - /* Set clipping to the given region */ - XFixesSetPictureClipRegion (xdisplay, info->root_picture, 0, 0, region); - - meta_screen_get_size (screen, &screen_width, &screen_height); - - if (DISPLAY_COMPOSITOR (display)->show_redraw) - { - Picture overlay; - - dump_xserver_region ("paint_all", display, region); - - /* Make a random colour overlay */ - overlay = solid_picture (display, screen, TRUE, 1, /* 0.3, alpha */ - ((double) (rand () % 100)) / 100.0, - ((double) (rand () % 100)) / 100.0, - ((double) (rand () % 100)) / 100.0); - - XRenderComposite (xdisplay, PictOpOver, overlay, None, info->root_picture, - 0, 0, 0, 0, 0, 0, screen_width, screen_height); - XRenderFreePicture (xdisplay, overlay); - XFlush (xdisplay); - usleep (100 * 1000); - } - - if (info->root_buffer == None) - info->root_buffer = create_root_buffer (screen); - - paint_windows (screen, info->windows, info->root_buffer, region); - - XFixesSetPictureClipRegion (xdisplay, info->root_buffer, 0, 0, region); - XRenderComposite (xdisplay, PictOpSrc, info->root_buffer, None, - info->root_picture, 0, 0, 0, 0, 0, 0, - screen_width, screen_height); -} - -static void -repair_screen (MetaScreen *screen) -{ - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - - if (info!=NULL && info->all_damage != None) - { - meta_error_trap_push (display); - paint_all (screen, info->all_damage); - XFixesDestroyRegion (xdisplay, info->all_damage); - info->all_damage = None; - info->clip_changed = FALSE; - meta_error_trap_pop (display, FALSE); - } -} - -static void -repair_display (MetaDisplay *display) -{ - GSList *screens = meta_display_get_screens (display); - MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display); - -#ifdef USE_IDLE_REPAINT - if (compositor->repaint_id > 0) - { - g_source_remove (compositor->repaint_id); - compositor->repaint_id = 0; - } -#endif - - for (; screens; screens = screens->next) - repair_screen ((MetaScreen *) screens->data); -} - -#ifdef USE_IDLE_REPAINT -static gboolean -compositor_idle_cb (gpointer data) -{ - MetaCompositorXRender *compositor = (MetaCompositorXRender *) data; - - compositor->repaint_id = 0; - repair_display (compositor->display); - - return FALSE; -} - -static void -add_repair (MetaDisplay *display) -{ - MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display); - - if (compositor->repaint_id > 0) - return; - -#if 1 - compositor->repaint_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE, - compositor_idle_cb, compositor, - NULL); -#else - /* Limit it to 50fps */ - compositor->repaint_id = g_timeout_add_full (G_PRIORITY_HIGH, 20, - compositor_idle_cb, compositor, - NULL); -#endif -} -#endif - -static void -add_damage (MetaScreen *screen, - XserverRegion damage) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - - /* dump_xserver_region ("add_damage", display, damage); */ - - if (info != NULL && info->all_damage) - { - XFixesUnionRegion (xdisplay, info->all_damage, info->all_damage, damage); - XFixesDestroyRegion (xdisplay, damage); - } - else - info->all_damage = damage; - -#ifdef USE_IDLE_REPAINT - add_repair (display); -#endif -} - -static void -damage_screen (MetaScreen *screen) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XserverRegion region; - int width, height; - XRectangle r; - - r.x = 0; - r.y = 0; - meta_screen_get_size (screen, &width, &height); - r.width = width; - r.height = height; - - region = XFixesCreateRegion (xdisplay, &r, 1); - dump_xserver_region ("damage_screen", display, region); - add_damage (screen, region); -} - -static void -repair_win (MetaCompWindow *cw) -{ - MetaScreen *screen = cw->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XserverRegion parts; - - meta_error_trap_push (display); - if (!cw->damaged) - { - parts = win_extents (cw); - XDamageSubtract (xdisplay, cw->damage, None, None); - } - else - { - parts = XFixesCreateRegion (xdisplay, 0, 0); - XDamageSubtract (xdisplay, cw->damage, None, parts); - XFixesTranslateRegion (xdisplay, parts, - cw->attrs.x + cw->attrs.border_width, - cw->attrs.y + cw->attrs.border_width); - } - - meta_error_trap_pop (display, FALSE); - - dump_xserver_region ("repair_win", display, parts); - add_damage (screen, parts); - cw->damaged = TRUE; -} - -static void -free_win (MetaCompWindow *cw, - gboolean destroy) -{ - MetaDisplay *display = meta_screen_get_display (cw->screen); - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompScreen *info = meta_screen_get_compositor_data (cw->screen); - -#ifdef HAVE_NAME_WINDOW_PIXMAP - if (have_name_window_pixmap (display)) - { - /* See comment in map_win */ - if (cw->back_pixmap && destroy) - { - XFreePixmap (xdisplay, cw->back_pixmap); - cw->back_pixmap = None; - } - - if (cw->shaded_back_pixmap && destroy) - { - XFreePixmap (xdisplay, cw->shaded_back_pixmap); - cw->shaded_back_pixmap = None; - } - } -#endif - - if (cw->picture) - { - XRenderFreePicture (xdisplay, cw->picture); - cw->picture = None; - } - - if (cw->shadow) - { - XRenderFreePicture (xdisplay, cw->shadow); - cw->shadow = None; - } - - if (cw->alpha_pict) - { - XRenderFreePicture (xdisplay, cw->alpha_pict); - cw->alpha_pict = None; - } - - if (cw->shadow_pict) - { - XRenderFreePicture (xdisplay, cw->shadow_pict); - cw->shadow_pict = None; - } - - if (cw->border_size) - { - XFixesDestroyRegion (xdisplay, cw->border_size); - cw->border_size = None; - } - - if (cw->border_clip) - { - XFixesDestroyRegion (xdisplay, cw->border_clip); - cw->border_clip = None; - } - - if (cw->extents) - { - XFixesDestroyRegion (xdisplay, cw->extents); - cw->extents = None; - } - - if (destroy) - { - if (cw->damage != None) { - meta_error_trap_push (display); - XDamageDestroy (xdisplay, cw->damage); - meta_error_trap_pop (display, FALSE); - - cw->damage = None; - } - - /* The window may not have been added to the list in this case, - but we can check anyway */ - if (info!=NULL && cw->type == META_COMP_WINDOW_DOCK) - info->dock_windows = g_slist_remove (info->dock_windows, cw); - - g_free (cw); - } -} - -static void -map_win (MetaDisplay *display, - MetaScreen *screen, - Window id) -{ - MetaCompWindow *cw = find_window_for_screen (screen, id); - Display *xdisplay = meta_display_get_xdisplay (display); - - if (cw == NULL) - return; - -#ifdef HAVE_NAME_WINDOW_PIXMAP - /* The reason we deallocate this here and not in unmap - is so that we will still have a valid pixmap for - whenever the window is unmapped */ - if (cw->back_pixmap) - { - XFreePixmap (xdisplay, cw->back_pixmap); - cw->back_pixmap = None; - } - - if (cw->shaded_back_pixmap) - { - XFreePixmap (xdisplay, cw->shaded_back_pixmap); - cw->shaded_back_pixmap = None; - } -#endif - - cw->attrs.map_state = IsViewable; - cw->damaged = FALSE; -} - -static void -unmap_win (MetaDisplay *display, - MetaScreen *screen, - Window id) -{ - MetaCompWindow *cw = find_window_for_screen (screen, id); - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - - if (cw == NULL || info == NULL) - { - return; - } - - if (cw->window && cw->window == info->focus_window) - info->focus_window = NULL; - - cw->attrs.map_state = IsUnmapped; - cw->damaged = FALSE; - - if (cw->extents != None) - { - dump_xserver_region ("unmap_win", display, cw->extents); - add_damage (screen, cw->extents); - cw->extents = None; - } - - free_win (cw, FALSE); - info->clip_changed = TRUE; -} - -static void -determine_mode (MetaDisplay *display, - MetaScreen *screen, - MetaCompWindow *cw) -{ - XRenderPictFormat *format; - Display *xdisplay = meta_display_get_xdisplay (display); - - if (cw->alpha_pict) - { - XRenderFreePicture (xdisplay, cw->alpha_pict); - cw->alpha_pict = None; - } - - if (cw->shadow_pict) - { - XRenderFreePicture (xdisplay, cw->shadow_pict); - cw->shadow_pict = None; - } - - if (cw->attrs.class == InputOnly) - format = NULL; - else - format = XRenderFindVisualFormat (xdisplay, cw->attrs.visual); - - if ((format && format->type == PictTypeDirect && format->direct.alphaMask) - || cw->opacity != (guint) OPAQUE) - cw->mode = WINDOW_ARGB; - else - cw->mode = WINDOW_SOLID; - - if (cw->extents) - { - XserverRegion damage; - damage = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesCopyRegion (xdisplay, damage, cw->extents); - - dump_xserver_region ("determine_mode", display, damage); - add_damage (screen, damage); - } -} - -static gboolean -is_shaped (MetaDisplay *display, - Window xwindow) -{ - Display *xdisplay = meta_display_get_xdisplay (display); - int xws, yws, xbs, ybs; - unsigned wws, hws, wbs, hbs; - int bounding_shaped, clip_shaped; - - if (meta_display_has_shape (display)) - { - XShapeQueryExtents (xdisplay, xwindow, &bounding_shaped, - &xws, &yws, &wws, &hws, &clip_shaped, - &xbs, &ybs, &wbs, &hbs); - return (bounding_shaped != 0); - } - - return FALSE; -} - -static void -get_window_type (MetaDisplay *display, - MetaCompWindow *cw) -{ - MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display); - int n_atoms; - Atom *atoms, type_atom; - int i; - - type_atom = None; - n_atoms = 0; - atoms = NULL; - - meta_prop_get_atom_list (display, cw->id, - compositor->atom_net_wm_window_type, - &atoms, &n_atoms); - - for (i = 0; i < n_atoms; i++) - { - if (atoms[i] == compositor->atom_net_wm_window_type_dnd || - atoms[i] == compositor->atom_net_wm_window_type_desktop || - atoms[i] == compositor->atom_net_wm_window_type_dock || - atoms[i] == compositor->atom_net_wm_window_type_toolbar || - atoms[i] == compositor->atom_net_wm_window_type_menu || - atoms[i] == compositor->atom_net_wm_window_type_dialog || - atoms[i] == compositor->atom_net_wm_window_type_normal || - atoms[i] == compositor->atom_net_wm_window_type_utility || - atoms[i] == compositor->atom_net_wm_window_type_splash || - atoms[i] == compositor->atom_net_wm_window_type_dropdown_menu || - atoms[i] == compositor->atom_net_wm_window_type_tooltip) - { - type_atom = atoms[i]; - break; - } - } - - meta_XFree (atoms); - - if (type_atom == compositor->atom_net_wm_window_type_dnd) - cw->type = META_COMP_WINDOW_DND; - else if (type_atom == compositor->atom_net_wm_window_type_desktop) - cw->type = META_COMP_WINDOW_DESKTOP; - else if (type_atom == compositor->atom_net_wm_window_type_dock) - cw->type = META_COMP_WINDOW_DOCK; - else if (type_atom == compositor->atom_net_wm_window_type_menu) - cw->type = META_COMP_WINDOW_MENU; - else if (type_atom == compositor->atom_net_wm_window_type_dropdown_menu) - cw->type = META_COMP_WINDOW_DROP_DOWN_MENU; - else if (type_atom == compositor->atom_net_wm_window_type_tooltip) - cw->type = META_COMP_WINDOW_TOOLTIP; - else - cw->type = META_COMP_WINDOW_NORMAL; - -/* meta_verbose ("Window is %d\n", cw->type); */ -} - -/* Must be called with an error trap in place */ -static void -add_win (MetaScreen *screen, - MetaWindow *window, - Window xwindow) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - MetaCompWindow *cw; - gulong event_mask; - - if (info == NULL) - return; - - if (xwindow == info->output) - return; - - cw = g_new0 (MetaCompWindow, 1); - cw->screen = screen; - cw->window = window; - cw->id = xwindow; - - if (!XGetWindowAttributes (xdisplay, xwindow, &cw->attrs)) - { - g_free (cw); - return; - } - get_window_type (display, cw); - - /* If Metacity has decided not to manage this window then the input events - won't have been set on the window */ - event_mask = cw->attrs.your_event_mask | PropertyChangeMask; - - XSelectInput (xdisplay, xwindow, event_mask); - - -#ifdef HAVE_NAME_WINDOW_PIXMAP - cw->back_pixmap = None; - cw->shaded_back_pixmap = None; -#endif - - cw->damaged = FALSE; - cw->shaped = is_shaped (display, xwindow); - - if (cw->attrs.class == InputOnly) - cw->damage = None; - else - cw->damage = XDamageCreate (xdisplay, xwindow, XDamageReportNonEmpty); - - cw->alpha_pict = None; - cw->shadow_pict = None; - cw->border_size = None; - cw->extents = None; - cw->shadow = None; - cw->shadow_dx = 0; - cw->shadow_dy = 0; - cw->shadow_width = 0; - cw->shadow_height = 0; - - if (window && meta_window_has_focus (window)) - cw->shadow_type = META_SHADOW_LARGE; - else - cw->shadow_type = META_SHADOW_MEDIUM; - - cw->opacity = OPAQUE; - - cw->border_clip = None; - - determine_mode (display, screen, cw); - cw->needs_shadow = window_has_shadow (cw); - - /* Only add the window to the list of docks if it needs a shadow */ - if (cw->type == META_COMP_WINDOW_DOCK && cw->needs_shadow) - { - meta_verbose ("Appending %p to dock windows\n", cw); - info->dock_windows = g_slist_append (info->dock_windows, cw); - } - - /* Add this to the list at the top of the stack - before it is mapped so that map_win can find it again */ - info->windows = g_list_prepend (info->windows, cw); - g_hash_table_insert (info->windows_by_xid, (gpointer) xwindow, cw); - - if (cw->attrs.map_state == IsViewable) - map_win (display, screen, xwindow); -} - -static void -destroy_win (MetaDisplay *display, - Window xwindow, - gboolean gone) -{ - MetaScreen *screen; - MetaCompScreen *info; - MetaCompWindow *cw; - - cw = find_window_in_display (display, xwindow); - - if (cw == NULL) - return; - - screen = cw->screen; - - if (cw->extents != None) - { - dump_xserver_region ("destroy_win", display, cw->extents); - add_damage (screen, cw->extents); - cw->extents = None; - } - - info = meta_screen_get_compositor_data (screen); - if (info != NULL) - { - info->windows = g_list_remove (info->windows, (gconstpointer) cw); - g_hash_table_remove (info->windows_by_xid, (gpointer) xwindow); - } - - free_win (cw, TRUE); -} - -static void -restack_win (MetaCompWindow *cw, - Window above) -{ - MetaScreen *screen; - MetaCompScreen *info; - Window previous_above; - GList *sibling, *next; - - screen = cw->screen; - info = meta_screen_get_compositor_data (screen); - - if (info == NULL) - { - return; - } - - sibling = g_list_find (info->windows, (gconstpointer) cw); - next = g_list_next (sibling); - previous_above = None; - - if (next) - { - MetaCompWindow *ncw = (MetaCompWindow *) next->data; - previous_above = ncw->id; - } - - /* If above is set to None, the window whose state was changed is on - * the bottom of the stack with respect to sibling. - */ - if (above == None) - { - /* Insert at bottom of window stack */ - info->windows = g_list_delete_link (info->windows, sibling); - info->windows = g_list_append (info->windows, cw); - } - else if (previous_above != above) - { - GList *index; - - for (index = info->windows; index; index = index->next) { - MetaCompWindow *cw2 = (MetaCompWindow *) index->data; - if (cw2->id == above) - break; - } - - if (index != NULL) - { - info->windows = g_list_delete_link (info->windows, sibling); - info->windows = g_list_insert_before (info->windows, index, cw); - } - } -} - -static void -resize_win (MetaCompWindow *cw, - int x, - int y, - int width, - int height, - int border_width, - gboolean override_redirect) -{ - MetaScreen *screen = cw->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - XserverRegion damage; - gboolean debug; - - debug = DISPLAY_COMPOSITOR (display)->debug; - - if (cw->extents) - { - damage = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesCopyRegion (xdisplay, damage, cw->extents); - } - else - { - damage = None; - if (debug) - fprintf (stderr, "no extents to damage !\n"); - } - - /* { // Damage whole screen each time ! ;-) - XRectangle r; - - r.x = 0; - r.y = 0; - meta_screen_get_size (screen, &r.width, &r.height); - fprintf (stderr, "Damage whole screen %d,%d (%d %d)\n", - r.x, r.y, r.width, r.height); - - damage = XFixesCreateRegion (xdisplay, &r, 1); - } */ - - cw->attrs.x = x; - cw->attrs.y = y; - - if (cw->attrs.width != width || cw->attrs.height != height) - { -#ifdef HAVE_NAME_WINDOW_PIXMAP - if (have_name_window_pixmap (display)) - { - if (cw->shaded_back_pixmap) - { - XFreePixmap (xdisplay, cw->shaded_back_pixmap); - cw->shaded_back_pixmap = None; - } - - if (cw->back_pixmap) - { - /* If the window is shaded, we store the old backing pixmap - so we can return a proper image of the window */ - if (cw->window && meta_window_is_shaded (cw->window)) - { - cw->shaded_back_pixmap = cw->back_pixmap; - cw->back_pixmap = None; - } - else - { - XFreePixmap (xdisplay, cw->back_pixmap); - cw->back_pixmap = None; - } - } - } -#endif - if (cw->picture) - { - XRenderFreePicture (xdisplay, cw->picture); - cw->picture = None; - } - - if (cw->shadow) - { - XRenderFreePicture (xdisplay, cw->shadow); - cw->shadow = None; - } - } - - cw->attrs.width = width; - cw->attrs.height = height; - cw->attrs.border_width = border_width; - cw->attrs.override_redirect = override_redirect; - - if (cw->extents) - XFixesDestroyRegion (xdisplay, cw->extents); - - cw->extents = win_extents (cw); - - if (damage) - { - if (debug) - fprintf (stderr, "Inexplicable intersection with new extents!\n"); - - XFixesUnionRegion (xdisplay, damage, damage, cw->extents); - } - else - { - damage = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesCopyRegion (xdisplay, damage, cw->extents); - } - - dump_xserver_region ("resize_win", display, damage); - add_damage (screen, damage); - - if (info != NULL) - { - info->clip_changed = TRUE; - } -} - -/* event processors must all be called with an error trap in place */ -static void -process_circulate_notify (MetaCompositorXRender *compositor, - XCirculateEvent *event) -{ - MetaCompWindow *cw = find_window_in_display (compositor->display, - event->window); - MetaCompWindow *top; - MetaCompScreen *info; - MetaScreen *screen; - GList *first; - Window above; - - if (!cw) - return; - - screen = cw->screen; - info = meta_screen_get_compositor_data (screen); - first = info->windows; - top = (MetaCompWindow *) first->data; - - if ((event->place == PlaceOnTop) && top) - above = top->id; - else - above = None; - restack_win (cw, above); - - if (info != NULL) - { - info->clip_changed = TRUE; - } - -#ifdef USE_IDLE_REPAINT - add_repair (compositor->display); -#endif -} - -static void -process_configure_notify (MetaCompositorXRender *compositor, - XConfigureEvent *event) -{ - MetaDisplay *display = compositor->display; - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompWindow *cw = find_window_in_display (display, event->window); - - if (cw) - { -#if 0 - int x = -1, y = -1, width = -1, height = -1; - int ex = -1, ey = -1, ewidth = -1, eheight = -1; - MetaRectangle *rect; - - if (cw->window) { - rect = meta_window_get_rect (cw->window); - x = rect->x; - y = rect->y; - width = rect->width; - height = rect->height; - } - fprintf (stderr, "configure notify xy (%d %d) -> (%d %d), wh (%d %d) -> (%d %d)\n", - x, y, event->x, event->y, - width, height, event->width, event->height); -#endif - - if (compositor->debug) - { - fprintf (stderr, "configure notify %d %d %d\n", cw->damaged, - cw->shaped, cw->needs_shadow); - dump_xserver_region ("\textents", display, cw->extents); - fprintf (stderr, "\txy (%d %d), wh (%d %d)\n", - event->x, event->y, event->width, event->height); - } - - restack_win (cw, event->above); - resize_win (cw, event->x, event->y, event->width, event->height, - event->border_width, event->override_redirect); - } - else - { - MetaScreen *screen; - MetaCompScreen *info; - - /* Might be the root window? */ - screen = meta_display_screen_for_root (display, event->window); - if (screen == NULL) - return; - - info = meta_screen_get_compositor_data (screen); - if (info != NULL && info->root_buffer) - { - XRenderFreePicture (xdisplay, info->root_buffer); - info->root_buffer = None; - } - - damage_screen (screen); - } -} - -static void -process_property_notify (MetaCompositorXRender *compositor, - XPropertyEvent *event) -{ - MetaDisplay *display = compositor->display; - Display *xdisplay = meta_display_get_xdisplay (display); - MetaScreen *screen; - int p; - Atom background_atoms[2]; - - /* Check for the background property changing */ - background_atoms[0] = compositor->atom_x_root_pixmap; - background_atoms[1] = compositor->atom_x_set_root; - - for (p = 0; p < 2; p++) - { - if (event->atom == background_atoms[p]) - { - screen = meta_display_screen_for_root (display, event->window); - if (screen) - { - MetaCompScreen *info = meta_screen_get_compositor_data (screen); - Window xroot = meta_screen_get_xroot (screen); - - if (info != NULL && info->root_tile) - { - XClearArea (xdisplay, xroot, 0, 0, 0, 0, TRUE); - XRenderFreePicture (xdisplay, info->root_tile); - info->root_tile = None; - - /* Damage the whole screen as we may need to redraw the - background ourselves */ - damage_screen (screen); -#ifdef USE_IDLE_REPAINT - add_repair (display); -#endif - - return; - } - } - } - } - - /* Check for the opacity changing */ - if (event->atom == compositor->atom_net_wm_window_opacity) - { - MetaCompWindow *cw = find_window_in_display (display, event->window); - gulong value; - - if (!cw) - { - /* Applications can set this for their toplevel windows, so - * this must be propagated to the window managed by the compositor - */ - cw = find_window_for_child_window_in_display (display, event->window); - } - - if (!cw) - return; - - if (meta_prop_get_cardinal (display, event->window, - compositor->atom_net_wm_window_opacity, - &value) == FALSE) - value = OPAQUE; - - cw->opacity = (guint)value; - determine_mode (display, cw->screen, cw); - cw->needs_shadow = window_has_shadow (cw); - - if (cw->shadow) - { - XRenderFreePicture (xdisplay, cw->shadow); - cw->shadow = None; - } - - if (cw->extents) - XFixesDestroyRegion (xdisplay, cw->extents); - cw->extents = win_extents (cw); - - cw->damaged = TRUE; -#ifdef USE_IDLE_REPAINT - add_repair (display); -#endif - - return; - } - - if (event->atom == compositor->atom_net_wm_window_type) { - MetaCompWindow *cw = find_window_in_display (display, event->window); - - if (!cw) - return; - - get_window_type (display, cw); - cw->needs_shadow = window_has_shadow (cw); - return; - } -} - -static void -expose_area (MetaScreen *screen, - XRectangle *rects, - int nrects) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XserverRegion region; - - region = XFixesCreateRegion (xdisplay, rects, nrects); - - dump_xserver_region ("expose_area", display, region); - add_damage (screen, region); -} - -static void -process_expose (MetaCompositorXRender *compositor, - XExposeEvent *event) -{ - MetaCompWindow *cw = find_window_in_display (compositor->display, - event->window); - MetaScreen *screen = NULL; - XRectangle rect[1]; - int origin_x = 0, origin_y = 0; - - if (cw != NULL) - { - screen = cw->screen; - origin_x = cw->attrs.x; /* + cw->attrs.border_width; ? */ - origin_y = cw->attrs.y; /* + cw->attrs.border_width; ? */ - } - else - { - screen = meta_display_screen_for_root (compositor->display, - event->window); - if (screen == NULL) - return; - } - - rect[0].x = event->x + origin_x; - rect[0].y = event->y + origin_y; - rect[0].width = event->width; - rect[0].height = event->height; - - expose_area (screen, rect, 1); -} - -static void -process_unmap (MetaCompositorXRender *compositor, - XUnmapEvent *event) -{ - MetaCompWindow *cw; - - if (event->from_configure) - { - /* Ignore unmap caused by parent's resize */ - return; - } - - - cw = find_window_in_display (compositor->display, event->window); - if (cw) - unmap_win (compositor->display, cw->screen, event->window); -} - -static void -process_map (MetaCompositorXRender *compositor, - XMapEvent *event) -{ - MetaCompWindow *cw = find_window_in_display (compositor->display, - event->window); - - if (cw) - map_win (compositor->display, cw->screen, event->window); -} - -static void -process_reparent (MetaCompositorXRender *compositor, - XReparentEvent *event, - MetaWindow *window) -{ - MetaScreen *screen; - - screen = meta_display_screen_for_root (compositor->display, event->parent); - if (screen != NULL) - add_win (screen, window, event->window); - else - destroy_win (compositor->display, event->window, FALSE); -} - -static void -process_create (MetaCompositorXRender *compositor, - XCreateWindowEvent *event, - MetaWindow *window) -{ - MetaScreen *screen; - /* We are only interested in top level windows, others will - be caught by normal metacity functions */ - - screen = meta_display_screen_for_root (compositor->display, event->parent); - if (screen == NULL) - return; - - if (!find_window_in_display (compositor->display, event->window)) - add_win (screen, window, event->window); -} - -static void -process_destroy (MetaCompositorXRender *compositor, - XDestroyWindowEvent *event) -{ - destroy_win (compositor->display, event->window, FALSE); -} - -static void -process_damage (MetaCompositorXRender *compositor, - XDamageNotifyEvent *event) -{ - MetaCompWindow *cw = find_window_in_display (compositor->display, - event->drawable); - if (cw == NULL) - return; - - repair_win (cw); - -#ifdef USE_IDLE_REPAINT - if (event->more == FALSE) - add_repair (compositor->display); -#endif -} - -static void -process_shape (MetaCompositorXRender *compositor, - XShapeEvent *event) -{ - MetaCompWindow *cw = find_window_in_display (compositor->display, - event->window); - - if (cw == NULL) - return; - - if (event->kind == ShapeBounding) - { - if (!event->shaped && cw->shaped) - cw->shaped = FALSE; - - resize_win (cw, cw->attrs.x, cw->attrs.y, - event->width + event->x, event->height + event->y, - cw->attrs.border_width, cw->attrs.override_redirect); - - if (event->shaped && !cw->shaped) - cw->shaped = TRUE; - } -} - -static int -timeout_debug (MetaCompositorXRender *compositor) -{ - compositor->show_redraw = (g_getenv ("METACITY_DEBUG_REDRAWS") != NULL); - compositor->debug = (g_getenv ("METACITY_DEBUG_COMPOSITOR") != NULL); - - return FALSE; -} - -static void -xrender_add_window (MetaCompositor *compositor, - MetaWindow *window, - Window xwindow, - XWindowAttributes *attrs) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor; - MetaScreen *screen = meta_screen_for_x_screen (attrs->screen); - - meta_error_trap_push (xrc->display); - add_win (screen, window, xwindow); - meta_error_trap_pop (xrc->display, FALSE); -#endif -} - -static void -xrender_remove_window (MetaCompositor *compositor, - Window xwindow) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS -#endif -} - -static void -show_overlay_window (MetaScreen *screen, - Window cow) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - -#ifdef HAVE_COW - if (have_cow (display)) - { - XserverRegion region; - - region = XFixesCreateRegion (xdisplay, NULL, 0); - - XFixesSetWindowShapeRegion (xdisplay, cow, ShapeBounding, 0, 0, 0); - XFixesSetWindowShapeRegion (xdisplay, cow, ShapeInput, 0, 0, region); - - XFixesDestroyRegion (xdisplay, region); - - damage_screen (screen); - } -#endif -} - -static void -hide_overlay_window (MetaScreen *screen, - Window cow) -{ -#ifdef HAVE_COW - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XserverRegion region; - - region = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesSetWindowShapeRegion (xdisplay, cow, ShapeBounding, 0, 0, region); - XFixesDestroyRegion (xdisplay, region); -#endif -} - -static Window -get_output_window (MetaScreen *screen) -{ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - Window output, xroot; - - xroot = meta_screen_get_xroot (screen); - -#ifdef HAVE_COW - if (have_cow (display)) - { - output = XCompositeGetOverlayWindow (xdisplay, xroot); - XSelectInput (xdisplay, output, ExposureMask); - } - else -#endif - { - output = xroot; - } - - return output; -} - -static void -xrender_manage_screen (MetaCompositor *compositor, - MetaScreen *screen) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompScreen *info; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - XRenderPictureAttributes pa; - XRenderPictFormat *visual_format; - int screen_number = meta_screen_get_screen_number (screen); - Window xroot = meta_screen_get_xroot (screen); - - /* Check if the screen is already managed */ - if (meta_screen_get_compositor_data (screen)) - return; - - gdk_error_trap_push (); - XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual); - XSync (xdisplay, FALSE); - - if (gdk_error_trap_pop ()) - { - g_warning ("Another compositing manager is running on screen %i", - screen_number); - return; - } - - info = g_new0 (MetaCompScreen, 1); - info->screen = screen; - - meta_screen_set_compositor_data (screen, info); - - visual_format = XRenderFindVisualFormat (xdisplay, DefaultVisual (xdisplay, - screen_number)); - if (!visual_format) - { - g_warning ("Cannot find visual format on screen %i", screen_number); - return; - } - - info->output = get_output_window (screen); - - pa.subwindow_mode = IncludeInferiors; - info->root_picture = XRenderCreatePicture (xdisplay, info->output, - visual_format, - CPSubwindowMode, &pa); - if (info->root_picture == None) - { - g_warning ("Cannot create root picture on screen %i", screen_number); - return; - } - - info->root_buffer = None; - info->black_picture = solid_picture (display, screen, TRUE, 1, 0, 0, 0); - - info->root_tile = None; - info->all_damage = None; - - info->windows = NULL; - info->windows_by_xid = g_hash_table_new (g_direct_hash, g_direct_equal); - - info->focus_window = meta_display_get_focus_window (display); - - info->compositor_active = TRUE; - info->overlays = 0; - info->clip_changed = TRUE; - - info->have_shadows = (g_getenv("META_DEBUG_NO_SHADOW") == NULL); - if (info->have_shadows) - { - meta_verbose ("Enabling shadows\n"); - generate_shadows (info); - } - else - meta_verbose ("Disabling shadows\n"); - - XClearArea (xdisplay, info->output, 0, 0, 0, 0, TRUE); - - meta_screen_set_cm_selection (screen); - - /* Now we're up and running we can show the output if needed */ - show_overlay_window (screen, info->output); -#endif -} - -static void -xrender_unmanage_screen (MetaCompositor *compositor, - MetaScreen *screen) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - MetaCompScreen *info; - Window xroot = meta_screen_get_xroot (screen); - GList *index; - - info = meta_screen_get_compositor_data (screen); - - /* This screen isn't managed */ - if (info == NULL) - return; - - hide_overlay_window (screen, info->output); - - /* Destroy the windows */ - for (index = info->windows; index; index = index->next) - { - MetaCompWindow *cw = (MetaCompWindow *) index->data; - free_win (cw, TRUE); - } - g_list_free (info->windows); - g_hash_table_destroy (info->windows_by_xid); - - if (info->root_picture) - XRenderFreePicture (xdisplay, info->root_picture); - - if (info->black_picture) - XRenderFreePicture (xdisplay, info->black_picture); - - if (info->have_shadows) - { - int i; - - for (i = 0; i < LAST_SHADOW_TYPE; i++) - g_free (info->shadows[i]->gaussian_map); - } - - XCompositeUnredirectSubwindows (xdisplay, xroot, - CompositeRedirectManual); - meta_screen_unset_cm_selection (screen); - -#ifdef HAVE_COW - XCompositeReleaseOverlayWindow (xdisplay, info->output); -#endif - - g_free (info); - - meta_screen_set_compositor_data (screen, NULL); -#endif -} - -static void -xrender_set_updates (MetaCompositor *compositor, - MetaWindow *window, - gboolean updates) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - -#endif -} - -static void -xrender_destroy (MetaCompositor *compositor) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - g_free (compositor); -#endif -} - -#if 0 -/* Taking these out because they're empty and never called, and the - * compiler complains -- tthurman - */ - -static void -xrender_begin_move (MetaCompositor *compositor, - MetaWindow *window, - MetaRectangle *initial, - int grab_x, - int grab_y) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS -#endif -} - -static void -xrender_update_move (MetaCompositor *compositor, - MetaWindow *window, - int x, - int y) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS -#endif -} - -static void -xrender_end_move (MetaCompositor *compositor, - MetaWindow *window) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS -#endif -} - -static void -xrender_free_window (MetaCompositor *compositor, - MetaWindow *window) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - /* FIXME: When an undecorated window is hidden this is called, - but the window does not get readded if it is subsequentally shown again - See http://bugzilla.gnome.org/show_bug.cgi?id=504876 - - I don't *think* theres any need for this call anyway, leaving it out - does not seem to cause any side effects so far, but I should check with - someone who understands more. */ - /* destroy_win (compositor->display, window->xwindow, FALSE); */ -#endif -} -#endif /* 0 */ - -static void -xrender_process_event (MetaCompositor *compositor, - XEvent *event, - MetaWindow *window) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor; - /* - * This trap is so that none of the compositor functions cause - * X errors. This is really a hack, but I'm afraid I don't understand - * enough about Metacity/X to know how else you are supposed to do it - */ - meta_error_trap_push (xrc->display); - switch (event->type) - { - case CirculateNotify: - process_circulate_notify (xrc, (XCirculateEvent *) event); - break; - - case ConfigureNotify: - process_configure_notify (xrc, (XConfigureEvent *) event); - break; - - case PropertyNotify: - process_property_notify (xrc, (XPropertyEvent *) event); - break; - - case Expose: - process_expose (xrc, (XExposeEvent *) event); - break; - - case UnmapNotify: - process_unmap (xrc, (XUnmapEvent *) event); - break; - - case MapNotify: - process_map (xrc, (XMapEvent *) event); - break; - - case ReparentNotify: - process_reparent (xrc, (XReparentEvent *) event, window); - break; - - case CreateNotify: - process_create (xrc, (XCreateWindowEvent *) event, window); - break; - - case DestroyNotify: - process_destroy (xrc, (XDestroyWindowEvent *) event); - break; - - default: - if (event->type == meta_display_get_damage_event_base (xrc->display) + XDamageNotify) - process_damage (xrc, (XDamageNotifyEvent *) event); -#ifdef HAVE_SHAPE - else if (event->type == meta_display_get_shape_event_base (xrc->display) + ShapeNotify) - process_shape (xrc, (XShapeEvent *) event); -#endif /* HAVE_SHAPE */ - else - { - meta_error_trap_pop (xrc->display, FALSE); - return; - } - break; - } - - meta_error_trap_pop (xrc->display, FALSE); -#ifndef USE_IDLE_REPAINT - repair_display (xrc->display); -#endif - - return; -#endif -} - -static Pixmap -xrender_get_window_pixmap (MetaCompositor *compositor, - MetaWindow *window) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompWindow *cw = NULL; - MetaScreen *screen = meta_window_get_screen (window); - MetaFrame *frame = meta_window_get_frame (window); - - cw = find_window_for_screen (screen, frame ? meta_frame_get_xwindow (frame) : - meta_window_get_xwindow (window)); - if (cw == NULL) - return None; - -#ifdef HAVE_NAME_WINDOW_PIXMAP - if (have_name_window_pixmap (meta_window_get_display (window))) - { - if (meta_window_is_shaded (window)) - return cw->shaded_back_pixmap; - else - return cw->back_pixmap; - } - else -#endif - return None; -#endif -} - -static void -xrender_set_active_window (MetaCompositor *compositor, - MetaScreen *screen, - MetaWindow *window) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor; - MetaDisplay *display; - Display *xdisplay; - MetaCompWindow *old_focus = NULL, *new_focus = NULL; - MetaCompScreen *info = NULL; - MetaWindow *old_focus_win = NULL; - - if (compositor == NULL) - return; - - display = xrc->display; - xdisplay = meta_display_get_xdisplay (display); - info = meta_screen_get_compositor_data (screen); - - if (info != NULL) - { - old_focus_win = info->focus_window; - } - - if (old_focus_win) - { - MetaFrame *f = meta_window_get_frame (old_focus_win); - - old_focus = find_window_for_screen (screen, - f ? meta_frame_get_xwindow (f) : - meta_window_get_xwindow (old_focus_win)); - } - - if (window) - { - MetaFrame *f = meta_window_get_frame (window); - new_focus = find_window_for_screen (screen, - f ? meta_frame_get_xwindow (f) : - meta_window_get_xwindow (window)); - } - - if (info != NULL) - { - info->focus_window = window; - } - - if (old_focus) - { - XserverRegion damage; - - /* Tear down old shadows */ - old_focus->shadow_type = META_SHADOW_MEDIUM; - determine_mode (display, screen, old_focus); - old_focus->needs_shadow = window_has_shadow (old_focus); - - if (old_focus->attrs.map_state == IsViewable) - { - if (old_focus->shadow) - { - XRenderFreePicture (xdisplay, old_focus->shadow); - old_focus->shadow = None; - } - - if (old_focus->extents) - { - damage = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesCopyRegion (xdisplay, damage, old_focus->extents); - XFixesDestroyRegion (xdisplay, old_focus->extents); - } - else - damage = None; - - /* Build new extents */ - old_focus->extents = win_extents (old_focus); - - if (damage) - XFixesUnionRegion (xdisplay, damage, damage, old_focus->extents); - else - { - damage = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesCopyRegion (xdisplay, damage, old_focus->extents); - } - - dump_xserver_region ("resize_win", display, damage); - add_damage (screen, damage); - - if (info != NULL) - { - info->clip_changed = TRUE; - } - } - } - - if (new_focus) - { - XserverRegion damage; - - new_focus->shadow_type = META_SHADOW_LARGE; - determine_mode (display, screen, new_focus); - new_focus->needs_shadow = window_has_shadow (new_focus); - - if (new_focus->shadow) - { - XRenderFreePicture (xdisplay, new_focus->shadow); - new_focus->shadow = None; - } - - if (new_focus->extents) - { - damage = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesCopyRegion (xdisplay, damage, new_focus->extents); - XFixesDestroyRegion (xdisplay, new_focus->extents); - } - else - damage = None; - - /* Build new extents */ - new_focus->extents = win_extents (new_focus); - - if (damage) - XFixesUnionRegion (xdisplay, damage, damage, new_focus->extents); - else - { - damage = XFixesCreateRegion (xdisplay, NULL, 0); - XFixesCopyRegion (xdisplay, damage, new_focus->extents); - } - - dump_xserver_region ("resize_win", display, damage); - add_damage (screen, damage); - - if (info != NULL) - { - info->clip_changed = TRUE; - } - } -#ifdef USE_IDLE_REPAINT - add_repair (display); -#endif -#endif -} - -static MetaCompositor comp_info = { - xrender_destroy, - xrender_manage_screen, - xrender_unmanage_screen, - xrender_add_window, - xrender_remove_window, - xrender_set_updates, - xrender_process_event, - xrender_get_window_pixmap, - xrender_set_active_window -}; - -MetaCompositor * -meta_compositor_xrender_new (MetaDisplay *display) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - char *atom_names[] = { - "_XROOTPMAP_ID", - "_XSETROOT_ID", - "_NET_WM_WINDOW_OPACITY", - "_NET_WM_WINDOW_TYPE_DND", - "_NET_WM_WINDOW_TYPE", - "_NET_WM_WINDOW_TYPE_DESKTOP", - "_NET_WM_WINDOW_TYPE_DOCK", - "_NET_WM_WINDOW_TYPE_MENU", - "_NET_WM_WINDOW_TYPE_DIALOG", - "_NET_WM_WINDOW_TYPE_NORMAL", - "_NET_WM_WINDOW_TYPE_UTILITY", - "_NET_WM_WINDOW_TYPE_SPLASH", - "_NET_WM_WINDOW_TYPE_TOOLBAR", - "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", - "_NET_WM_WINDOW_TYPE_TOOLTIP" - }; - Atom atoms[G_N_ELEMENTS(atom_names)]; - MetaCompositorXRender *xrc; - MetaCompositor *compositor; - Display *xdisplay = meta_display_get_xdisplay (display); - - xrc = g_new (MetaCompositorXRender, 1); - xrc->compositor = comp_info; - - compositor = (MetaCompositor *) xrc; - - xrc->display = display; - - meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names)); - XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names), - False, atoms); - - xrc->atom_x_root_pixmap = atoms[0]; - xrc->atom_x_set_root = atoms[1]; - xrc->atom_net_wm_window_opacity = atoms[2]; - xrc->atom_net_wm_window_type_dnd = atoms[3]; - xrc->atom_net_wm_window_type = atoms[4]; - xrc->atom_net_wm_window_type_desktop = atoms[5]; - xrc->atom_net_wm_window_type_dock = atoms[6]; - xrc->atom_net_wm_window_type_menu = atoms[7]; - xrc->atom_net_wm_window_type_dialog = atoms[8]; - xrc->atom_net_wm_window_type_normal = atoms[9]; - xrc->atom_net_wm_window_type_utility = atoms[10]; - xrc->atom_net_wm_window_type_splash = atoms[11]; - xrc->atom_net_wm_window_type_toolbar = atoms[12]; - xrc->atom_net_wm_window_type_dropdown_menu = atoms[13]; - xrc->atom_net_wm_window_type_tooltip = atoms[14]; - -#ifdef USE_IDLE_REPAINT - meta_verbose ("Using idle repaint\n"); - xrc->repaint_id = 0; -#endif - - xrc->enabled = TRUE; - g_timeout_add (2000, (GSourceFunc) timeout_debug, xrc); - - return compositor; -#else - return NULL; -#endif -} - -#endif /* HAVE_COMPOSITE_EXTENSIONS */ - diff --git a/src/compositor/compositor-xrender.h b/src/compositor/compositor-xrender.h deleted file mode 100644 index 5c8a36c0..00000000 --- a/src/compositor/compositor-xrender.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2007 Iain Holmes - * Based on xcompmgr - (c) 2003 Keith Packard - * xfwm4 - (c) 2005-2007 Olivier Fourdan - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_COMPOSITOR_XRENDER_H_ -#define META_COMPOSITOR_XRENDER_H_ - -#include "types.h" - -MetaCompositor *meta_compositor_xrender_new (MetaDisplay *display); - -#endif diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c deleted file mode 100644 index 975bf341..00000000 --- a/src/compositor/compositor.c +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "compositor-private.h" -#include "compositor-xrender.h" - -MetaCompositor * -meta_compositor_new (MetaDisplay *display) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - /* At some point we would have a way to select between backends */ - return meta_compositor_xrender_new (display); -#else - return NULL; -#endif -} - -void -meta_compositor_destroy (MetaCompositor *compositor) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->destroy) - compositor->destroy (compositor); -#endif -} - -void -meta_compositor_add_window (MetaCompositor *compositor, - MetaWindow *window, - Window xwindow, - XWindowAttributes *attrs) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->add_window) - compositor->add_window (compositor, window, xwindow, attrs); -#endif -} - -void -meta_compositor_remove_window (MetaCompositor *compositor, - Window xwindow) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->remove_window) - compositor->remove_window (compositor, xwindow); -#endif -} - -void -meta_compositor_manage_screen (MetaCompositor *compositor, - MetaScreen *screen) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->manage_screen) - compositor->manage_screen (compositor, screen); -#endif -} - -void -meta_compositor_unmanage_screen (MetaCompositor *compositor, - MetaScreen *screen) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->unmanage_screen) - compositor->unmanage_screen (compositor, screen); -#endif -} - -void -meta_compositor_set_updates (MetaCompositor *compositor, - MetaWindow *window, - gboolean updates) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->set_updates) - compositor->set_updates (compositor, window, updates); -#endif -} - -void -meta_compositor_process_event (MetaCompositor *compositor, - XEvent *event, - MetaWindow *window) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->process_event) - compositor->process_event (compositor, event, window); -#endif -} - -Pixmap -meta_compositor_get_window_pixmap (MetaCompositor *compositor, - MetaWindow *window) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->get_window_pixmap) - return compositor->get_window_pixmap (compositor, window); - else - return None; -#else - return None; -#endif -} - -void -meta_compositor_set_active_window (MetaCompositor *compositor, - MetaScreen *screen, - MetaWindow *window) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - if (compositor && compositor->set_active_window) - compositor->set_active_window (compositor, screen, window); -#endif -} - -/* These functions are unused at the moment */ -void meta_compositor_begin_move (MetaCompositor *compositor, - MetaWindow *window, - MetaRectangle *initial, - int grab_x, - int grab_y) -{ -} - -void meta_compositor_update_move (MetaCompositor *compositor, - MetaWindow *window, - int x, - int y) -{ -} - -void meta_compositor_end_move (MetaCompositor *compositor, - MetaWindow *window) -{ -} - -void meta_compositor_free_window (MetaCompositor *compositor, - MetaWindow *window) -{ -} diff --git a/src/core/async-getprop.c b/src/core/async-getprop.c deleted file mode 100644 index 31b0edc3..00000000 --- a/src/core/async-getprop.c +++ /dev/null @@ -1,680 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Asynchronous X property getting hack */ - -/* - * Copyright (C) 2002 Havoc Pennington - * Copyright (C) 1986, 1998 The Open Group - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation. - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of The Open Group shall not be - * used in advertising or otherwise to promote the sale, use or other dealings - * in this Software without prior written authorization from The Open Group. - */ - -#include <assert.h> - -#undef DEBUG_SPEW -#ifdef DEBUG_SPEW -#include <stdio.h> -#endif - -#include "async-getprop.h" - -#define NEED_REPLIES -#include <X11/Xlibint.h> - -#ifndef NULL -#define NULL ((void*)0) -#endif - -typedef struct _ListNode ListNode; -typedef struct _AgPerDisplayData AgPerDisplayData; - -struct _ListNode -{ - ListNode *next; -}; - -struct _AgGetPropertyTask -{ - ListNode node; - - AgPerDisplayData *dd; - Window window; - Atom property; - - unsigned long request_seq; - int error; - - Atom actual_type; - int actual_format; - - unsigned long n_items; - unsigned long bytes_after; - char *data; - - Bool have_reply; -}; - -struct _AgPerDisplayData -{ - ListNode node; - _XAsyncHandler async; - - Display *display; - ListNode *pending_tasks; - ListNode *pending_tasks_tail; - ListNode *completed_tasks; - ListNode *completed_tasks_tail; - int n_tasks_pending; - int n_tasks_completed; -}; - -static ListNode *display_datas = NULL; -static ListNode *display_datas_tail = NULL; - -static void -append_to_list (ListNode **head, - ListNode **tail, - ListNode *task) -{ - task->next = NULL; - - if (*tail == NULL) - { - assert (*head == NULL); - *head = task; - *tail = task; - } - else - { - (*tail)->next = task; - *tail = task; - } -} - -static void -remove_from_list (ListNode **head, - ListNode **tail, - ListNode *task) -{ - ListNode *prev; - ListNode *node; - - prev = NULL; - node = *head; - while (node != NULL) - { - if (node == task) - { - if (prev) - prev->next = node->next; - else - *head = node->next; - - if (node == *tail) - *tail = prev; - - break; - } - - prev = node; - node = node->next; - } - - /* can't remove what's not there */ - assert (node != NULL); - - node->next = NULL; -} - -static void -move_to_completed (AgPerDisplayData *dd, - AgGetPropertyTask *task) -{ - remove_from_list (&dd->pending_tasks, - &dd->pending_tasks_tail, - &task->node); - - append_to_list (&dd->completed_tasks, - &dd->completed_tasks_tail, - &task->node); - - dd->n_tasks_pending -= 1; - dd->n_tasks_completed += 1; -} - -static AgGetPropertyTask* -find_pending_by_request_sequence (AgPerDisplayData *dd, - unsigned long request_seq) -{ - ListNode *node; - - /* if the sequence is after our last pending task, we - * aren't going to find a match - */ - { - AgGetPropertyTask *task = (AgGetPropertyTask*) dd->pending_tasks_tail; - if (task != NULL) - { - if (task->request_seq < request_seq) - return NULL; - else if (task->request_seq == request_seq) - return task; /* why not check this */ - } - } - - /* Generally we should get replies in the order we sent - * requests, so we should usually be using the task - * at the head of the list, if we use any task at all. - * I'm not sure this is 100% guaranteed, if it is, - * it would be a big speedup. - */ - - node = dd->pending_tasks; - while (node != NULL) - { - AgGetPropertyTask *task = (AgGetPropertyTask*) node; - - if (task->request_seq == request_seq) - return task; - - node = node->next; - } - - return NULL; -} - -static Bool -async_get_property_handler (Display *dpy, - xReply *rep, - char *buf, - int len, - XPointer data) -{ - xGetPropertyReply replbuf; - xGetPropertyReply *reply; - AgGetPropertyTask *task; - AgPerDisplayData *dd; - int bytes_read; - - dd = (AgPerDisplayData*) data; - -#if 0 - printf ("%s: seeing request seq %ld buflen %d\n", __FUNCTION__, - dpy->last_request_read, len); -#endif - - task = find_pending_by_request_sequence (dd, dpy->last_request_read); - - if (task == NULL) - return False; - - assert (dpy->last_request_read == task->request_seq); - - task->have_reply = True; - move_to_completed (dd, task); - - /* read bytes so far */ - bytes_read = SIZEOF (xReply); - - if (rep->generic.type == X_Error) - { - xError errbuf; - - task->error = rep->error.errorCode; - -#ifdef DEBUG_SPEW - printf ("%s: error code = %d (ignoring error, eating %d bytes, generic.length = %ld)\n", - __FUNCTION__, task->error, (SIZEOF (xError) - bytes_read), - rep->generic.length); -#endif - - /* We return True (meaning we consumed the reply) - * because otherwise it would invoke the X error handler, - * and an async API is useless if you have to synchronously - * trap X errors. Also GetProperty can always fail, pretty - * much, so trapping errors is always what you want. - * - * We have to eat all the error reply data here. - * (kind of a charade as we know sizeof(xError) == sizeof(xReply)) - * - * Passing discard = True seems to break things; I don't understand - * why, because there should be no extra data in an error reply, - * right? - */ - _XGetAsyncReply (dpy, (char *)&errbuf, rep, buf, len, - (SIZEOF (xError) - bytes_read) >> 2, /* in 32-bit words */ - False); /* really seems like it should be True */ - - return True; - } - -#ifdef DEBUG_SPEW - printf ("%s: already read %d bytes reading %d more for total of %d; generic.length = %ld\n", - __FUNCTION__, bytes_read, (SIZEOF (xGetPropertyReply) - bytes_read) >> 2, - SIZEOF (xGetPropertyReply), rep->generic.length); -#endif - - /* (kind of a silly as we know sizeof(xGetPropertyReply) == sizeof(xReply)) */ - reply = (xGetPropertyReply *) - _XGetAsyncReply (dpy, (char *)&replbuf, rep, buf, len, - (SIZEOF (xGetPropertyReply) - bytes_read) >> 2, /* in 32-bit words */ - False); /* False means expecting more data to follow, - * don't eat the rest of the reply - */ - - bytes_read = SIZEOF (xGetPropertyReply); - -#ifdef DEBUG_SPEW - printf ("%s: have reply propertyType = %ld format = %d n_items = %ld\n", - __FUNCTION__, reply->propertyType, reply->format, reply->nItems); -#endif - - assert (task->data == NULL); - - /* This is all copied from XGetWindowProperty(). Not sure we should - * LockDisplay(). Not sure I'm passing the right args to - * XGetAsyncData(). Not sure about a lot of things. - */ - - /* LockDisplay (dpy); */ - - if (reply->propertyType != None) - { - long nbytes, netbytes; - - /* this alignment macro from orbit2 */ -#define ALIGN_VALUE(this, boundary) \ - (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1))) - - switch (reply->format) - { - /* - * One extra byte is malloced than is needed to contain the property - * data, but this last byte is null terminated and convenient for - * returning string properties, so the client doesn't then have to - * recopy the string to make it null terminated. - */ - case 8: - nbytes = reply->nItems; - /* there's padding to word boundary */ - netbytes = ALIGN_VALUE (nbytes, 4); - if (nbytes + 1 > 0 && - (task->data = (char *) Xmalloc ((unsigned)nbytes + 1))) - { -#ifdef DEBUG_SPEW - printf ("%s: already read %d bytes using %ld, more eating %ld more\n", - __FUNCTION__, bytes_read, nbytes, netbytes); -#endif - /* _XReadPad (dpy, (char *) task->data, netbytes); */ - _XGetAsyncData (dpy, task->data, buf, len, - bytes_read, nbytes, - netbytes); - } - break; - - case 16: - nbytes = reply->nItems * sizeof (short); - netbytes = reply->nItems << 1; - netbytes = ALIGN_VALUE (netbytes, 4); /* align to word boundary */ - if (nbytes + 1 > 0 && - (task->data = (char *) Xmalloc ((unsigned)nbytes + 1))) - { -#ifdef DEBUG_SPEW - printf ("%s: already read %d bytes using %ld more, eating %ld more\n", - __FUNCTION__, bytes_read, nbytes, netbytes); -#endif - /* _XRead16Pad (dpy, (short *) task->data, netbytes); */ - _XGetAsyncData (dpy, task->data, buf, len, - bytes_read, nbytes, netbytes); - } - break; - - case 32: - /* NOTE buffer is in longs to match XGetWindowProperty() */ - nbytes = reply->nItems * sizeof (long); - netbytes = reply->nItems << 2; /* wire size is always 32 bits though */ - if (nbytes + 1 > 0 && - (task->data = (char *) Xmalloc ((unsigned)nbytes + 1))) - { -#ifdef DEBUG_SPEW - printf ("%s: already read %d bytes using %ld more, eating %ld more\n", - __FUNCTION__, bytes_read, nbytes, netbytes); -#endif - - /* We have to copy the XGetWindowProperty() crackrock - * and get format 32 as long even on 64-bit platforms. - */ - if (sizeof (long) == 8) - { - char *netdata; - char *lptr; - char *end_lptr; - - /* Store the 32-bit values in the end of the array */ - netdata = task->data + nbytes / 2; - - _XGetAsyncData (dpy, netdata, buf, len, - bytes_read, netbytes, - netbytes); - - /* Now move the 32-bit values to the front */ - - lptr = task->data; - end_lptr = task->data + nbytes; - while (lptr != end_lptr) - { - *(long*) lptr = *(CARD32*) netdata; - lptr += sizeof (long); - netdata += sizeof (CARD32); - } - } - else - { - /* Here the wire format matches our actual format */ - _XGetAsyncData (dpy, task->data, buf, len, - bytes_read, netbytes, - netbytes); - } - } - break; - - default: - /* - * This part of the code should never be reached. If it is, - * the server sent back a property with an invalid format. - * This is a BadImplementation error. - * - * However this async GetProperty API doesn't report errors - * via the standard X mechanism, so don't do anything about - * it, other than store it in task->error. - */ - { -#if 0 - xError error; -#endif - - task->error = BadImplementation; - -#if 0 - error.sequenceNumber = task->request_seq; - error.type = X_Error; - error.majorCode = X_GetProperty; - error.minorCode = 0; - error.errorCode = BadImplementation; - - _XError (dpy, &error); -#endif - } - - nbytes = netbytes = 0L; - break; - } - - if (task->data == NULL) - { - task->error = BadAlloc; - -#ifdef DEBUG_SPEW - printf ("%s: already read %d bytes eating %ld\n", - __FUNCTION__, bytes_read, netbytes); -#endif - /* _XEatData (dpy, (unsigned long) netbytes); */ - _XGetAsyncData (dpy, NULL, buf, len, - bytes_read, 0, netbytes); - - /* UnlockDisplay (dpy); */ - return BadAlloc; /* not Success */ - } - - (task->data)[nbytes] = '\0'; - } - -#ifdef DEBUG_SPEW - printf ("%s: have data\n", __FUNCTION__); -#endif - - task->actual_type = reply->propertyType; - task->actual_format = reply->format; - task->n_items = reply->nItems; - task->bytes_after = reply->bytesAfter; - - /* UnlockDisplay (dpy); */ - - return True; -} - -static AgPerDisplayData* -get_display_data (Display *display, - Bool create) -{ - ListNode *node; - AgPerDisplayData *dd; - - node = display_datas; - while (node != NULL) - { - dd = (AgPerDisplayData*) node; - - if (dd->display == display) - return dd; - - node = node->next; - } - - if (!create) - return NULL; - - dd = Xcalloc (1, sizeof (AgPerDisplayData)); - if (dd == NULL) - return NULL; - - dd->display = display; - dd->async.next = display->async_handlers; - dd->async.handler = async_get_property_handler; - dd->async.data = (XPointer) dd; - dd->display->async_handlers = &dd->async; - - append_to_list (&display_datas, - &display_datas_tail, - &dd->node); - - return dd; -} - -static void -maybe_free_display_data (AgPerDisplayData *dd) -{ - if (dd->pending_tasks == NULL && - dd->completed_tasks == NULL) - { - DeqAsyncHandler (dd->display, &dd->async); - remove_from_list (&display_datas, &display_datas_tail, - &dd->node); - XFree (dd); - } -} - -AgGetPropertyTask* -ag_task_create (Display *dpy, - Window window, - Atom property, - long offset, - long length, - Bool delete, - Atom req_type) -{ - AgGetPropertyTask *task; - xGetPropertyReq *req; - AgPerDisplayData *dd; - - /* Fire up our request */ - LockDisplay (dpy); - - dd = get_display_data (dpy, True); - if (dd == NULL) - { - UnlockDisplay (dpy); - return NULL; - } - - GetReq (GetProperty, req); - req->window = window; - req->property = property; - req->type = req_type; - req->delete = delete; - req->longOffset = offset; - req->longLength = length; - - /* Queue up our async task */ - task = Xcalloc (1, sizeof (AgGetPropertyTask)); - if (task == NULL) - { - UnlockDisplay (dpy); - return NULL; - } - - task->dd = dd; - task->window = window; - task->property = property; - task->request_seq = dpy->request; - - append_to_list (&dd->pending_tasks, - &dd->pending_tasks_tail, - &task->node); - dd->n_tasks_pending += 1; - - UnlockDisplay (dpy); - - SyncHandle (); - - return task; -} - -static void -free_task (AgGetPropertyTask *task) -{ - remove_from_list (&task->dd->completed_tasks, - &task->dd->completed_tasks_tail, - &task->node); - task->dd->n_tasks_completed -= 1; - maybe_free_display_data (task->dd); - XFree (task); -} - -Status -ag_task_get_reply_and_free (AgGetPropertyTask *task, - Atom *actual_type, - int *actual_format, - unsigned long *nitems, - unsigned long *bytesafter, - unsigned char **prop) -{ - Display *dpy; - - *prop = NULL; - - dpy = task->dd->display; /* Xlib macros require a variable named "dpy" */ - - if (task->error != Success) - { - Status s = task->error; - - free_task (task); - - return s; - } - - if (!task->have_reply) - { - free_task (task); - - return BadAlloc; /* not Success */ - } - - *actual_type = task->actual_type; - *actual_format = task->actual_format; - *nitems = task->n_items; - *bytesafter = task->bytes_after; - - *prop = (unsigned char*) task->data; /* pass out ownership of task->data */ - - SyncHandle (); - - free_task (task); - - return Success; -} - -Bool -ag_task_have_reply (AgGetPropertyTask *task) -{ - return task->have_reply; -} - -Atom -ag_task_get_property (AgGetPropertyTask *task) -{ - return task->property; -} - -Window -ag_task_get_window (AgGetPropertyTask *task) -{ - return task->window; -} - -Display* -ag_task_get_display (AgGetPropertyTask *task) -{ - return task->dd->display; -} - -AgGetPropertyTask* -ag_get_next_completed_task (Display *display) -{ - AgPerDisplayData *dd; - - dd = get_display_data (display, False); - - if (dd == NULL) - return NULL; - -#ifdef DEBUG_SPEW - printf ("%d pending %d completed\n", - dd->n_tasks_pending, - dd->n_tasks_completed); -#endif - - return (AgGetPropertyTask*) dd->completed_tasks; -} - -void* -ag_Xmalloc (unsigned long bytes) -{ - return (void*) Xmalloc (bytes); -} - -void* -ag_Xmalloc0 (unsigned long bytes) -{ - return (void*) Xcalloc (bytes, 1); -} diff --git a/src/core/async-getprop.h b/src/core/async-getprop.h deleted file mode 100644 index c857e930..00000000 --- a/src/core/async-getprop.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Asynchronous X property getting hack */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation. - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of The Open Group shall not be - * used in advertising or otherwise to promote the sale, use or other dealings - * in this Software without prior written authorization from The Open Group. - */ - -#ifndef ASYNC_GETPROP_H -#define ASYNC_GETPROP_H - -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -typedef struct _AgGetPropertyTask AgGetPropertyTask; - -AgGetPropertyTask* ag_task_create (Display *display, - Window window, - Atom property, - long offset, - long length, - Bool delete, - Atom req_type); -Status ag_task_get_reply_and_free (AgGetPropertyTask *task, - Atom *actual_type, - int *actual_format, - unsigned long *nitems, - unsigned long *bytesafter, - unsigned char **prop); - -Bool ag_task_have_reply (AgGetPropertyTask *task); -Atom ag_task_get_property (AgGetPropertyTask *task); -Window ag_task_get_window (AgGetPropertyTask *task); -Display* ag_task_get_display (AgGetPropertyTask *task); - -AgGetPropertyTask* ag_get_next_completed_task (Display *display); - -/* so other headers don't have to include internal Xlib goo */ -void* ag_Xmalloc (unsigned long bytes); -void* ag_Xmalloc0 (unsigned long bytes); - -#endif - - - - diff --git a/src/core/atomnames.h b/src/core/atomnames.h deleted file mode 100644 index 43710f37..00000000 --- a/src/core/atomnames.h +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2008 Thomas Thurman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** - * \file atomnames.h A list of atom names. - * - * This is a list of the names of all the X atoms that Metacity uses. - * Each is wrapped in a macro "item()" which is undefined here; the - * idea is that when you need to make a big list of all the X atoms, - * you can define item(), include this file, and then undefine it - * again. - * - * If you also define EWMH_ATOMS_ONLY then you will only get _NET_WM_* - * atoms rather than all of them. - */ - -#ifndef item -#error "item(x) must be defined when you include atomnames.h" -#endif - -#ifndef EWMH_ATOMS_ONLY - -item(WM_PROTOCOLS) -item(WM_TAKE_FOCUS) -item(WM_DELETE_WINDOW) -item(WM_STATE) -item(_MOTIF_WM_HINTS) -item(WM_CHANGE_STATE) -item(SM_CLIENT_ID) -item(WM_CLIENT_LEADER) -item(WM_WINDOW_ROLE) -item(UTF8_STRING) -item(WM_ICON_SIZE) -item(_KWM_WIN_ICON) -item(_METACITY_RESTART_MESSAGE) -item(_METACITY_RELOAD_THEME_MESSAGE) -item(_METACITY_SET_KEYBINDINGS_MESSAGE) -item(_METACITY_TOGGLE_VERBOSE) -item(_GNOME_PANEL_ACTION) -item(_GNOME_PANEL_ACTION_MAIN_MENU) -item(_GNOME_PANEL_ACTION_RUN_DIALOG) -item(_METACITY_SENTINEL) -item(_METACITY_VERSION) -item(WM_CLIENT_MACHINE) -item(MANAGER) -item(TARGETS) -item(MULTIPLE) -item(TIMESTAMP) -item(VERSION) -item(ATOM_PAIR) - -/* Oddities: These are used, and we need atoms for them, - * but when we need all _NET_WM hints (i.e. when we're making - * lists of which _NET_WM hints we support in order to advertise - * it) we haven't historically listed them. I don't know what - * the reason for this is. It may be a bug. - */ -item(_NET_WM_SYNC_REQUEST) -item(_NET_WM_SYNC_REQUEST_COUNTER) -item(_NET_WM_VISIBLE_NAME) -item(_NET_WM_VISIBLE_ICON_NAME) -item(_NET_SUPPORTING_WM_CHECK) - -/* But I suppose it's quite reasonable not to advertise using - * _NET_SUPPORTED that we support _NET_SUPPORTED :) - */ -item(_NET_SUPPORTED) - -#endif /* !EWMH_ATOMS_ONLY */ - -/**************************************************************************/ - -item(_NET_WM_NAME) -item(_NET_CLOSE_WINDOW) -item(_NET_WM_STATE) -item(_NET_WM_STATE_SHADED) -item(_NET_WM_STATE_MAXIMIZED_HORZ) -item(_NET_WM_STATE_MAXIMIZED_VERT) -item(_NET_WM_DESKTOP) -item(_NET_NUMBER_OF_DESKTOPS) -item(_NET_CURRENT_DESKTOP) -item(_NET_WM_WINDOW_TYPE) -item(_NET_WM_WINDOW_TYPE_DESKTOP) -item(_NET_WM_WINDOW_TYPE_DOCK) -item(_NET_WM_WINDOW_TYPE_TOOLBAR) -item(_NET_WM_WINDOW_TYPE_MENU) -item(_NET_WM_WINDOW_TYPE_DIALOG) -item(_NET_WM_WINDOW_TYPE_NORMAL) -item(_NET_WM_STATE_MODAL) -item(_NET_CLIENT_LIST) -item(_NET_CLIENT_LIST_STACKING) -item(_NET_WM_STATE_SKIP_TASKBAR) -item(_NET_WM_STATE_SKIP_PAGER) -item(_NET_WM_ICON_NAME) -item(_NET_WM_ICON) -item(_NET_WM_ICON_GEOMETRY) -item(_NET_WM_MOVERESIZE) -item(_NET_ACTIVE_WINDOW) -item(_NET_WM_STRUT) -item(_NET_WM_STATE_HIDDEN) -item(_NET_WM_WINDOW_TYPE_UTILITY) -item(_NET_WM_WINDOW_TYPE_SPLASH) -item(_NET_WM_STATE_FULLSCREEN) -item(_NET_WM_PING) -item(_NET_WM_PID) -item(_NET_WORKAREA) -item(_NET_SHOWING_DESKTOP) -item(_NET_DESKTOP_LAYOUT) -item(_NET_DESKTOP_NAMES) -item(_NET_WM_ALLOWED_ACTIONS) -item(_NET_WM_ACTION_MOVE) -item(_NET_WM_ACTION_RESIZE) -item(_NET_WM_ACTION_SHADE) -item(_NET_WM_ACTION_STICK) -item(_NET_WM_ACTION_MAXIMIZE_HORZ) -item(_NET_WM_ACTION_MAXIMIZE_VERT) -item(_NET_WM_ACTION_CHANGE_DESKTOP) -item(_NET_WM_ACTION_CLOSE) -item(_NET_WM_STATE_ABOVE) -item(_NET_WM_STATE_BELOW) -item(_NET_STARTUP_ID) -item(_NET_WM_STRUT_PARTIAL) -item(_NET_WM_ACTION_FULLSCREEN) -item(_NET_WM_ACTION_MINIMIZE) -item(_NET_FRAME_EXTENTS) -item(_NET_REQUEST_FRAME_EXTENTS) -item(_NET_WM_USER_TIME) -item(_NET_WM_STATE_DEMANDS_ATTENTION) -item(_NET_MOVERESIZE_WINDOW) -item(_NET_DESKTOP_GEOMETRY) -item(_NET_DESKTOP_VIEWPORT) -item(_NET_WM_USER_TIME_WINDOW) -item(_NET_WM_ACTION_ABOVE) -item(_NET_WM_ACTION_BELOW) -item(_NET_WM_STATE_STICKY) -item(_NET_WM_FULLSCREEN_MONITORS) - -#if 0 -/* We apparently never use: */ -/* item(_NET_RESTACK_WINDOW) */ -#endif - -/* eof atomnames.h */ - diff --git a/src/core/bell.c b/src/core/bell.c deleted file mode 100644 index 1b6022c8..00000000 --- a/src/core/bell.c +++ /dev/null @@ -1,363 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity visual bell */ - -/* - * Copyright (C) 2002 Sun Microsystems Inc. - * Copyright (C) 2005, 2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** - * \file bell.c Ring the bell or flash the screen - * - * Sometimes, X programs "ring the bell", whatever that means. Metacity lets - * the user configure the bell to be audible or visible (aka visual), and - * if it's visual it can be configured to be frame-flash or fullscreen-flash. - * We never get told about audible bells; X handles them just fine by itself. - * - * Visual bells come in at meta_bell_notify(), which checks we are actually - * in visual mode and calls through to bell_visual_notify(). That - * function then checks what kind of visual flash you like, and calls either - * bell_flash_fullscreen()-- which calls bell_flash_screen() to do - * its work-- or bell_flash_frame(), which flashes the focussed window - * using bell_flash_window_frame(), unless there is no such window, in - * which case it flashes the screen instead. bell_flash_window_frame() - * flashes the frame and calls bell_unflash_frame() as a timeout to - * remove the flash. - * - * The visual bell was the result of a discussion in Bugzilla here: - * <http://bugzilla.gnome.org/show_bug.cgi?id=99886>. - * - * Several of the functions in this file are ifdeffed out entirely if we are - * found not to have the XKB extension, which is required to do these clever - * things with bells; some others are entirely no-ops in that case. - */ - -#include <config.h> -#include "bell.h" -#include "screen-private.h" -#include "prefs.h" - -/** - * Flashes one entire screen. This is done by making a window the size of the - * whole screen (or reusing the old one, if it's still around), mapping it, - * painting it white and then black, and then unmapping it. We set saveunder so - * that all the windows behind it come back immediately. - * - * Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather, - * we do them in one go, because we don't have to rely on the theme code - * redrawing the frame for us in order to do the flash. - * - * \param display The display which owns the screen (rather redundant) - * \param screen The screen to flash - * - * \bug The way I read it, this appears not to do the flash - * the first time we flash a particular display. Am I wrong? - * - * \bug This appears to destroy our current XSync status. - */ -static void -bell_flash_screen (MetaDisplay *display, - MetaScreen *screen) -{ - Window root = screen->xroot; - int width = screen->rect.width; - int height = screen->rect.height; - - if (screen->flash_window == None) - { - Visual *visual = (Visual *)CopyFromParent; - XSetWindowAttributes xswa; - int depth = CopyFromParent; - xswa.save_under = True; - xswa.override_redirect = True; - /* - * TODO: use XGetVisualInfo and determine which is an - * overlay, if one is present, and use the Overlay visual - * for this window (for performance reasons). - * Not sure how to tell this yet... - */ - screen->flash_window = XCreateWindow (display->xdisplay, root, - 0, 0, width, height, - 0, depth, - InputOutput, - visual, - /* note: XSun doesn't like SaveUnder here */ - CWSaveUnder | CWOverrideRedirect, - &xswa); - XSelectInput (display->xdisplay, screen->flash_window, ExposureMask); - XMapWindow (display->xdisplay, screen->flash_window); - XSync (display->xdisplay, False); - XFlush (display->xdisplay); - XUnmapWindow (display->xdisplay, screen->flash_window); - } - else - { - /* just draw something in the window */ - GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL); - XMapWindow (display->xdisplay, screen->flash_window); - XSetForeground (display->xdisplay, gc, - WhitePixel (display->xdisplay, - XScreenNumberOfScreen (screen->xscreen))); - XFillRectangle (display->xdisplay, screen->flash_window, gc, - 0, 0, width, height); - XSetForeground (display->xdisplay, gc, - BlackPixel (display->xdisplay, - XScreenNumberOfScreen (screen->xscreen))); - XFillRectangle (display->xdisplay, screen->flash_window, gc, - 0, 0, width, height); - XFlush (display->xdisplay); - XSync (display->xdisplay, False); - XUnmapWindow (display->xdisplay, screen->flash_window); - XFreeGC (display->xdisplay, gc); - } - - if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK && - !display->mouse_mode) - meta_display_increment_focus_sentinel (display); - XFlush (display->xdisplay); -} - -/** - * Flashes one screen, or all screens, in response to a bell event. - * If the event is on a particular window, flash the screen that - * window is on. Otherwise, flash every screen on this display. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param display The display the event came in on - * \param xkb_ev The bell event - */ -#ifdef HAVE_XKB -static void -bell_flash_fullscreen (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev; - MetaScreen *screen; - - g_assert (xkb_ev->xkb_type == XkbBellNotify); - if (xkb_bell_ev->window != None) - { - screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window); - if (screen) - bell_flash_screen (display, screen); - } - else - { - GSList *screen_list = display->screens; - while (screen_list) - { - screen = (MetaScreen *) screen_list->data; - bell_flash_screen (display, screen); - screen_list = screen_list->next; - } - } -} - -/** - * Makes a frame be not flashed; this is the timeout half of - * bell_flash_window_frame(). This is done simply by clearing the - * flash flag and queuing a redraw of the frame. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param data The frame to unflash, cast to a gpointer so it can go into - * a callback function. - * \return Always FALSE, so we don't get called again. - * - * \bug This is the parallel to bell_flash_window_frame(), so it should - * really be called meta_bell_unflash_window_frame(). - */ -static gboolean -bell_unflash_frame (gpointer data) -{ - MetaFrame *frame = (MetaFrame *) data; - frame->is_flashing = 0; - meta_frame_queue_draw (frame); - return FALSE; -} - -/** - * Makes a frame flash and then return to normal shortly afterwards. - * This is done by setting a flag so that the theme - * code will temporarily draw the frame as focussed if it's unfocussed and - * vice versa, and then queueing a redraw. Lastly, we create a timeout so - * that the flag can be unset and the frame re-redrawn. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param window The window to flash - */ -static void -bell_flash_window_frame (MetaWindow *window) -{ - g_assert (window->frame != NULL); - window->frame->is_flashing = 1; - meta_frame_queue_draw (window->frame); - g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 100, - bell_unflash_frame, window->frame, NULL); -} - -/** - * Flashes the frame of the focussed window. If there is no focussed window, - * flashes the screen. - * - * \param display The display the bell event came in on - * \param xkb_ev The bell event we just received - */ -static void -bell_flash_frame (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev; - MetaWindow *window; - - g_assert (xkb_ev->xkb_type == XkbBellNotify); - window = meta_display_lookup_x_window (display, xkb_bell_event->window); - if (!window && (display->focus_window) && (display->focus_window->frame)) - { - window = display->focus_window; - } - if (window) - { - bell_flash_window_frame (window); - } - else /* revert to fullscreen flash if there's no focussed window */ - { - bell_flash_fullscreen (display, xkb_ev); - } -} - -/** - * Gives the user some kind of visual bell substitute, in response to a - * bell event. What this is depends on the "visual bell type" pref. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param display The display the bell event came in on - * \param xkb_ev The bell event we just received - * - * \bug This should be merged with meta_bell_notify(). - */ -static void -bell_visual_notify (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - switch (meta_prefs_get_visual_bell_type ()) - { - case META_VISUAL_BELL_FULLSCREEN_FLASH: - bell_flash_fullscreen (display, xkb_ev); - break; - case META_VISUAL_BELL_FRAME_FLASH: - bell_flash_frame (display, xkb_ev); /* does nothing yet */ - break; - case META_VISUAL_BELL_INVALID: - /* do nothing */ - break; - } -} - -void -meta_bell_notify (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - /* flash something */ - if (meta_prefs_get_visual_bell ()) - bell_visual_notify (display, xkb_ev); -} -#endif /* HAVE_XKB */ - -void -meta_bell_set_audible (MetaDisplay *display, gboolean audible) -{ -#ifdef HAVE_XKB - XkbChangeEnabledControls (display->xdisplay, - XkbUseCoreKbd, - XkbAudibleBellMask, - audible ? XkbAudibleBellMask : 0); -#endif -} - -gboolean -meta_bell_init (MetaDisplay *display) -{ -#ifdef HAVE_XKB - int xkb_base_error_type, xkb_opcode; - - if (!XkbQueryExtension (display->xdisplay, &xkb_opcode, - &display->xkb_base_event_type, - &xkb_base_error_type, - NULL, NULL)) - { - display->xkb_base_event_type = -1; - g_message ("could not find XKB extension."); - return FALSE; - } - else - { - unsigned int mask = XkbBellNotifyMask; - gboolean visual_bell_auto_reset = FALSE; - /* TRUE if and when non-broken version is available */ - XkbSelectEvents (display->xdisplay, - XkbUseCoreKbd, - XkbBellNotifyMask, - XkbBellNotifyMask); - XkbChangeEnabledControls (display->xdisplay, - XkbUseCoreKbd, - XkbAudibleBellMask, - meta_prefs_bell_is_audible () - ? XkbAudibleBellMask : 0); - if (visual_bell_auto_reset) { - XkbSetAutoResetControls (display->xdisplay, - XkbAudibleBellMask, - &mask, - &mask); - } - return TRUE; - } -#endif - return FALSE; -} - -void -meta_bell_shutdown (MetaDisplay *display) -{ -#ifdef HAVE_XKB - /* TODO: persist initial bell state in display, reset here */ - XkbChangeEnabledControls (display->xdisplay, - XkbUseCoreKbd, - XkbAudibleBellMask, - XkbAudibleBellMask); -#endif -} - -/** - * Deals with a frame being destroyed. This is important because if we're - * using a visual bell, we might be flashing the edges of the frame, and - * so we'd have a timeout function waiting ready to un-flash them. If the - * frame's going away, we can tell the timeout not to bother. - * - * \param frame The frame which is being destroyed - */ -void -meta_bell_notify_frame_destroy (MetaFrame *frame) -{ - if (frame->is_flashing) - g_source_remove_by_funcs_user_data (&g_timeout_funcs, frame); -} diff --git a/src/core/bell.h b/src/core/bell.h deleted file mode 100644 index 462d1ed7..00000000 --- a/src/core/bell.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file bell.h Ring the bell or flash the screen - * - * Sometimes, X programs "ring the bell", whatever that means. Metacity lets - * the user configure the bell to be audible or visible (aka visual), and - * if it's visual it can be configured to be frame-flash or fullscreen-flash. - * We never get told about audible bells; X handles them just fine by itself. - * - * The visual bell was the result of a discussion in Bugzilla here: - * <http://bugzilla.gnome.org/show_bug.cgi?id=99886>. - */ - -/* - * Copyright (C) 2002 Sun Microsystems Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <X11/Xlib.h> -#ifdef HAVE_XKB -#include <X11/XKBlib.h> -#endif -#include "display-private.h" -#include "frame-private.h" - -#ifdef HAVE_XKB -/** - * Gives the user some kind of visual bell; in fact, this is our response - * to any kind of bell request, but we set it up so that we only get - * notified about visual bells, and X deals with audible ones. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param display The display the bell event came in on - * \param xkb_ev The bell event we just received - */ -void meta_bell_notify (MetaDisplay *display, XkbAnyEvent *xkb_ev); -#endif - -/** - * Turns the bell to audible or visual. This tells X what to do, but - * not Metacity; you will need to set the "visual bell" pref for that. - * - * If the configure script found we had no XKB, this is a no-op. - * - * \param display The display we're configuring - * \param audible True for an audible bell, false for a visual bell - */ -void meta_bell_set_audible (MetaDisplay *display, gboolean audible); - -/** - * Initialises the bell subsystem. This involves intialising - * XKB (which, despite being a keyboard extension, is the - * place to look for bell notifications), then asking it - * to send us bell notifications, and then also switching - * off the audible bell if we're using a visual one ourselves. - * - * Unlike most X extensions we use, we only initialise XKB here - * (rather than in main()). It's possible that XKB is not - * installed at all, but if that was known at build time - * we will have HAVE_XKB undefined, which will cause this - * function to be a no-op. - * - * \param display The display which is opening - * - * \bug There is a line of code that's never run that tells - * XKB to reset the bell status after we quit. Bill H said - * (<http://bugzilla.gnome.org/show_bug.cgi?id=99886#c12>) - * that XFree86's implementation is broken so we shouldn't - * call it, but that was in 2002. Is it working now? - */ -gboolean meta_bell_init (MetaDisplay *display); - -/** - * Shuts down the bell subsystem. - * - * \param display The display which is closing - * - * \bug This is never called! If we had XkbSetAutoResetControls - * enabled in meta_bell_init(), this wouldn't be a problem, but - * we don't. - */ -void meta_bell_shutdown (MetaDisplay *display); - -/** - * Deals with a frame being destroyed. This is important because if we're - * using a visual bell, we might be flashing the edges of the frame, and - * so we'd have a timeout function waiting ready to un-flash them. If the - * frame's going away, we can tell the timeout not to bother. - * - * \param frame The frame which is being destroyed - */ -void meta_bell_notify_frame_destroy (MetaFrame *frame); diff --git a/src/core/boxes.c b/src/core/boxes.c deleted file mode 100644 index 139f1736..00000000 --- a/src/core/boxes.c +++ /dev/null @@ -1,1926 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Simple box operations */ - -/* - * Copyright (C) 2005, 2006 Elijah Newren - * [meta_rectangle_intersect() is copyright the GTK+ Team according to Havoc, - * see gdkrectangle.c. As far as Havoc knows, he probably wrote - * meta_rectangle_equal(), and I'm guessing it's (C) Red Hat. So...] - * Copyright (C) 1995-2000 GTK+ Team - * Copyright (C) 2002 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "boxes.h" -#include "util.h" -#include <X11/Xutil.h> /* Just for the definition of the various gravities */ - -char* -meta_rectangle_to_string (const MetaRectangle *rect, - char *output) -{ - /* 25 chars: 2 commas, space, plus, trailing \0 + 5 for each digit. - * Should be more than enough space. Note that of this space, the - * trailing \0 will be overwritten for all but the last rectangle. - */ - g_snprintf (output, RECT_LENGTH, "%d,%d +%d,%d", - rect->x, rect->y, rect->width, rect->height); - - return output; -} - -char* -meta_rectangle_region_to_string (GList *region, - const char *separator_string, - char *output) -{ - /* 27 chars: 2 commas, 2 square brackets, space, plus, trailing \0 + 5 - * for each digit. Should be more than enough space. Note that of this - * space, the trailing \0 will be overwritten for all but the last - * rectangle. - */ - char rect_string[RECT_LENGTH]; - - GList *tmp = region; - char *cur = output; - - if (region == NULL) - g_snprintf (output, 10, "(EMPTY)"); - - while (tmp) - { - MetaRectangle *rect = tmp->data; - g_snprintf (rect_string, RECT_LENGTH, "[%d,%d +%d,%d]", - rect->x, rect->y, rect->width, rect->height); - cur = g_stpcpy (cur, rect_string); - tmp = tmp->next; - if (tmp) - cur = g_stpcpy (cur, separator_string); - } - - return output; -} - -char* -meta_rectangle_edge_to_string (const MetaEdge *edge, - char *output) -{ - /* 25 chars: 2 commas, space, plus, trailing \0 + 5 for each digit. - * Should be more than enough space. Note that of this space, the - * trailing \0 will be overwritten for all but the last rectangle. - * - * Plus 2 for parenthesis, 4 for 2 more numbers, 2 more commas, and - * 2 more spaces, for a total of 10 more. - */ - g_snprintf (output, EDGE_LENGTH, "[%d,%d +%d,%d], %2d, %2d", - edge->rect.x, edge->rect.y, edge->rect.width, edge->rect.height, - edge->side_type, edge->edge_type); - - return output; -} - -char* -meta_rectangle_edge_list_to_string (GList *edge_list, - const char *separator_string, - char *output) -{ - /* 27 chars: 2 commas, 2 square brackets, space, plus, trailing \0 + 5 for - * each digit. Should be more than enough space. Note that of this - * space, the trailing \0 will be overwritten for all but the last - * rectangle. - * - * Plus 2 for parenthesis, 4 for 2 more numbers, 2 more commas, and - * 2 more spaces, for a total of 10 more. - */ - char rect_string[EDGE_LENGTH]; - - char *cur = output; - GList *tmp = edge_list; - - if (edge_list == NULL) - g_snprintf (output, 10, "(EMPTY)"); - - while (tmp) - { - MetaEdge *edge = tmp->data; - MetaRectangle *rect = &edge->rect; - g_snprintf (rect_string, EDGE_LENGTH, "([%d,%d +%d,%d], %2d, %2d)", - rect->x, rect->y, rect->width, rect->height, - edge->side_type, edge->edge_type); - cur = g_stpcpy (cur, rect_string); - tmp = tmp->next; - if (tmp) - cur = g_stpcpy (cur, separator_string); - } - - return output; -} - -MetaRectangle -meta_rect (int x, int y, int width, int height) -{ - MetaRectangle temporary; - temporary.x = x; - temporary.y = y; - temporary.width = width; - temporary.height = height; - - return temporary; -} - -int -meta_rectangle_area (const MetaRectangle *rect) -{ - g_return_val_if_fail (rect != NULL, 0); - return rect->width * rect->height; -} - -gboolean -meta_rectangle_intersect (const MetaRectangle *src1, - const MetaRectangle *src2, - MetaRectangle *dest) -{ - int dest_x, dest_y; - int dest_w, dest_h; - int return_val; - - g_return_val_if_fail (src1 != NULL, FALSE); - g_return_val_if_fail (src2 != NULL, FALSE); - g_return_val_if_fail (dest != NULL, FALSE); - - return_val = FALSE; - - dest_x = MAX (src1->x, src2->x); - dest_y = MAX (src1->y, src2->y); - dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x; - dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y; - - if (dest_w > 0 && dest_h > 0) - { - dest->x = dest_x; - dest->y = dest_y; - dest->width = dest_w; - dest->height = dest_h; - return_val = TRUE; - } - else - { - dest->width = 0; - dest->height = 0; - } - - return return_val; -} - -gboolean -meta_rectangle_equal (const MetaRectangle *src1, - const MetaRectangle *src2) -{ - return ((src1->x == src2->x) && - (src1->y == src2->y) && - (src1->width == src2->width) && - (src1->height == src2->height)); -} - -void -meta_rectangle_union (const MetaRectangle *rect1, - const MetaRectangle *rect2, - MetaRectangle *dest) -{ - int dest_x, dest_y; - int dest_w, dest_h; - - dest_x = rect1->x; - dest_y = rect1->y; - dest_w = rect1->width; - dest_h = rect1->height; - - if (rect2->x < dest_x) - { - dest_w += dest_x - rect2->x; - dest_x = rect2->x; - } - if (rect2->y < dest_y) - { - dest_h += dest_y - rect2->y; - dest_y = rect2->y; - } - if (rect2->x + rect2->width > dest_x + dest_w) - dest_w = rect2->x + rect2->width - dest_x; - if (rect2->y + rect2->height > dest_y + dest_h) - dest_h = rect2->y + rect2->height - dest_y; - - dest->x = dest_x; - dest->y = dest_y; - dest->width = dest_w; - dest->height = dest_h; -} - -gboolean -meta_rectangle_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2) -{ - g_return_val_if_fail (rect1 != NULL, FALSE); - g_return_val_if_fail (rect2 != NULL, FALSE); - - return !((rect1->x + rect1->width <= rect2->x) || - (rect2->x + rect2->width <= rect1->x) || - (rect1->y + rect1->height <= rect2->y) || - (rect2->y + rect2->height <= rect1->y)); -} - -gboolean -meta_rectangle_vert_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2) -{ - return (rect1->y < rect2->y + rect2->height && - rect2->y < rect1->y + rect1->height); -} - -gboolean -meta_rectangle_horiz_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2) -{ - return (rect1->x < rect2->x + rect2->width && - rect2->x < rect1->x + rect1->width); -} - -gboolean -meta_rectangle_could_fit_rect (const MetaRectangle *outer_rect, - const MetaRectangle *inner_rect) -{ - return (outer_rect->width >= inner_rect->width && - outer_rect->height >= inner_rect->height); -} - -gboolean -meta_rectangle_contains_rect (const MetaRectangle *outer_rect, - const MetaRectangle *inner_rect) -{ - return - inner_rect->x >= outer_rect->x && - inner_rect->y >= outer_rect->y && - inner_rect->x + inner_rect->width <= outer_rect->x + outer_rect->width && - inner_rect->y + inner_rect->height <= outer_rect->y + outer_rect->height; -} - -void -meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect, - MetaRectangle *rect, - int gravity, - int new_width, - int new_height) -{ - /* FIXME: I'm too deep into this to know whether the below comment is - * still clear or not now that I've moved it out of constraints.c. - * boxes.h has a good comment, but I'm not sure if the below info is also - * helpful on top of that (or whether it has superfluous info). - */ - - /* These formulas may look overly simplistic at first but you can work - * everything out with a left_frame_with, right_frame_width, - * border_width, and old and new client area widths (instead of old total - * width and new total width) and you come up with the same formulas. - * - * Also, note that the reason we can treat NorthWestGravity and - * StaticGravity the same is because we're not given a location at - * which to place the window--the window was already placed - * appropriately before. So, NorthWestGravity for this function - * means to just leave the upper left corner of the outer window - * where it already is, and StaticGravity for this function means to - * just leave the upper left corner of the inner window where it - * already is. But leaving either of those two corners where they - * already are will ensure that the other corner is fixed as well - * (since frame size doesn't change)--thus making the two - * equivalent. - */ - - /* First, the x direction */ - int adjust = 0; - switch (gravity) - { - case NorthWestGravity: - case WestGravity: - case SouthWestGravity: - rect->x = old_rect->x; - break; - - case NorthGravity: - case CenterGravity: - case SouthGravity: - /* FIXME: Needing to adjust new_width kind of sucks, but not doing so - * would cause drift. - */ - new_width -= (old_rect->width - new_width) % 2; - rect->x = old_rect->x + (old_rect->width - new_width)/2; - break; - - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - rect->x = old_rect->x + (old_rect->width - new_width); - break; - - case StaticGravity: - default: - rect->x = old_rect->x; - break; - } - rect->width = new_width; - - /* Next, the y direction */ - adjust = 0; - switch (gravity) - { - case NorthWestGravity: - case NorthGravity: - case NorthEastGravity: - rect->y = old_rect->y; - break; - - case WestGravity: - case CenterGravity: - case EastGravity: - /* FIXME: Needing to adjust new_height kind of sucks, but not doing so - * would cause drift. - */ - new_height -= (old_rect->height - new_height) % 2; - rect->y = old_rect->y + (old_rect->height - new_height)/2; - break; - - case SouthWestGravity: - case SouthGravity: - case SouthEastGravity: - rect->y = old_rect->y + (old_rect->height - new_height); - break; - - case StaticGravity: - default: - rect->y = old_rect->y; - break; - } - rect->height = new_height; -} - -/* Not so simple helper function for get_minimal_spanning_set_for_region() */ -static GList* -merge_spanning_rects_in_region (GList *region) -{ - /* NOTE FOR ANY OPTIMIZATION PEOPLE OUT THERE: Please see the - * documentation of get_minimal_spanning_set_for_region() for performance - * considerations that also apply to this function. - */ - - GList* compare; - compare = region; - - if (region == NULL) - { - meta_warning ("Region to merge was empty! Either you have a some " - "pathological STRUT list or there's a bug somewhere!\n"); - return NULL; - } - - while (compare && compare->next) - { - MetaRectangle *a = compare->data; - GList *other = compare->next; - - g_assert (a->width > 0 && a->height > 0); - - while (other) - { - MetaRectangle *b = other->data; - GList *delete_me = NULL; - - g_assert (b->width > 0 && b->height > 0); - - /* If a contains b, just remove b */ - if (meta_rectangle_contains_rect (a, b)) - { - delete_me = other; - } - /* If b contains a, just remove a */ - else if (meta_rectangle_contains_rect (a, b)) - { - delete_me = compare; - } - /* If a and b might be mergeable horizontally */ - else if (a->y == b->y && a->height == b->height) - { - /* If a and b overlap */ - if (meta_rectangle_overlap (a, b)) - { - int new_x = MIN (a->x, b->x); - a->width = MAX (a->x + a->width, b->x + b->width) - new_x; - a->x = new_x; - delete_me = other; - } - /* If a and b are adjacent */ - else if (a->x + a->width == b->x || a->x == b->x + b->width) - { - int new_x = MIN (a->x, b->x); - a->width = MAX (a->x + a->width, b->x + b->width) - new_x; - a->x = new_x; - delete_me = other; - } - } - /* If a and b might be mergeable vertically */ - else if (a->x == b->x && a->width == b->width) - { - /* If a and b overlap */ - if (meta_rectangle_overlap (a, b)) - { - int new_y = MIN (a->y, b->y); - a->height = MAX (a->y + a->height, b->y + b->height) - new_y; - a->y = new_y; - delete_me = other; - } - /* If a and b are adjacent */ - else if (a->y + a->height == b->y || a->y == b->y + b->height) - { - int new_y = MIN (a->y, b->y); - a->height = MAX (a->y + a->height, b->y + b->height) - new_y; - a->y = new_y; - delete_me = other; - } - } - - other = other->next; - - /* Delete any rectangle in the list that is no longer wanted */ - if (delete_me != NULL) - { - /* Deleting the rect we compare others to is a little tricker */ - if (compare == delete_me) - { - compare = compare->next; - other = compare->next; - a = compare->data; - } - - /* Okay, we can free it now */ - g_free (delete_me->data); - region = g_list_delete_link (region, delete_me); - } - - } - - compare = compare->next; - } - - return region; -} - -/* Simple helper function for get_minimal_spanning_set_for_region()... */ -static gint -compare_rect_areas (gconstpointer a, gconstpointer b) -{ - const MetaRectangle *a_rect = (gconstpointer) a; - const MetaRectangle *b_rect = (gconstpointer) b; - - int a_area = meta_rectangle_area (a_rect); - int b_area = meta_rectangle_area (b_rect); - - return b_area - a_area; /* positive ret value denotes b > a, ... */ -} - -/* This function is trying to find a "minimal spanning set (of rectangles)" - * for a given region. - * - * The region is given by taking basic_rect, then removing the areas - * covered by all the rectangles in the all_struts list, and then expanding - * the resulting region by the given number of pixels in each direction. - * - * A "minimal spanning set (of rectangles)" is the best name I could come - * up with for the concept I had in mind. Basically, for a given region, I - * want a set of rectangles with the property that a window is contained in - * the region if and only if it is contained within at least one of the - * rectangles. - * - * The GList* returned will be a list of (allocated) MetaRectangles. - * The list will need to be freed by calling - * meta_rectangle_free_spanning_set() on it (or by manually - * implementing that function...) - */ -GList* -meta_rectangle_get_minimal_spanning_set_for_region ( - const MetaRectangle *basic_rect, - const GSList *all_struts) -{ - /* NOTE FOR OPTIMIZERS: This function *might* be somewhat slow, - * especially due to the call to merge_spanning_rects_in_region() (which - * is O(n^2) where n is the size of the list generated in this function). - * This is made more onerous due to the fact that it involves a fair - * number of memory allocation and deallocation calls. However, n is 1 - * for default installations of Gnome (because partial struts aren't used - * by default and only partial struts increase the size of the spanning - * set generated). With one partial strut, n will be 2 or 3. With 2 - * partial struts, n will probably be 4 or 5. So, n probably isn't large - * enough to make this worth bothering. Further, it is only called from - * workspace.c:ensure_work_areas_validated (at least as of the time of - * writing this comment), which in turn should only be called if the - * strut list changes or the screen or xinerama size changes. If it ever - * does show up on profiles (most likely because people start using - * ridiculously huge numbers of partial struts), possible optimizations - * include: - * - * (1) rewrite merge_spanning_rects_in_region() to be O(n) or O(nlogn). - * I'm not totally sure it's possible, but with a couple copies of - * the list and sorting them appropriately, I believe it might be. - * (2) only call merge_spanning_rects_in_region() with a subset of the - * full list of rectangles. I believe from some of my preliminary - * debugging and thinking about it that it is possible to figure out - * apriori groups of rectangles which are only merge candidates with - * each other. (See testboxes.c:get_screen_region() when which==2 - * and track the steps of this function carefully to see what gave - * me the hint that this might work) - * (3) figure out how to avoid merge_spanning_rects_in_region(). I think - * it might be possible to modify this function to make that - * possible, and I spent just a little while thinking about it, but n - * wasn't large enough to convince me to care yet. - * (4) Some of the stuff Rob mentioned at http://mail.gnome.org/archives\ - * /metacity-devel-list/2005-November/msg00028.html. (Sorry for the - * URL splitting.) - */ - - GList *ret; - GList *tmp_list; - const GSList *strut_iter; - MetaRectangle *temp_rect; - - /* The algorithm is basically as follows: - * Initialize rectangle_set to basic_rect - * Foreach strut: - * Foreach rectangle in rectangle_set: - * - Split the rectangle into new rectangles that don't overlap the - * strut (but which are as big as possible otherwise) - * - Remove the old (pre-split) rectangle from the rectangle_set, - * and replace it with the new rectangles generated from the - * splitting - */ - - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *basic_rect; - ret = g_list_prepend (NULL, temp_rect); - - strut_iter = all_struts; - for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next) - { - GList *rect_iter; - MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect; - - tmp_list = ret; - ret = NULL; - rect_iter = tmp_list; - while (rect_iter) - { - MetaRectangle *rect = (MetaRectangle*) rect_iter->data; - if (!meta_rectangle_overlap (rect, strut_rect)) - ret = g_list_prepend (ret, rect); - else - { - /* If there is area in rect left of strut */ - if (BOX_LEFT (*rect) < BOX_LEFT (*strut_rect)) - { - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *rect; - temp_rect->width = BOX_LEFT (*strut_rect) - BOX_LEFT (*rect); - ret = g_list_prepend (ret, temp_rect); - } - /* If there is area in rect right of strut */ - if (BOX_RIGHT (*rect) > BOX_RIGHT (*strut_rect)) - { - int new_x; - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *rect; - new_x = BOX_RIGHT (*strut_rect); - temp_rect->width = BOX_RIGHT(*rect) - new_x; - temp_rect->x = new_x; - ret = g_list_prepend (ret, temp_rect); - } - /* If there is area in rect above strut */ - if (BOX_TOP (*rect) < BOX_TOP (*strut_rect)) - { - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *rect; - temp_rect->height = BOX_TOP (*strut_rect) - BOX_TOP (*rect); - ret = g_list_prepend (ret, temp_rect); - } - /* If there is area in rect below strut */ - if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*strut_rect)) - { - int new_y; - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *rect; - new_y = BOX_BOTTOM (*strut_rect); - temp_rect->height = BOX_BOTTOM (*rect) - new_y; - temp_rect->y = new_y; - ret = g_list_prepend (ret, temp_rect); - } - g_free (rect); - } - rect_iter = rect_iter->next; - } - g_list_free (tmp_list); - } - - /* Sort by maximal area, just because I feel like it... */ - ret = g_list_sort (ret, compare_rect_areas); - - /* Merge rectangles if possible so that the list really is minimal */ - ret = merge_spanning_rects_in_region (ret); - - return ret; -} - -GList* -meta_rectangle_expand_region (GList *region, - const int left_expand, - const int right_expand, - const int top_expand, - const int bottom_expand) -{ - return meta_rectangle_expand_region_conditionally (region, - left_expand, - right_expand, - top_expand, - bottom_expand, - 0, - 0); -} - -GList* -meta_rectangle_expand_region_conditionally (GList *region, - const int left_expand, - const int right_expand, - const int top_expand, - const int bottom_expand, - const int min_x, - const int min_y) -{ - GList *tmp_list = region; - while (tmp_list) - { - MetaRectangle *rect = (MetaRectangle*) tmp_list->data; - if (rect->width >= min_x) - { - rect->x -= left_expand; - rect->width += (left_expand + right_expand); - } - if (rect->height >= min_y) - { - rect->y -= top_expand; - rect->height += (top_expand + bottom_expand); - } - tmp_list = tmp_list->next; - } - - return region; -} - -void -meta_rectangle_expand_to_avoiding_struts (MetaRectangle *rect, - const MetaRectangle *expand_to, - const MetaDirection direction, - const GSList *all_struts) -{ - const GSList *strut_iter; - - /* If someone wants this function to handle more fine-grained - * direction expanding in the future (e.g. only left, or fully - * horizontal plus upward), feel free. But I'm hard-coding for both - * horizontal directions (exclusive-)or both vertical directions. - */ - g_assert ((direction == META_DIRECTION_HORIZONTAL) ^ - (direction == META_DIRECTION_VERTICAL )); - - if (direction == META_DIRECTION_HORIZONTAL) - { - rect->x = expand_to->x; - rect->width = expand_to->width; - } - else - { - rect->y = expand_to->y; - rect->height = expand_to->height; - } - - - /* Run over all struts */ - for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next) - { - MetaStrut *strut = (MetaStrut*) strut_iter->data; - - /* Skip struts that don't overlap */ - if (!meta_rectangle_overlap (&strut->rect, rect)) - continue; - - if (direction == META_DIRECTION_HORIZONTAL) - { - if (strut->side == META_SIDE_LEFT) - { - int offset = BOX_RIGHT(strut->rect) - BOX_LEFT(*rect); - rect->x += offset; - rect->width -= offset; - } - else if (strut->side == META_SIDE_RIGHT) - { - int offset = BOX_RIGHT (*rect) - BOX_LEFT(strut->rect); - rect->width -= offset; - } - /* else ignore the strut */ - } - else /* direction == META_DIRECTION_VERTICAL */ - { - if (strut->side == META_SIDE_TOP) - { - int offset = BOX_BOTTOM(strut->rect) - BOX_TOP(*rect); - rect->y += offset; - rect->height -= offset; - } - else if (strut->side == META_SIDE_BOTTOM) - { - int offset = BOX_BOTTOM(*rect) - BOX_TOP(strut->rect); - rect->height -= offset; - } - /* else ignore the strut */ - } - } /* end loop over struts */ -} /* end meta_rectangle_expand_to_avoiding_struts */ - -void -meta_rectangle_free_list_and_elements (GList *filled_list) -{ - g_list_foreach (filled_list, - (void (*)(gpointer,gpointer))&g_free, /* ew, for ugly */ - NULL); - g_list_free (filled_list); -} - -gboolean -meta_rectangle_could_fit_in_region (const GList *spanning_rects, - const MetaRectangle *rect) -{ - const GList *temp; - gboolean could_fit; - - temp = spanning_rects; - could_fit = FALSE; - while (!could_fit && temp != NULL) - { - could_fit = could_fit || meta_rectangle_could_fit_rect (temp->data, rect); - temp = temp->next; - } - - return could_fit; -} - -gboolean -meta_rectangle_contained_in_region (const GList *spanning_rects, - const MetaRectangle *rect) -{ - const GList *temp; - gboolean contained; - - temp = spanning_rects; - contained = FALSE; - while (!contained && temp != NULL) - { - contained = contained || meta_rectangle_contains_rect (temp->data, rect); - temp = temp->next; - } - - return contained; -} - -gboolean -meta_rectangle_overlaps_with_region (const GList *spanning_rects, - const MetaRectangle *rect) -{ - const GList *temp; - gboolean overlaps; - - temp = spanning_rects; - overlaps = FALSE; - while (!overlaps && temp != NULL) - { - overlaps = overlaps || meta_rectangle_overlap (temp->data, rect); - temp = temp->next; - } - - return overlaps; -} - - -void -meta_rectangle_clamp_to_fit_into_region (const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect, - const MetaRectangle *min_size) -{ - const GList *temp; - const MetaRectangle *best_rect = NULL; - int best_overlap = 0; - - /* First, find best rectangle from spanning_rects to which we can clamp - * rect to fit into. - */ - for (temp = spanning_rects; temp; temp = temp->next) - { - MetaRectangle *compare_rect = temp->data; - int maximal_overlap_amount_for_compare; - - /* If x is fixed and the entire width of rect doesn't fit in compare, - * skip this rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_X) && - (compare_rect->x > rect->x || - compare_rect->x + compare_rect->width < rect->x + rect->width)) - continue; - - /* If y is fixed and the entire height of rect doesn't fit in compare, - * skip this rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_Y) && - (compare_rect->y > rect->y || - compare_rect->y + compare_rect->height < rect->y + rect->height)) - continue; - - /* If compare can't hold the min_size window, skip this rectangle. */ - if (compare_rect->width < min_size->width || - compare_rect->height < min_size->height) - continue; - - /* Determine maximal overlap amount */ - maximal_overlap_amount_for_compare = - MIN (rect->width, compare_rect->width) * - MIN (rect->height, compare_rect->height); - - /* See if this is the best rect so far */ - if (maximal_overlap_amount_for_compare > best_overlap) - { - best_rect = compare_rect; - best_overlap = maximal_overlap_amount_for_compare; - } - } - - /* Clamp rect appropriately */ - if (best_rect == NULL) - { - meta_warning ("No rect whose size to clamp to found!\n"); - - /* If it doesn't fit, at least make it no bigger than it has to be */ - if (!(fixed_directions & FIXED_DIRECTION_X)) - rect->width = min_size->width; - if (!(fixed_directions & FIXED_DIRECTION_Y)) - rect->height = min_size->height; - } - else - { - rect->width = MIN (rect->width, best_rect->width); - rect->height = MIN (rect->height, best_rect->height); - } -} - -void -meta_rectangle_clip_to_region (const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect) -{ - const GList *temp; - const MetaRectangle *best_rect = NULL; - int best_overlap = 0; - - /* First, find best rectangle from spanning_rects to which we will clip - * rect into. - */ - for (temp = spanning_rects; temp; temp = temp->next) - { - MetaRectangle *compare_rect = temp->data; - MetaRectangle overlap; - int maximal_overlap_amount_for_compare; - - /* If x is fixed and the entire width of rect doesn't fit in compare, - * skip the rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_X) && - (compare_rect->x > rect->x || - compare_rect->x + compare_rect->width < rect->x + rect->width)) - continue; - - /* If y is fixed and the entire height of rect doesn't fit in compare, - * skip the rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_Y) && - (compare_rect->y > rect->y || - compare_rect->y + compare_rect->height < rect->y + rect->height)) - continue; - - /* Determine maximal overlap amount */ - meta_rectangle_intersect (rect, compare_rect, &overlap); - maximal_overlap_amount_for_compare = meta_rectangle_area (&overlap); - - /* See if this is the best rect so far */ - if (maximal_overlap_amount_for_compare > best_overlap) - { - best_rect = compare_rect; - best_overlap = maximal_overlap_amount_for_compare; - } - } - - /* Clip rect appropriately */ - if (best_rect == NULL) - meta_warning ("No rect to clip to found!\n"); - else - { - /* Extra precaution with checking fixed direction shouldn't be needed - * due to logic above, but it shouldn't hurt either. - */ - if (!(fixed_directions & FIXED_DIRECTION_X)) - { - /* Find the new left and right */ - int new_x = MAX (rect->x, best_rect->x); - rect->width = MIN ((rect->x + rect->width) - new_x, - (best_rect->x + best_rect->width) - new_x); - rect->x = new_x; - } - - /* Extra precaution with checking fixed direction shouldn't be needed - * due to logic above, but it shouldn't hurt either. - */ - if (!(fixed_directions & FIXED_DIRECTION_Y)) - { - /* Clip the top, if needed */ - int new_y = MAX (rect->y, best_rect->y); - rect->height = MIN ((rect->y + rect->height) - new_y, - (best_rect->y + best_rect->height) - new_y); - rect->y = new_y; - } - } -} - -void -meta_rectangle_shove_into_region (const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect) -{ - const GList *temp; - const MetaRectangle *best_rect = NULL; - int best_overlap = 0; - int shortest_distance = G_MAXINT; - - /* First, find best rectangle from spanning_rects to which we will shove - * rect into. - */ - - for (temp = spanning_rects; temp; temp = temp->next) - { - MetaRectangle *compare_rect = temp->data; - int maximal_overlap_amount_for_compare; - int dist_to_compare; - - /* If x is fixed and the entire width of rect doesn't fit in compare, - * skip this rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_X) && - (compare_rect->x > rect->x || - compare_rect->x + compare_rect->width < rect->x + rect->width)) - continue; - - /* If y is fixed and the entire height of rect doesn't fit in compare, - * skip this rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_Y) && - (compare_rect->y > rect->y || - compare_rect->y + compare_rect->height < rect->y + rect->height)) - continue; - - /* Determine maximal overlap amount between rect & compare_rect */ - maximal_overlap_amount_for_compare = - MIN (rect->width, compare_rect->width) * - MIN (rect->height, compare_rect->height); - - /* Determine distance necessary to put rect into compare_rect */ - dist_to_compare = 0; - if (compare_rect->x > rect->x) - dist_to_compare += compare_rect->x - rect->x; - if (compare_rect->x + compare_rect->width < rect->x + rect->width) - dist_to_compare += (rect->x + rect->width) - - (compare_rect->x + compare_rect->width); - if (compare_rect->y > rect->y) - dist_to_compare += compare_rect->y - rect->y; - if (compare_rect->y + compare_rect->height < rect->y + rect->height) - dist_to_compare += (rect->y + rect->height) - - (compare_rect->y + compare_rect->height); - - /* See if this is the best rect so far */ - if ((maximal_overlap_amount_for_compare > best_overlap) || - (maximal_overlap_amount_for_compare == best_overlap && - dist_to_compare < shortest_distance)) - { - best_rect = compare_rect; - best_overlap = maximal_overlap_amount_for_compare; - shortest_distance = dist_to_compare; - } - } - - /* Shove rect appropriately */ - if (best_rect == NULL) - meta_warning ("No rect to shove into found!\n"); - else - { - /* Extra precaution with checking fixed direction shouldn't be needed - * due to logic above, but it shouldn't hurt either. - */ - if (!(fixed_directions & FIXED_DIRECTION_X)) - { - /* Shove to the right, if needed */ - if (best_rect->x > rect->x) - rect->x = best_rect->x; - - /* Shove to the left, if needed */ - if (best_rect->x + best_rect->width < rect->x + rect->width) - rect->x = (best_rect->x + best_rect->width) - rect->width; - } - - /* Extra precaution with checking fixed direction shouldn't be needed - * due to logic above, but it shouldn't hurt either. - */ - if (!(fixed_directions & FIXED_DIRECTION_Y)) - { - /* Shove down, if needed */ - if (best_rect->y > rect->y) - rect->y = best_rect->y; - - /* Shove up, if needed */ - if (best_rect->y + best_rect->height < rect->y + rect->height) - rect->y = (best_rect->y + best_rect->height) - rect->height; - } - } -} - -void -meta_rectangle_find_linepoint_closest_to_point (double x1, - double y1, - double x2, - double y2, - double px, - double py, - double *valx, - double *valy) -{ - /* I'll use the shorthand rx, ry for the return values, valx & valy. - * Now, we need (rx,ry) to be on the line between (x1,y1) and (x2,y2). - * For that to happen, we first need the slope of the line from (x1,y1) - * to (rx,ry) must match the slope of (x1,y1) to (x2,y2), i.e.: - * (ry-y1) (y2-y1) - * ------- = ------- - * (rx-x1) (x2-x1) - * If x1==x2, though, this gives divide by zero errors, so we want to - * rewrite the equation by multiplying both sides by (rx-x1)*(x2-x1): - * (ry-y1)(x2-x1) = (y2-y1)(rx-x1) - * This is a valid requirement even when x1==x2 (when x1==x2, this latter - * equation will basically just mean that rx must be equal to both x1 and - * x2) - * - * The other requirement that we have is that the line from (rx,ry) to - * (px,py) must be perpendicular to the line from (x1,y1) to (x2,y2). So - * we just need to get a vector in the direction of each line, take the - * dot product of the two, and ensure that the result is 0: - * (rx-px)*(x2-x1) + (ry-py)*(y2-y1) = 0. - * - * This gives us two equations and two unknowns: - * - * (ry-y1)(x2-x1) = (y2-y1)(rx-x1) - * (rx-px)*(x2-x1) + (ry-py)*(y2-y1) = 0. - * - * This particular pair of equations is always solvable so long as - * (x1,y1) and (x2,y2) are not the same point (and note that anyone who - * calls this function that way is braindead because it means that they - * really didn't specify a line after all). However, the caller should - * be careful to avoid making (x1,y1) and (x2,y2) too close (e.g. like - * 10^{-8} apart in each coordinate), otherwise roundoff error could - * cause issues. Solving these equations by hand (or using Maple(TM) or - * Mathematica(TM) or whatever) results in slightly messy expressions, - * but that's all the below few lines do. - */ - - double diffx, diffy, den; - diffx = x2 - x1; - diffy = y2 - y1; - den = diffx * diffx + diffy * diffy; - - *valx = (py * diffx * diffy + px * diffx * diffx + - y2 * x1 * diffy - y1 * x2 * diffy) / den; - *valy = (px * diffx * diffy + py * diffy * diffy + - x2 * y1 * diffx - x1 * y2 * diffx) / den; -} - -/***************************************************************************/ -/* */ -/* Switching gears to code for edges instead of just rectangles */ -/* */ -/***************************************************************************/ - -gboolean -meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge) -{ - /* The reason for the usage of <= below instead of < is because we are - * interested in in-the-way-or-adject'ness. So, a left (i.e. vertical - * edge) occupying y positions 0-9 (which has a y of 0 and a height of - * 10) and a rectangle with top at y=10 would be considered to "align" by - * this function. - */ - switch (edge->side_type) - { - case META_DIRECTION_LEFT: - case META_DIRECTION_RIGHT: - return BOX_TOP (*rect) <= BOX_BOTTOM (edge->rect) && - BOX_TOP (edge->rect) <= BOX_BOTTOM (*rect); - case META_DIRECTION_TOP: - case META_DIRECTION_BOTTOM: - return BOX_LEFT (*rect) <= BOX_RIGHT (edge->rect) && - BOX_LEFT (edge->rect) <= BOX_RIGHT (*rect); - default: - g_assert_not_reached (); - } -} - -static GList* -get_rect_minus_overlap (const GList *rect_in_list, - MetaRectangle *overlap) -{ - MetaRectangle *temp; - MetaRectangle *rect = rect_in_list->data; - GList *ret = NULL; - - if (BOX_LEFT (*rect) < BOX_LEFT (*overlap)) - { - temp = g_new (MetaRectangle, 1); - *temp = *rect; - temp->width = BOX_LEFT (*overlap) - BOX_LEFT (*rect); - ret = g_list_prepend (ret, temp); - } - if (BOX_RIGHT (*rect) > BOX_RIGHT (*overlap)) - { - temp = g_new (MetaRectangle, 1); - *temp = *rect; - temp->x = BOX_RIGHT (*overlap); - temp->width = BOX_RIGHT (*rect) - BOX_RIGHT (*overlap); - ret = g_list_prepend (ret, temp); - } - if (BOX_TOP (*rect) < BOX_TOP (*overlap)) - { - temp = g_new (MetaRectangle, 1); - temp->x = overlap->x; - temp->width = overlap->width; - temp->y = BOX_TOP (*rect); - temp->height = BOX_TOP (*overlap) - BOX_TOP (*rect); - ret = g_list_prepend (ret, temp); - } - if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*overlap)) - { - temp = g_new (MetaRectangle, 1); - temp->x = overlap->x; - temp->width = overlap->width; - temp->y = BOX_BOTTOM (*overlap); - temp->height = BOX_BOTTOM (*rect) - BOX_BOTTOM (*overlap); - ret = g_list_prepend (ret, temp); - } - - return ret; -} - -static GList* -replace_rect_with_list (GList *old_element, - GList *new_list) -{ - GList *ret; - g_assert (old_element != NULL); - - if (!new_list) - { - /* If there is no new list, just remove the old_element */ - ret = g_list_remove_link (old_element, old_element); - } - else - { - /* Fix up the prev and next pointers everywhere */ - ret = new_list; - if (old_element->prev) - { - old_element->prev->next = new_list; - new_list->prev = old_element->prev; - } - if (old_element->next) - { - GList *tmp = g_list_last (new_list); - old_element->next->prev = tmp; - tmp->next = old_element->next; - } - } - - /* Free the old_element and return the appropriate "next" point */ - g_free (old_element->data); - g_list_free_1 (old_element); - return ret; -} - -/* Make a copy of the strut list, make sure that copy only contains parts - * of the old_struts that intersect with the region rect, and then do some - * magic to make all the new struts disjoint (okay, we we break up struts - * that aren't disjoint in a way that the overlapping part is only included - * once, so it's not really magic...). - */ -static GList* -get_disjoint_strut_rect_list_in_region (const GSList *old_struts, - const MetaRectangle *region) -{ - GList *strut_rects; - GList *tmp; - - /* First, copy the list */ - strut_rects = NULL; - while (old_struts) - { - MetaRectangle *cur = &((MetaStrut*)old_struts->data)->rect; - MetaRectangle *copy = g_new (MetaRectangle, 1); - *copy = *cur; - if (meta_rectangle_intersect (copy, region, copy)) - strut_rects = g_list_prepend (strut_rects, copy); - else - g_free (copy); - - old_struts = old_struts->next; - } - - /* Now, loop over the list and check for intersections, fixing things up - * where they do intersect. - */ - tmp = strut_rects; - while (tmp) - { - GList *compare; - - MetaRectangle *cur = tmp->data; - - compare = tmp->next; - while (compare) - { - MetaRectangle *comp = compare->data; - MetaRectangle overlap; - - if (meta_rectangle_intersect (cur, comp, &overlap)) - { - /* Get a list of rectangles for each strut that don't overlap - * the intersection region. - */ - GList *cur_leftover = get_rect_minus_overlap (tmp, &overlap); - GList *comp_leftover = get_rect_minus_overlap (compare, &overlap); - - /* Add the intersection region to cur_leftover */ - MetaRectangle *overlap_allocated = g_new (MetaRectangle, 1); - *overlap_allocated = overlap; - cur_leftover = g_list_prepend (cur_leftover, overlap_allocated); - - /* Fix up tmp, compare, and cur -- maybe struts too */ - if (strut_rects == tmp) - { - strut_rects = replace_rect_with_list (tmp, cur_leftover); - tmp = strut_rects; - } - else - tmp = replace_rect_with_list (tmp, cur_leftover); - compare = replace_rect_with_list (compare, comp_leftover); - - if (compare == NULL) - break; - - cur = tmp->data; - } - - compare = compare->next; - } - - tmp = tmp->next; - } - - return strut_rects; -} - -gint -meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b) -{ - const MetaEdge *a_edge_rect = (gconstpointer) a; - const MetaEdge *b_edge_rect = (gconstpointer) b; - int a_compare, b_compare; - - /* Edges must be both vertical or both horizontal, or it doesn't make - * sense to compare them. - */ - g_assert ((a_edge_rect->rect.width == 0 && b_edge_rect->rect.width == 0) || - (a_edge_rect->rect.height == 0 && b_edge_rect->rect.height == 0)); - - a_compare = b_compare = 0; /* gcc-3.4.2 sucks at figuring initialized'ness */ - - if (a_edge_rect->side_type == META_DIRECTION_LEFT || - a_edge_rect->side_type == META_DIRECTION_RIGHT) - { - a_compare = a_edge_rect->rect.x; - b_compare = b_edge_rect->rect.x; - if (a_compare == b_compare) - { - a_compare = a_edge_rect->rect.y; - b_compare = b_edge_rect->rect.y; - } - } - else if (a_edge_rect->side_type == META_DIRECTION_TOP || - a_edge_rect->side_type == META_DIRECTION_BOTTOM) - { - a_compare = a_edge_rect->rect.y; - b_compare = b_edge_rect->rect.y; - if (a_compare == b_compare) - { - a_compare = a_edge_rect->rect.x; - b_compare = b_edge_rect->rect.x; - } - } - else - g_assert ("Some idiot wanted to sort sides of different types.\n"); - - return a_compare - b_compare; /* positive value denotes a > b ... */ -} - -/* To make things easily testable, provide a nice way of sorting edges */ -gint -meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b) -{ - const MetaEdge *a_edge_rect = (gconstpointer) a; - const MetaEdge *b_edge_rect = (gconstpointer) b; - - int a_compare, b_compare; - - a_compare = a_edge_rect->side_type; - b_compare = b_edge_rect->side_type; - - if (a_compare == b_compare) - return meta_rectangle_edge_cmp_ignore_type (a, b); - - return a_compare - b_compare; /* positive value denotes a > b ... */ -} - -/* Determine whether two given edges overlap */ -static gboolean -edges_overlap (const MetaEdge *edge1, - const MetaEdge *edge2) -{ - if (edge1->rect.width == 0 && edge2->rect.width == 0) - { - return meta_rectangle_vert_overlap (&edge1->rect, &edge2->rect) && - edge1->rect.x == edge2->rect.x; - } - else if (edge1->rect.height == 0 && edge2->rect.height == 0) - { - return meta_rectangle_horiz_overlap (&edge1->rect, &edge2->rect) && - edge1->rect.y == edge2->rect.y; - } - else - { - return FALSE; - } -} - -static gboolean -rectangle_and_edge_intersection (const MetaRectangle *rect, - const MetaEdge *edge, - MetaEdge *overlap, - int *handle_type) -{ - const MetaRectangle *rect2 = &edge->rect; - MetaRectangle *result = &overlap->rect; - gboolean intersect = TRUE; - - /* We don't know how to set these, so set them to invalid values */ - overlap->edge_type = -1; - overlap->side_type = -1; - - /* Figure out what the intersection is */ - result->x = MAX (rect->x, rect2->x); - result->y = MAX (rect->y, rect2->y); - result->width = MIN (BOX_RIGHT (*rect), BOX_RIGHT (*rect2)) - result->x; - result->height = MIN (BOX_BOTTOM (*rect), BOX_BOTTOM (*rect2)) - result->y; - - /* Find out if the intersection is empty; have to do it this way since - * edges have a thickness of 0 - */ - if ((result->width < 0 || result->height < 0) || - (result->width == 0 && result->height == 0)) - { - result->width = 0; - result->height = 0; - intersect = FALSE; - } - else - { - /* Need to figure out the handle_type, a somewhat weird quantity: - * 0 - overlap is in middle of rect - * -1 - overlap is at the side of rect, and is on the opposite side - * of rect than the edge->side_type side - * 1 - overlap is at the side of rect, and the side of rect it is - * on is the edge->side_type side - */ - switch (edge->side_type) - { - case META_DIRECTION_LEFT: - if (result->x == rect->x) - *handle_type = 1; - else if (result->x == BOX_RIGHT (*rect)) - *handle_type = -1; - else - *handle_type = 0; - break; - case META_DIRECTION_RIGHT: - if (result->x == rect->x) - *handle_type = -1; - else if (result->x == BOX_RIGHT (*rect)) - *handle_type = 1; - else - *handle_type = 0; - break; - case META_DIRECTION_TOP: - if (result->y == rect->y) - *handle_type = 1; - else if (result->y == BOX_BOTTOM (*rect)) - *handle_type = -1; - else - *handle_type = 0; - break; - case META_DIRECTION_BOTTOM: - if (result->y == rect->y) - *handle_type = -1; - else if (result->y == BOX_BOTTOM (*rect)) - *handle_type = 1; - else - *handle_type = 0; - break; - default: - g_assert_not_reached (); - } - } - return intersect; -} - -/* Add all edges of the given rect to cur_edges and return the result. If - * rect_is_internal is false, the side types are switched (LEFT<->RIGHT and - * TOP<->BOTTOM). - */ -static GList* -add_edges (GList *cur_edges, - const MetaRectangle *rect, - gboolean rect_is_internal) -{ - MetaEdge *temp_edge; - int i; - - for (i=0; i<4; i++) - { - temp_edge = g_new (MetaEdge, 1); - temp_edge->rect = *rect; - switch (i) - { - case 0: - temp_edge->side_type = - rect_is_internal ? META_DIRECTION_LEFT : META_DIRECTION_RIGHT; - temp_edge->rect.width = 0; - break; - case 1: - temp_edge->side_type = - rect_is_internal ? META_DIRECTION_RIGHT : META_DIRECTION_LEFT; - temp_edge->rect.x += temp_edge->rect.width; - temp_edge->rect.width = 0; - break; - case 2: - temp_edge->side_type = - rect_is_internal ? META_DIRECTION_TOP : META_DIRECTION_BOTTOM; - temp_edge->rect.height = 0; - break; - case 3: - temp_edge->side_type = - rect_is_internal ? META_DIRECTION_BOTTOM : META_DIRECTION_TOP; - temp_edge->rect.y += temp_edge->rect.height; - temp_edge->rect.height = 0; - break; - } - temp_edge->edge_type = META_EDGE_SCREEN; - cur_edges = g_list_prepend (cur_edges, temp_edge); - } - - return cur_edges; -} - -/* Remove any part of old_edge that intersects remove and add any resulting - * edges to cur_list. Return cur_list when finished. - */ -static GList* -split_edge (GList *cur_list, - const MetaEdge *old_edge, - const MetaEdge *remove) -{ - MetaEdge *temp_edge; - switch (old_edge->side_type) - { - case META_DIRECTION_LEFT: - case META_DIRECTION_RIGHT: - g_assert (meta_rectangle_vert_overlap (&old_edge->rect, &remove->rect)); - if (BOX_TOP (old_edge->rect) < BOX_TOP (remove->rect)) - { - temp_edge = g_new (MetaEdge, 1); - *temp_edge = *old_edge; - temp_edge->rect.height = BOX_TOP (remove->rect) - - BOX_TOP (old_edge->rect); - cur_list = g_list_prepend (cur_list, temp_edge); - } - if (BOX_BOTTOM (old_edge->rect) > BOX_BOTTOM (remove->rect)) - { - temp_edge = g_new (MetaEdge, 1); - *temp_edge = *old_edge; - temp_edge->rect.y = BOX_BOTTOM (remove->rect); - temp_edge->rect.height = BOX_BOTTOM (old_edge->rect) - - BOX_BOTTOM (remove->rect); - cur_list = g_list_prepend (cur_list, temp_edge); - } - break; - case META_DIRECTION_TOP: - case META_DIRECTION_BOTTOM: - g_assert (meta_rectangle_horiz_overlap (&old_edge->rect, &remove->rect)); - if (BOX_LEFT (old_edge->rect) < BOX_LEFT (remove->rect)) - { - temp_edge = g_new (MetaEdge, 1); - *temp_edge = *old_edge; - temp_edge->rect.width = BOX_LEFT (remove->rect) - - BOX_LEFT (old_edge->rect); - cur_list = g_list_prepend (cur_list, temp_edge); - } - if (BOX_RIGHT (old_edge->rect) > BOX_RIGHT (remove->rect)) - { - temp_edge = g_new (MetaEdge, 1); - *temp_edge = *old_edge; - temp_edge->rect.x = BOX_RIGHT (remove->rect); - temp_edge->rect.width = BOX_RIGHT (old_edge->rect) - - BOX_RIGHT (remove->rect); - cur_list = g_list_prepend (cur_list, temp_edge); - } - break; - default: - g_assert_not_reached (); - } - - return cur_list; -} - -/* Split up edge and remove preliminary edges from strut_edges depending on - * if and how rect and edge intersect. - */ -static void -fix_up_edges (MetaRectangle *rect, MetaEdge *edge, - GList **strut_edges, GList **edge_splits, - gboolean *edge_needs_removal) -{ - MetaEdge overlap; - int handle_type; - - if (!rectangle_and_edge_intersection (rect, edge, &overlap, &handle_type)) - return; - - if (handle_type == 0 || handle_type == 1) - { - /* Put the result of removing overlap from edge into edge_splits */ - *edge_splits = split_edge (*edge_splits, edge, &overlap); - *edge_needs_removal = TRUE; - } - - if (handle_type == -1 || handle_type == 1) - { - /* Remove the overlap from strut_edges */ - /* First, loop over the edges of the strut */ - GList *tmp = *strut_edges; - while (tmp) - { - MetaEdge *cur = tmp->data; - /* If this is the edge that overlaps, then we need to split it */ - if (edges_overlap (cur, &overlap)) - { - GList *delete_me = tmp; - - /* Split this edge into some new ones */ - *strut_edges = split_edge (*strut_edges, cur, &overlap); - - /* Delete the old one */ - tmp = tmp->next; - g_free (cur); - *strut_edges = g_list_delete_link (*strut_edges, delete_me); - } - else - tmp = tmp->next; - } - } -} - -/* This function removes intersections of edges with the rectangles from the - * list of edges. - */ -GList* -meta_rectangle_remove_intersections_with_boxes_from_edges ( - GList *edges, - const GSList *rectangles) -{ - const GSList *rect_iter; - const int opposing = 1; - - /* Now remove all intersections of rectangles with the edge list */ - rect_iter = rectangles; - while (rect_iter) - { - MetaRectangle *rect = rect_iter->data; - GList *edge_iter = edges; - while (edge_iter) - { - MetaEdge *edge = edge_iter->data; - MetaEdge overlap; - int handle; - gboolean edge_iter_advanced = FALSE; - - /* If this edge overlaps with this rect... */ - if (rectangle_and_edge_intersection (rect, edge, &overlap, &handle)) - { - - /* "Intersections" where the edges touch but are opposite - * sides (e.g. a left edge against the right edge) should not - * be split. Note that the comments in - * rectangle_and_edge_intersection() say that opposing edges - * occur when handle is -1, BUT you need to remember that we - * treat the left side of a window as a right edge because - * it's what the right side of the window being moved should - * be-resisted-by/snap-to. So opposing is really 1. Anyway, - * we just keep track of it in the opposing constant set up - * above and if handle isn't equal to that, then we know the - * edge should be split. - */ - if (handle != opposing) - { - /* Keep track of this edge so we can delete it below */ - GList *delete_me = edge_iter; - edge_iter = edge_iter->next; - edge_iter_advanced = TRUE; - - /* Split the edge and add the result to beginning of edges */ - edges = split_edge (edges, edge, &overlap); - - /* Now free the edge... */ - g_free (edge); - edges = g_list_delete_link (edges, delete_me); - } - } - - if (!edge_iter_advanced) - edge_iter = edge_iter->next; - } - - rect_iter = rect_iter->next; - } - - return edges; -} - -/* This function is trying to find all the edges of an onscreen region. */ -GList* -meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect, - const GSList *all_struts) -{ - GList *ret; - GList *fixed_strut_rects; - GList *edge_iter; - const GList *strut_rect_iter; - - /* The algorithm is basically as follows: - * Make sure the struts are disjoint - * Initialize the edge_set to the edges of basic_rect - * Foreach strut: - * Put together a preliminary new edge from the edges of the strut - * Foreach edge in edge_set: - * - Split the edge if it is partially contained inside the strut - * - If the edge matches an edge of the strut (i.e. a strut just - * against the edge of the screen or a not-next-to-edge-of-screen - * strut adjacent to another), then both the edge from the - * edge_set and the preliminary edge for the strut will need to - * be split - * Add any remaining "preliminary" strut edges to the edge_set - */ - - /* Make sure the struts are disjoint */ - fixed_strut_rects = - get_disjoint_strut_rect_list_in_region (all_struts, basic_rect); - - /* Start off the list with the edges of basic_rect */ - ret = add_edges (NULL, basic_rect, TRUE); - - strut_rect_iter = fixed_strut_rects; - while (strut_rect_iter) - { - MetaRectangle *strut_rect = (MetaRectangle*) strut_rect_iter->data; - - /* Get the new possible edges we may need to add from the strut */ - GList *new_strut_edges = add_edges (NULL, strut_rect, FALSE); - - edge_iter = ret; - while (edge_iter) - { - MetaEdge *cur_edge = edge_iter->data; - GList *splits_of_cur_edge = NULL; - gboolean edge_needs_removal = FALSE; - - fix_up_edges (strut_rect, cur_edge, - &new_strut_edges, &splits_of_cur_edge, - &edge_needs_removal); - - if (edge_needs_removal) - { - /* Delete the old edge */ - GList *delete_me = edge_iter; - edge_iter = edge_iter->next; - g_free (cur_edge); - ret = g_list_delete_link (ret, delete_me); - - /* Add the new split parts of the edge */ - ret = g_list_concat (splits_of_cur_edge, ret); - } - else - { - edge_iter = edge_iter->next; - } - - /* edge_iter was already advanced above */ - } - - ret = g_list_concat (new_strut_edges, ret); - strut_rect_iter = strut_rect_iter->next; - } - - /* Sort the list */ - ret = g_list_sort (ret, meta_rectangle_edge_cmp); - - /* Free the fixed struts list */ - meta_rectangle_free_list_and_elements (fixed_strut_rects); - - return ret; -} - -GList* -meta_rectangle_find_nonintersected_xinerama_edges ( - const GList *xinerama_rects, - const GSList *all_struts) -{ - /* This function cannot easily be merged with - * meta_rectangle_find_onscreen_edges() because real screen edges - * and strut edges both are of the type "there ain't anything - * immediately on the other side"; xinerama edges are different. - */ - GList *ret; - const GList *cur; - GSList *temp_rects; - - /* Initialize the return list to be empty */ - ret = NULL; - - /* start of ret with all the edges of xineramas that are adjacent to - * another xinerama. - */ - cur = xinerama_rects; - while (cur) - { - MetaRectangle *cur_rect = cur->data; - const GList *compare = xinerama_rects; - while (compare) - { - MetaRectangle *compare_rect = compare->data; - - /* Check if cur might be horizontally adjacent to compare */ - if (meta_rectangle_vert_overlap(cur_rect, compare_rect)) - { - MetaDirection side_type; - int y = MAX (cur_rect->y, compare_rect->y); - int height = MIN (BOX_BOTTOM (*cur_rect) - y, - BOX_BOTTOM (*compare_rect) - y); - int width = 0; - int x; - - if (BOX_LEFT (*cur_rect) == BOX_RIGHT (*compare_rect)) - { - /* compare_rect is to the left of cur_rect */ - x = BOX_LEFT (*cur_rect); - side_type = META_DIRECTION_LEFT; - } - else if (BOX_RIGHT (*cur_rect) == BOX_LEFT (*compare_rect)) - { - /* compare_rect is to the right of cur_rect */ - x = BOX_RIGHT (*cur_rect); - side_type = META_DIRECTION_RIGHT; - } - else - /* These rectangles aren't adjacent after all */ - x = INT_MIN; - - /* If the rectangles really are adjacent */ - if (x != INT_MIN) - { - /* We need a left edge for the xinerama on the right, and - * a right edge for the xinerama on the left. Just fill - * up the edges and stick 'em on the list. - */ - MetaEdge *new_edge = g_new (MetaEdge, 1); - - new_edge->rect = meta_rect (x, y, width, height); - new_edge->side_type = side_type; - new_edge->edge_type = META_EDGE_XINERAMA; - - ret = g_list_prepend (ret, new_edge); - } - } - - /* Check if cur might be vertically adjacent to compare */ - if (meta_rectangle_horiz_overlap(cur_rect, compare_rect)) - { - MetaDirection side_type; - int x = MAX (cur_rect->x, compare_rect->x); - int width = MIN (BOX_RIGHT (*cur_rect) - x, - BOX_RIGHT (*compare_rect) - x); - int height = 0; - int y; - - if (BOX_TOP (*cur_rect) == BOX_BOTTOM (*compare_rect)) - { - /* compare_rect is to the top of cur_rect */ - y = BOX_TOP (*cur_rect); - side_type = META_DIRECTION_TOP; - } - else if (BOX_BOTTOM (*cur_rect) == BOX_TOP (*compare_rect)) - { - /* compare_rect is to the bottom of cur_rect */ - y = BOX_BOTTOM (*cur_rect); - side_type = META_DIRECTION_BOTTOM; - } - else - /* These rectangles aren't adjacent after all */ - y = INT_MIN; - - /* If the rectangles really are adjacent */ - if (y != INT_MIN) - { - /* We need a top edge for the xinerama on the bottom, and - * a bottom edge for the xinerama on the top. Just fill - * up the edges and stick 'em on the list. - */ - MetaEdge *new_edge = g_new (MetaEdge, 1); - - new_edge->rect = meta_rect (x, y, width, height); - new_edge->side_type = side_type; - new_edge->edge_type = META_EDGE_XINERAMA; - - ret = g_list_prepend (ret, new_edge); - } - } - - compare = compare->next; - } - cur = cur->next; - } - - temp_rects = NULL; - for (; all_struts; all_struts = all_struts->next) - temp_rects = g_slist_prepend (temp_rects, - &((MetaStrut*)all_struts->data)->rect); - ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret, - temp_rects); - g_slist_free (temp_rects); - - /* Sort the list */ - ret = g_list_sort (ret, meta_rectangle_edge_cmp); - - return ret; -} diff --git a/src/core/constraints.c b/src/core/constraints.c deleted file mode 100644 index 800b293a..00000000 --- a/src/core/constraints.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity size/position constraints */ - -/* - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2005, 2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "constraints.h" -#include "workspace.h" -#include "place.h" - -#include <stdlib.h> -#include <math.h> - -#if 0 - // This is the short and sweet version of how to hack on this file; see - // doc/how-constraints-works.txt for the gory details. The basics of - // understanding this file can be shown by the steps needed to add a new - // constraint, which are: - // 1) Add a new entry in the ConstraintPriority enum; higher values - // have higher priority - // 2) Write a new function following the format of the example below, - // "constrain_whatever". - // 3) Add your function to the all_constraints and all_constraint_names - // arrays (the latter of which is for debugging purposes) - // - // An example constraint function, constrain_whatever: - // - // /* constrain_whatever does the following: - // * Quits (returning true) if priority is higher than PRIORITY_WHATEVER - // * If check_only is TRUE - // * Returns whether the constraint is satisfied or not - // * otherwise - // * Enforces the constraint - // * Note that the value of PRIORITY_WHATEVER is centralized with the - // * priorities of other constraints in the definition of ConstrainPriority - // * for easier maintenance and shuffling of priorities. - // */ - // static gboolean - // constrain_whatever (MetaWindow *window, - // ConstraintInfo *info, - // ConstraintPriority priority, - // gboolean check_only) - // { - // if (priority > PRIORITY_WHATEVER) - // return TRUE; - // - // /* Determine whether constraint applies; note that if the constraint - // * cannot possibly be satisfied, constraint_applies should be set to - // * false. If we don't do this, all constraints with a lesser priority - // * will be dropped along with this one, and we'd rather apply as many as - // * possible. - // */ - // if (!constraint_applies) - // return TRUE; - // - // /* Determine whether constraint is already satisfied; if we're only - // * checking the status of whether the constraint is satisfied, we end - // * here. - // */ - // if (check_only || constraint_already_satisfied) - // return constraint_already_satisfied; - // - // /* Enforce constraints */ - // return TRUE; /* Note that we exited early if check_only is FALSE; also, - // * we know we can return TRUE here because we exited early - // * if the constraint could not be satisfied; not that the - // * return value is heeded in this case... - // */ - // } -#endif - -typedef enum -{ - PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */ - PRIORITY_ASPECT_RATIO = 0, - PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA = 0, - PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1, - PRIORITY_SIZE_HINTS_INCREMENTS = 1, - PRIORITY_MAXIMIZATION = 2, - PRIORITY_FULLSCREEN = 2, - PRIORITY_SIZE_HINTS_LIMITS = 3, - PRIORITY_TITLEBAR_VISIBLE = 4, - PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4, - PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */ -} ConstraintPriority; - -typedef enum -{ - ACTION_MOVE, - ACTION_RESIZE, - ACTION_MOVE_AND_RESIZE -} ActionType; - -typedef struct -{ - MetaRectangle orig; - MetaRectangle current; - MetaFrameGeometry *fgeom; - ActionType action_type; - gboolean is_user_action; - - /* I know that these two things probably look similar at first, but they - * have much different uses. See doc/how-constraints-works.txt for for - * explanation of the differences and similarity between resize_gravity - * and fixed_directions - */ - int resize_gravity; - FixedDirections fixed_directions; - - /* work_area_xinerama - current xinerama region minus struts - * entire_xinerama - current xienrama, including strut regions - */ - MetaRectangle work_area_xinerama; - MetaRectangle entire_xinerama; - - /* Spanning rectangles for the non-covered (by struts) region of the - * screen and also for just the current xinerama - */ - GList *usable_screen_region; - GList *usable_xinerama_region; -} ConstraintInfo; - -static gboolean constrain_maximization (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_fullscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_size_increments (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_size_limits (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_aspect_ratio (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_to_single_xinerama (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_fully_onscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_titlebar_visible (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_partially_onscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); - -static void setup_constraint_info (ConstraintInfo *info, - MetaWindow *window, - MetaFrameGeometry *orig_fgeom, - MetaMoveResizeFlags flags, - int resize_gravity, - const MetaRectangle *orig, - MetaRectangle *new); -static void place_window_if_needed (MetaWindow *window, - ConstraintInfo *info); -static void update_onscreen_requirements (MetaWindow *window, - ConstraintInfo *info); -static void extend_by_frame (MetaRectangle *rect, - const MetaFrameGeometry *fgeom); -static void unextend_by_frame (MetaRectangle *rect, - const MetaFrameGeometry *fgeom); -static inline void get_size_limits (const MetaWindow *window, - const MetaFrameGeometry *fgeom, - gboolean include_frame, - MetaRectangle *min_size, - MetaRectangle *max_size); - -typedef gboolean (* ConstraintFunc) (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); - -typedef struct { - ConstraintFunc func; - const char* name; -} Constraint; - -static const Constraint all_constraints[] = { - {constrain_maximization, "constrain_maximization"}, - {constrain_fullscreen, "constrain_fullscreen"}, - {constrain_size_increments, "constrain_size_increments"}, - {constrain_size_limits, "constrain_size_limits"}, - {constrain_aspect_ratio, "constrain_aspect_ratio"}, - {constrain_to_single_xinerama, "constrain_to_single_xinerama"}, - {constrain_fully_onscreen, "constrain_fully_onscreen"}, - {constrain_titlebar_visible, "constrain_titlebar_visible"}, - {constrain_partially_onscreen, "constrain_partially_onscreen"}, - {NULL, NULL} -}; - -static gboolean -do_all_constraints (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - const Constraint *constraint; - gboolean satisfied; - - constraint = &all_constraints[0]; - satisfied = TRUE; - while (constraint->func != NULL) - { - satisfied = satisfied && - (*constraint->func) (window, info, priority, check_only); - - if (!check_only) - { - /* Log how the constraint modified the position */ - meta_topic (META_DEBUG_GEOMETRY, - "info->current is %d,%d +%d,%d after %s\n", - info->current.x, info->current.y, - info->current.width, info->current.height, - constraint->name); - } - else if (!satisfied) - { - /* Log which constraint was not satisfied */ - meta_topic (META_DEBUG_GEOMETRY, - "constraint %s not satisfied.\n", - constraint->name); - return FALSE; - } - ++constraint; - } - - return TRUE; -} - -void -meta_window_constrain (MetaWindow *window, - MetaFrameGeometry *orig_fgeom, - MetaMoveResizeFlags flags, - int resize_gravity, - const MetaRectangle *orig, - MetaRectangle *new) -{ - ConstraintInfo info; - ConstraintPriority priority = PRIORITY_MINIMUM; - gboolean satisfied = FALSE; - - /* WARNING: orig and new specify positions and sizes of the inner window, - * not the outer. This is a common gotcha since half the constraints - * deal with inner window position/size and half deal with outer. See - * doc/how-constraints-works.txt for more information. - */ - meta_topic (META_DEBUG_GEOMETRY, - "Constraining %s in move from %d,%d %dx%d to %d,%d %dx%d\n", - window->desc, - orig->x, orig->y, orig->width, orig->height, - new->x, new->y, new->width, new->height); - - setup_constraint_info (&info, - window, - orig_fgeom, - flags, - resize_gravity, - orig, - new); - place_window_if_needed (window, &info); - - while (!satisfied && priority <= PRIORITY_MAXIMUM) { - gboolean check_only = TRUE; - - /* Individually enforce all the high-enough priority constraints */ - do_all_constraints (window, &info, priority, !check_only); - - /* Check if all high-enough priority constraints are simultaneously - * satisfied - */ - satisfied = do_all_constraints (window, &info, priority, check_only); - - /* Drop the least important constraints if we can't satisfy them all */ - priority++; - } - - /* Make sure we use the constrained position */ - *new = info.current; - - /* We may need to update window->require_fully_onscreen, - * window->require_on_single_xinerama, and perhaps other quantities - * if this was a user move or user move-and-resize operation. - */ - update_onscreen_requirements (window, &info); - - /* Ew, what an ugly way to do things. Destructors (in a real OOP language, - * not gobject-style--gobject would be more pain than it's worth) or - * smart pointers would be so much nicer here. *shrug* - */ - if (!orig_fgeom) - g_free (info.fgeom); -} - -static void -setup_constraint_info (ConstraintInfo *info, - MetaWindow *window, - MetaFrameGeometry *orig_fgeom, - MetaMoveResizeFlags flags, - int resize_gravity, - const MetaRectangle *orig, - MetaRectangle *new) -{ - const MetaXineramaScreenInfo *xinerama_info; - MetaWorkspace *cur_workspace; - - info->orig = *orig; - info->current = *new; - - /* Create a fake frame geometry if none really exists */ - if (orig_fgeom && !window->fullscreen) - info->fgeom = orig_fgeom; - else - info->fgeom = g_new0 (MetaFrameGeometry, 1); - - if (flags & META_IS_MOVE_ACTION && flags & META_IS_RESIZE_ACTION) - info->action_type = ACTION_MOVE_AND_RESIZE; - else if (flags & META_IS_RESIZE_ACTION) - info->action_type = ACTION_RESIZE; - else if (flags & META_IS_MOVE_ACTION) - info->action_type = ACTION_MOVE; - else - g_error ("BAD, BAD developer! No treat for you! (Fix your calls to " - "meta_window_move_resize_internal()).\n"); - - info->is_user_action = (flags & META_IS_USER_ACTION); - - info->resize_gravity = resize_gravity; - - /* FIXME: fixed_directions might be more sane if we (a) made it - * depend on the grab_op type instead of current amount of movement - * (thus implying that it only has effect when user_action is true, - * and (b) ignored it for aspect ratio windows -- at least in those - * cases where both directions do actually change size. - */ - info->fixed_directions = FIXED_DIRECTION_NONE; - /* If x directions don't change but either y direction does */ - if ( orig->x == new->x && orig->x + orig->width == new->x + new->width && - (orig->y != new->y || orig->y + orig->height != new->y + new->height)) - { - info->fixed_directions = FIXED_DIRECTION_X; - } - /* If y directions don't change but either x direction does */ - if ( orig->y == new->y && orig->y + orig->height == new->y + new->height && - (orig->x != new->x || orig->x + orig->width != new->x + new->width )) - { - info->fixed_directions = FIXED_DIRECTION_Y; - } - /* The point of fixed directions is just that "move to nearest valid - * position" is sometimes a poorer choice than "move to nearest - * valid position but only change this coordinate" for windows the - * user is explicitly moving. This isn't ever true for things that - * aren't explicit user interaction, though, so just clear it out. - */ - if (!info->is_user_action) - info->fixed_directions = FIXED_DIRECTION_NONE; - - xinerama_info = - meta_screen_get_xinerama_for_rect (window->screen, &info->current); - meta_window_get_work_area_for_xinerama (window, - xinerama_info->number, - &info->work_area_xinerama); - - if (!window->fullscreen || window->fullscreen_monitors[0] == -1) - { - info->entire_xinerama = xinerama_info->rect; - } - else - { - int i = 0; - long monitor; - - monitor = window->fullscreen_monitors[i]; - info->entire_xinerama = - window->screen->xinerama_infos[monitor].rect; - for (i = 1; i <= 3; i++) - { - monitor = window->fullscreen_monitors[i]; - meta_rectangle_union (&info->entire_xinerama, - &window->screen->xinerama_infos[monitor].rect, - &info->entire_xinerama); - } - } - - cur_workspace = window->screen->active_workspace; - info->usable_screen_region = - meta_workspace_get_onscreen_region (cur_workspace); - info->usable_xinerama_region = - meta_workspace_get_onxinerama_region (cur_workspace, - xinerama_info->number); - - /* Workaround braindead legacy apps that don't know how to - * fullscreen themselves properly. - */ - if (meta_rectangle_equal (new, &xinerama_info->rect) && - window->has_fullscreen_func && - !window->fullscreen) - { - /* - meta_topic (META_DEBUG_GEOMETRY, - */ - meta_warning ( - "Treating resize request of legacy application %s as a " - "fullscreen request\n", - window->desc); - meta_window_make_fullscreen_internal (window); - } - - /* Log all this information for debugging */ - meta_topic (META_DEBUG_GEOMETRY, - "Setting up constraint info:\n" - " orig: %d,%d +%d,%d\n" - " new : %d,%d +%d,%d\n" - " fgeom: %d,%d,%d,%d\n" - " action_type : %s\n" - " is_user_action : %s\n" - " resize_gravity : %s\n" - " fixed_directions: %s\n" - " work_area_xinerama: %d,%d +%d,%d\n" - " entire_xinerama : %d,%d +%d,%d\n", - info->orig.x, info->orig.y, info->orig.width, info->orig.height, - info->current.x, info->current.y, - info->current.width, info->current.height, - info->fgeom->left_width, info->fgeom->right_width, - info->fgeom->top_height, info->fgeom->bottom_height, - (info->action_type == ACTION_MOVE) ? "Move" : - (info->action_type == ACTION_RESIZE) ? "Resize" : - (info->action_type == ACTION_MOVE_AND_RESIZE) ? "Move&Resize" : - "Freakin' Invalid Stupid", - (info->is_user_action) ? "true" : "false", - meta_gravity_to_string (info->resize_gravity), - (info->fixed_directions == FIXED_DIRECTION_NONE) ? "None" : - (info->fixed_directions == FIXED_DIRECTION_X) ? "X fixed" : - (info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" : - "Freakin' Invalid Stupid", - info->work_area_xinerama.x, info->work_area_xinerama.y, - info->work_area_xinerama.width, - info->work_area_xinerama.height, - info->entire_xinerama.x, info->entire_xinerama.y, - info->entire_xinerama.width, info->entire_xinerama.height); -} - -static void -place_window_if_needed(MetaWindow *window, - ConstraintInfo *info) -{ - gboolean did_placement; - - /* Do placement if any, so we go ahead and apply position - * constraints in a move-only context. Don't place - * maximized/minimized/fullscreen windows until they are - * unmaximized, unminimized and unfullscreened. - */ - did_placement = FALSE; - if (!window->placed && - window->calc_placement && - !(window->maximized_horizontally || - window->maximized_vertically) && - !window->minimized && - !window->fullscreen) - { - MetaRectangle placed_rect = info->orig; - MetaWorkspace *cur_workspace; - const MetaXineramaScreenInfo *xinerama_info; - - meta_window_place (window, info->fgeom, info->orig.x, info->orig.y, - &placed_rect.x, &placed_rect.y); - did_placement = TRUE; - - /* placing the window may have changed the xinerama. Find the - * new xinerama and update the ConstraintInfo - */ - xinerama_info = - meta_screen_get_xinerama_for_rect (window->screen, &placed_rect); - info->entire_xinerama = xinerama_info->rect; - meta_window_get_work_area_for_xinerama (window, - xinerama_info->number, - &info->work_area_xinerama); - cur_workspace = window->screen->active_workspace; - info->usable_xinerama_region = - meta_workspace_get_onxinerama_region (cur_workspace, - xinerama_info->number); - - - info->current.x = placed_rect.x; - info->current.y = placed_rect.y; - - /* Since we just barely placed the window, there's no reason to - * consider any of the directions fixed. - */ - info->fixed_directions = FIXED_DIRECTION_NONE; - } - - if (window->placed || did_placement) - { - if (window->maximize_horizontally_after_placement || - window->maximize_vertically_after_placement) - { - /* define a sane saved_rect so that the user can unmaximize to - * something reasonable. - */ - if (info->current.width >= info->work_area_xinerama.width) - { - info->current.width = .75 * info->work_area_xinerama.width; - info->current.x = info->work_area_xinerama.x + - .125 * info->work_area_xinerama.width; - } - if (info->current.height >= info->work_area_xinerama.height) - { - info->current.height = .75 * info->work_area_xinerama.height; - info->current.y = info->work_area_xinerama.y + - .083 * info->work_area_xinerama.height; - } - - if (window->maximize_horizontally_after_placement || - window->maximize_vertically_after_placement) - meta_window_maximize_internal (window, - (window->maximize_horizontally_after_placement ? - META_MAXIMIZE_HORIZONTAL : 0 ) | - (window->maximize_vertically_after_placement ? - META_MAXIMIZE_VERTICAL : 0), &info->current); - - /* maximization may have changed frame geometry */ - if (window->frame && !window->fullscreen) - meta_frame_calc_geometry (window->frame, info->fgeom); - - window->maximize_horizontally_after_placement = FALSE; - window->maximize_vertically_after_placement = FALSE; - } - if (window->minimize_after_placement) - { - meta_window_minimize (window); - window->minimize_after_placement = FALSE; - } - } -} - -static void -update_onscreen_requirements (MetaWindow *window, - ConstraintInfo *info) -{ - gboolean old; - - /* We only apply the various onscreen requirements to normal windows */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK) - return; - - /* We don't want to update the requirements for fullscreen windows; - * fullscreen windows are specially handled anyway, and it updating - * the requirements when windows enter fullscreen mode mess up the - * handling of the window when it leaves that mode (especially when - * the application sends a bunch of configurerequest events). See - * #353699. - */ - if (window->fullscreen) - return; - - /* USABILITY NOTE: Naturally, I only want the require_fully_onscreen, - * require_on_single_xinerama, and require_titlebar_visible flags to - * *become false* due to user interactions (which is allowed since - * certain constraints are ignored for user interactions regardless of - * the setting of these flags). However, whether to make these flags - * *become true* due to just an application interaction is a little - * trickier. It's possible that users may find not doing that strange - * since two application interactions that resize in opposite ways don't - * necessarily end up cancelling--but it may also be strange for the user - * to have an application resize the window so that it's onscreen, the - * user forgets about it, and then later the app is able to resize itself - * off the screen. Anyway, for now, I think the latter is the more - * problematic case but this may need to be revisited. - */ - - /* The require onscreen/on-single-xinerama and titlebar_visible - * stuff is relative to the outer window, not the inner - */ - extend_by_frame (&info->current, info->fgeom); - - /* Update whether we want future constraint runs to require the - * window to be on fully onscreen. - */ - old = window->require_fully_onscreen; - window->require_fully_onscreen = - meta_rectangle_contained_in_region (info->usable_screen_region, - &info->current); - if (old ^ window->require_fully_onscreen) - meta_topic (META_DEBUG_GEOMETRY, - "require_fully_onscreen for %s toggled to %s\n", - window->desc, - window->require_fully_onscreen ? "TRUE" : "FALSE"); - - /* Update whether we want future constraint runs to require the - * window to be on a single xinerama. - */ - old = window->require_on_single_xinerama; - window->require_on_single_xinerama = - meta_rectangle_contained_in_region (info->usable_xinerama_region, - &info->current); - if (old ^ window->require_on_single_xinerama) - meta_topic (META_DEBUG_GEOMETRY, - "require_on_single_xinerama for %s toggled to %s\n", - window->desc, - window->require_on_single_xinerama ? "TRUE" : "FALSE"); - - /* Update whether we want future constraint runs to require the - * titlebar to be visible. - */ - if (window->frame && window->decorated) - { - MetaRectangle titlebar_rect; - - titlebar_rect = info->current; - titlebar_rect.height = info->fgeom->top_height; - old = window->require_titlebar_visible; - window->require_titlebar_visible = - meta_rectangle_overlaps_with_region (info->usable_screen_region, - &titlebar_rect); - if (old ^ window->require_titlebar_visible) - meta_topic (META_DEBUG_GEOMETRY, - "require_titlebar_visible for %s toggled to %s\n", - window->desc, - window->require_titlebar_visible ? "TRUE" : "FALSE"); - } - - /* Don't forget to restore the position of the window */ - unextend_by_frame (&info->current, info->fgeom); -} - -static void -extend_by_frame (MetaRectangle *rect, - const MetaFrameGeometry *fgeom) -{ - rect->x -= fgeom->left_width; - rect->y -= fgeom->top_height; - rect->width += fgeom->left_width + fgeom->right_width; - rect->height += fgeom->top_height + fgeom->bottom_height; -} - -static void -unextend_by_frame (MetaRectangle *rect, - const MetaFrameGeometry *fgeom) -{ - rect->x += fgeom->left_width; - rect->y += fgeom->top_height; - rect->width -= fgeom->left_width + fgeom->right_width; - rect->height -= fgeom->top_height + fgeom->bottom_height; -} - -static inline void -get_size_limits (const MetaWindow *window, - const MetaFrameGeometry *fgeom, - gboolean include_frame, - MetaRectangle *min_size, - MetaRectangle *max_size) -{ - /* We pack the results into MetaRectangle structs just for convienience; we - * don't actually use the position of those rects. - */ - min_size->width = window->size_hints.min_width; - min_size->height = window->size_hints.min_height; - max_size->width = window->size_hints.max_width; - max_size->height = window->size_hints.max_height; - - if (include_frame) - { - int fw = fgeom->left_width + fgeom->right_width; - int fh = fgeom->top_height + fgeom->bottom_height; - - min_size->width += fw; - min_size->height += fh; - max_size->width += fw; - max_size->height += fh; - } -} - -static gboolean -constrain_maximization (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaRectangle target_size; - MetaRectangle min_size, max_size; - gboolean hminbad, vminbad; - gboolean horiz_equal, vert_equal; - gboolean constraint_already_satisfied; - - if (priority > PRIORITY_MAXIMIZATION) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't */ - if (!window->maximized_horizontally && !window->maximized_vertically) - return TRUE; - - /* Calculate target_size = maximized size of (window + frame) */ - if (window->maximized_horizontally && window->maximized_vertically) - target_size = info->work_area_xinerama; - else - { - /* Amount of maximization possible in a single direction depends - * on which struts could occlude the window given its current - * position. For example, a vertical partial strut on the right - * is only relevant for a horizontally maximized window when the - * window is at a vertical position where it could be occluded - * by that partial strut. - */ - MetaDirection direction; - GSList *active_workspace_struts; - - if (window->maximized_horizontally) - direction = META_DIRECTION_HORIZONTAL; - else - direction = META_DIRECTION_VERTICAL; - active_workspace_struts = window->screen->active_workspace->all_struts; - - target_size = info->current; - extend_by_frame (&target_size, info->fgeom); - meta_rectangle_expand_to_avoiding_struts (&target_size, - &info->entire_xinerama, - direction, - active_workspace_struts); - } - /* Now make target_size = maximized size of client window */ - unextend_by_frame (&target_size, info->fgeom); - - /* Check min size constraints; max size constraints are ignored for maximized - * windows, as per bug 327543. - */ - get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size); - hminbad = target_size.width < min_size.width && window->maximized_horizontally; - vminbad = target_size.height < min_size.height && window->maximized_vertically; - if (hminbad || vminbad) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - horiz_equal = target_size.x == info->current.x && - target_size.width == info->current.width; - vert_equal = target_size.y == info->current.y && - target_size.height == info->current.height; - constraint_already_satisfied = - (horiz_equal || !window->maximized_horizontally) && - (vert_equal || !window->maximized_vertically); - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - if (window->maximized_horizontally) - { - info->current.x = target_size.x; - info->current.width = target_size.width; - } - if (window->maximized_vertically) - { - info->current.y = target_size.y; - info->current.height = target_size.height; - } - return TRUE; -} - -static gboolean -constrain_fullscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaRectangle min_size, max_size, xinerama; - gboolean too_big, too_small, constraint_already_satisfied; - - if (priority > PRIORITY_FULLSCREEN) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't */ - if (!window->fullscreen) - return TRUE; - - xinerama = info->entire_xinerama; - - get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size); - too_big = !meta_rectangle_could_fit_rect (&xinerama, &min_size); - too_small = !meta_rectangle_could_fit_rect (&max_size, &xinerama); - if (too_big || too_small) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - constraint_already_satisfied = - meta_rectangle_equal (&info->current, &xinerama); - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - info->current = xinerama; - return TRUE; -} - -static gboolean -constrain_size_increments (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - int bh, hi, bw, wi, extra_height, extra_width; - int new_width, new_height; - gboolean constraint_already_satisfied; - MetaRectangle *start_rect; - - if (priority > PRIORITY_SIZE_HINTS_INCREMENTS) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't */ - if (META_WINDOW_MAXIMIZED (window) || window->fullscreen || - info->action_type == ACTION_MOVE) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - bh = window->size_hints.base_height; - hi = window->size_hints.height_inc; - bw = window->size_hints.base_width; - wi = window->size_hints.width_inc; - extra_height = (info->current.height - bh) % hi; - extra_width = (info->current.width - bw) % wi; - /* ignore size increments for maximized windows */ - if (window->maximized_horizontally) - extra_width *= 0; - if (window->maximized_vertically) - extra_height *= 0; - /* constraint is satisfied iff there is no extra height or width */ - constraint_already_satisfied = - (extra_height == 0 && extra_width == 0); - - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - new_width = info->current.width - extra_width; - new_height = info->current.height - extra_height; - - /* Adjusting down instead of up (as done in the above two lines) may - * violate minimum size constraints; fix the adjustment if this - * happens. - */ - if (new_width < window->size_hints.min_width) - new_width += ((window->size_hints.min_width - new_width)/wi + 1)*wi; - if (new_height < window->size_hints.min_height) - new_height += ((window->size_hints.min_height - new_height)/hi + 1)*hi; - - /* Figure out what original rect to pass to meta_rectangle_resize_with_gravity - * See bug 448183 - */ - if (info->action_type == ACTION_MOVE_AND_RESIZE) - start_rect = &info->current; - else - start_rect = &info->orig; - - /* Resize to the new size */ - meta_rectangle_resize_with_gravity (start_rect, - &info->current, - info->resize_gravity, - new_width, - new_height); - return TRUE; -} - -static gboolean -constrain_size_limits (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaRectangle min_size, max_size; - gboolean too_big, too_small, constraint_already_satisfied; - int new_width, new_height; - MetaRectangle *start_rect; - - if (priority > PRIORITY_SIZE_HINTS_LIMITS) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't. - * - * Note: The old code didn't apply this constraint for fullscreen or - * maximized windows--but that seems odd to me. *shrug* - */ - if (info->action_type == ACTION_MOVE) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size); - /* We ignore max-size limits for maximized windows; see #327543 */ - if (window->maximized_horizontally) - max_size.width = MAX (max_size.width, info->current.width); - if (window->maximized_vertically) - max_size.height = MAX (max_size.height, info->current.height); - too_small = !meta_rectangle_could_fit_rect (&info->current, &min_size); - too_big = !meta_rectangle_could_fit_rect (&max_size, &info->current); - constraint_already_satisfied = !too_big && !too_small; - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - new_width = CLAMP (info->current.width, min_size.width, max_size.width); - new_height = CLAMP (info->current.height, min_size.height, max_size.height); - - /* Figure out what original rect to pass to meta_rectangle_resize_with_gravity - * See bug 448183 - */ - if (info->action_type == ACTION_MOVE_AND_RESIZE) - start_rect = &info->current; - else - start_rect = &info->orig; - - meta_rectangle_resize_with_gravity (start_rect, - &info->current, - info->resize_gravity, - new_width, - new_height); - return TRUE; -} - -static gboolean -constrain_aspect_ratio (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - double minr, maxr; - gboolean constraints_are_inconsistent, constraint_already_satisfied; - int fudge, new_width, new_height; - double best_width, best_height; - double alt_width, alt_height; - MetaRectangle *start_rect; - - if (priority > PRIORITY_ASPECT_RATIO) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't. */ - minr = window->size_hints.min_aspect.x / - (double)window->size_hints.min_aspect.y; - maxr = window->size_hints.max_aspect.x / - (double)window->size_hints.max_aspect.y; - constraints_are_inconsistent = minr > maxr; - if (constraints_are_inconsistent || - META_WINDOW_MAXIMIZED (window) || window->fullscreen || - info->action_type == ACTION_MOVE) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is. We - * need the following to hold: - * - * width - * minr <= ------ <= maxr - * height - * - * But we need to allow for some slight fudging since width and height - * are integers instead of floating point numbers (this is particularly - * important when minr == maxr), so we allow width and height to be off - * a little bit from strictly satisfying these equations. For just one - * sided resizing, we have to make the fudge factor a little bigger - * because of how meta_rectangle_resize_with_gravity treats those as - * being a resize increment (FIXME: I should handle real resize - * increments better here...) - */ - switch (info->resize_gravity) - { - case WestGravity: - case NorthGravity: - case SouthGravity: - case EastGravity: - fudge = 2; - break; - - case NorthWestGravity: - case SouthWestGravity: - case CenterGravity: - case NorthEastGravity: - case SouthEastGravity: - case StaticGravity: - default: - fudge = 1; - break; - } - constraint_already_satisfied = - info->current.width - (info->current.height * minr ) > -minr*fudge && - info->current.width - (info->current.height * maxr ) < maxr*fudge; - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - new_width = info->current.width; - new_height = info->current.height; - - switch (info->resize_gravity) - { - case WestGravity: - case EastGravity: - /* Yeah, I suck for doing implicit rounding -- sue me */ - new_height = CLAMP (new_height, new_width / maxr, new_width / minr); - break; - - case NorthGravity: - case SouthGravity: - /* Yeah, I suck for doing implicit rounding -- sue me */ - new_width = CLAMP (new_width, new_height * minr, new_height * maxr); - break; - - case NorthWestGravity: - case SouthWestGravity: - case CenterGravity: - case NorthEastGravity: - case SouthEastGravity: - case StaticGravity: - default: - /* Find what width would correspond to new_height, and what height would - * correspond to new_width */ - alt_width = CLAMP (new_width, new_height * minr, new_height * maxr); - alt_height = CLAMP (new_height, new_width / maxr, new_width / minr); - - /* The line connecting the points (alt_width, new_height) and - * (new_width, alt_height) provide a range of - * valid-for-the-aspect-ratio-constraint sizes. We want the - * size in that range closest to the value requested, i.e. the - * point on the line which is closest to the point (new_width, - * new_height) - */ - meta_rectangle_find_linepoint_closest_to_point (alt_width, new_height, - new_width, alt_height, - new_width, new_height, - &best_width, &best_height); - - /* Yeah, I suck for doing implicit rounding -- sue me */ - new_width = best_width; - new_height = best_height; - - break; - } - - /* Figure out what original rect to pass to meta_rectangle_resize_with_gravity - * See bug 448183 - */ - if (info->action_type == ACTION_MOVE_AND_RESIZE) - start_rect = &info->current; - else - start_rect = &info->orig; - - meta_rectangle_resize_with_gravity (start_rect, - &info->current, - info->resize_gravity, - new_width, - new_height); - - return TRUE; -} - -static gboolean -do_screen_and_xinerama_relative_constraints ( - MetaWindow *window, - GList *region_spanning_rectangles, - ConstraintInfo *info, - gboolean check_only) -{ - gboolean exit_early = FALSE, constraint_satisfied; - MetaRectangle how_far_it_can_be_smushed, min_size, max_size; - -#ifdef WITH_VERBOSE_MODE - if (meta_is_verbose ()) - { - /* First, log some debugging information */ - char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)]; - - meta_topic (META_DEBUG_GEOMETRY, - "screen/xinerama constraint; region_spanning_rectangles: %s\n", - meta_rectangle_region_to_string (region_spanning_rectangles, ", ", - spanning_region)); - } -#endif - - /* Determine whether constraint applies; exit if it doesn't */ - how_far_it_can_be_smushed = info->current; - get_size_limits (window, info->fgeom, TRUE, &min_size, &max_size); - extend_by_frame (&info->current, info->fgeom); - - if (info->action_type != ACTION_MOVE) - { - if (!(info->fixed_directions & FIXED_DIRECTION_X)) - how_far_it_can_be_smushed.width = min_size.width; - - if (!(info->fixed_directions & FIXED_DIRECTION_Y)) - how_far_it_can_be_smushed.height = min_size.height; - } - if (!meta_rectangle_could_fit_in_region (region_spanning_rectangles, - &how_far_it_can_be_smushed)) - exit_early = TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - constraint_satisfied = - meta_rectangle_contained_in_region (region_spanning_rectangles, - &info->current); - if (exit_early || constraint_satisfied || check_only) - { - unextend_by_frame (&info->current, info->fgeom); - return constraint_satisfied; - } - - /* Enforce constraint */ - - /* Clamp rectangle size for resize or move+resize actions */ - if (info->action_type != ACTION_MOVE) - meta_rectangle_clamp_to_fit_into_region (region_spanning_rectangles, - info->fixed_directions, - &info->current, - &min_size); - - if (info->is_user_action && info->action_type == ACTION_RESIZE) - /* For user resize, clip to the relevant region */ - meta_rectangle_clip_to_region (region_spanning_rectangles, - info->fixed_directions, - &info->current); - else - /* For everything else, shove the rectangle into the relevant region */ - meta_rectangle_shove_into_region (region_spanning_rectangles, - info->fixed_directions, - &info->current); - - unextend_by_frame (&info->current, info->fgeom); - return TRUE; -} - -static gboolean -constrain_to_single_xinerama (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA) - return TRUE; - - /* Exit early if we know the constraint won't apply--note that this constraint - * is only meant for normal windows (e.g. we don't want docks to be shoved - * "onscreen" by their own strut) and we can't apply it to frameless windows - * or else users will be unable to move windows such as XMMS across xineramas. - */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->screen->n_xinerama_infos == 1 || - !window->require_on_single_xinerama || - !window->frame || - info->is_user_action) - return TRUE; - - /* Have a helper function handle the constraint for us */ - return do_screen_and_xinerama_relative_constraints (window, - info->usable_xinerama_region, - info, - check_only); -} - -static gboolean -constrain_fully_onscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA) - return TRUE; - - /* Exit early if we know the constraint won't apply--note that this constraint - * is only meant for normal windows (e.g. we don't want docks to be shoved - * "onscreen" by their own strut). - */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->fullscreen || - !window->require_fully_onscreen || - info->is_user_action) - return TRUE; - - /* Have a helper function handle the constraint for us */ - return do_screen_and_xinerama_relative_constraints (window, - info->usable_screen_region, - info, - check_only); -} - -static gboolean -constrain_titlebar_visible (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - gboolean unconstrained_user_action; - gboolean retval; - int bottom_amount; - int horiz_amount_offscreen, vert_amount_offscreen; - int horiz_amount_onscreen, vert_amount_onscreen; - - if (priority > PRIORITY_TITLEBAR_VISIBLE) - return TRUE; - - /* Allow the titlebar beyond the top of the screen only if the user wasn't - * clicking on the frame to start the move. - */ - unconstrained_user_action = - info->is_user_action && !window->display->grab_frame_action; - - /* Exit early if we know the constraint won't apply--note that this constraint - * is only meant for normal windows (e.g. we don't want docks to be shoved - * "onscreen" by their own strut). - */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->fullscreen || - !window->require_titlebar_visible || - !window->decorated || - unconstrained_user_action) - return TRUE; - - /* Determine how much offscreen things are allowed. We first need to - * figure out how much must remain on the screen. For that, we use 25% - * window width/height but clamp to the range of (10,75) pixels. This is - * somewhat of a seat of my pants random guess at what might look good. - * Then, the amount that is allowed off is just the window size minus - * this amount (but no less than 0 for tiny windows). - */ - horiz_amount_onscreen = info->current.width / 4; - vert_amount_onscreen = info->current.height / 4; - horiz_amount_onscreen = CLAMP (horiz_amount_onscreen, 10, 75); - vert_amount_onscreen = CLAMP (vert_amount_onscreen, 10, 75); - horiz_amount_offscreen = info->current.width - horiz_amount_onscreen; - vert_amount_offscreen = info->current.height - vert_amount_onscreen; - horiz_amount_offscreen = MAX (horiz_amount_offscreen, 0); - vert_amount_offscreen = MAX (vert_amount_offscreen, 0); - /* Allow the titlebar to touch the bottom panel; If there is no titlebar, - * require vert_amount to remain on the screen. - */ - if (window->frame) - { - bottom_amount = info->current.height + info->fgeom->bottom_height; - vert_amount_onscreen = info->fgeom->top_height; - } - else - bottom_amount = vert_amount_offscreen; - - /* Extend the region, have a helper function handle the constraint, - * then return the region to its original size. - */ - meta_rectangle_expand_region_conditionally (info->usable_screen_region, - horiz_amount_offscreen, - horiz_amount_offscreen, - 0, /* Don't let titlebar off */ - bottom_amount, - horiz_amount_onscreen, - vert_amount_onscreen); - retval = - do_screen_and_xinerama_relative_constraints (window, - info->usable_screen_region, - info, - check_only); - meta_rectangle_expand_region_conditionally (info->usable_screen_region, - -horiz_amount_offscreen, - -horiz_amount_offscreen, - 0, /* Don't let titlebar off */ - -bottom_amount, - horiz_amount_onscreen, - vert_amount_onscreen); - - return retval; -} - -static gboolean -constrain_partially_onscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - gboolean retval; - int top_amount, bottom_amount; - int horiz_amount_offscreen, vert_amount_offscreen; - int horiz_amount_onscreen, vert_amount_onscreen; - - if (priority > PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA) - return TRUE; - - /* Exit early if we know the constraint won't apply--note that this constraint - * is only meant for normal windows (e.g. we don't want docks to be shoved - * "onscreen" by their own strut). - */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK) - return TRUE; - - /* Determine how much offscreen things are allowed. We first need to - * figure out how much must remain on the screen. For that, we use 25% - * window width/height but clamp to the range of (10,75) pixels. This is - * somewhat of a seat of my pants random guess at what might look good. - * Then, the amount that is allowed off is just the window size minus - * this amount (but no less than 0 for tiny windows). - */ - horiz_amount_onscreen = info->current.width / 4; - vert_amount_onscreen = info->current.height / 4; - horiz_amount_onscreen = CLAMP (horiz_amount_onscreen, 10, 75); - vert_amount_onscreen = CLAMP (vert_amount_onscreen, 10, 75); - horiz_amount_offscreen = info->current.width - horiz_amount_onscreen; - vert_amount_offscreen = info->current.height - vert_amount_onscreen; - horiz_amount_offscreen = MAX (horiz_amount_offscreen, 0); - vert_amount_offscreen = MAX (vert_amount_offscreen, 0); - top_amount = vert_amount_offscreen; - /* Allow the titlebar to touch the bottom panel; If there is no titlebar, - * require vert_amount to remain on the screen. - */ - if (window->frame) - { - bottom_amount = info->current.height + info->fgeom->bottom_height; - vert_amount_onscreen = info->fgeom->top_height; - } - else - bottom_amount = vert_amount_offscreen; - - /* Extend the region, have a helper function handle the constraint, - * then return the region to its original size. - */ - meta_rectangle_expand_region_conditionally (info->usable_screen_region, - horiz_amount_offscreen, - horiz_amount_offscreen, - top_amount, - bottom_amount, - horiz_amount_onscreen, - vert_amount_onscreen); - retval = - do_screen_and_xinerama_relative_constraints (window, - info->usable_screen_region, - info, - check_only); - meta_rectangle_expand_region_conditionally (info->usable_screen_region, - -horiz_amount_offscreen, - -horiz_amount_offscreen, - -top_amount, - -bottom_amount, - horiz_amount_onscreen, - vert_amount_onscreen); - - return retval; -} diff --git a/src/core/constraints.h b/src/core/constraints.h deleted file mode 100644 index 6ccad00e..00000000 --- a/src/core/constraints.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity size/position constraints */ - -/* - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_CONSTRAINTS_H -#define META_CONSTRAINTS_H - -#include "util.h" -#include "window-private.h" -#include "frame-private.h" - -typedef enum -{ - META_IS_CONFIGURE_REQUEST = 1 << 0, - META_DO_GRAVITY_ADJUST = 1 << 1, - META_IS_USER_ACTION = 1 << 2, - META_IS_MOVE_ACTION = 1 << 3, - META_IS_RESIZE_ACTION = 1 << 4 -} MetaMoveResizeFlags; - -void meta_window_constrain (MetaWindow *window, - MetaFrameGeometry *orig_fgeom, - MetaMoveResizeFlags flags, - int resize_gravity, - const MetaRectangle *orig, - MetaRectangle *new); - -#endif /* META_CONSTRAINTS_H */ diff --git a/src/core/core.c b/src/core/core.c deleted file mode 100644 index a63531fe..00000000 --- a/src/core/core.c +++ /dev/null @@ -1,776 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity interface used by GTK+ UI to talk to core */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "core.h" -#include "frame-private.h" -#include "workspace.h" -#include "prefs.h" - -/* Looks up the MetaWindow representing the frame of the given X window. - * Used as a helper function by a bunch of the functions below. - * - * FIXME: The functions that use this function throw the result away - * after use. Many of these functions tend to be called in small groups, - * which results in get_window() getting called several times in succession - * with the same parameters. We should profile to see whether this wastes - * much time, and if it does we should look into a generalised - * meta_core_get_window_info() which takes a bunch of pointers to variables - * to put its results in, and only fills in the non-null ones. - */ -static MetaWindow * -get_window (Display *xdisplay, - Window frame_xwindow) -{ - MetaDisplay *display; - MetaWindow *window; - - display = meta_display_for_x_display (xdisplay); - window = meta_display_lookup_x_window (display, frame_xwindow); - - if (window == NULL || window->frame == NULL) - { - meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); - return NULL; - } - - return window; -} - -void -meta_core_get (Display *xdisplay, - Window xwindow, - ...) -{ - va_list args; - MetaCoreGetType request; - - MetaDisplay *display = meta_display_for_x_display (xdisplay); - MetaWindow *window = meta_display_lookup_x_window (display, xwindow); - - va_start (args, xwindow); - - request = va_arg (args, MetaCoreGetType); - - /* Now, we special-case the first request slightly. Mostly, requests - * for information on windows which have no frame are errors. - * But sometimes we may want to know *whether* a window has a frame. - * In this case, pass the key META_CORE_WINDOW_HAS_FRAME - * as the *first* request, with a pointer to a boolean; if the window - * has no frame, this will be set to False and meta_core_get will - * exit immediately (so the values of any other requests will be - * undefined). Otherwise it will be set to True and meta_core_get will - * continue happily on its way. - */ - - if (request != META_CORE_WINDOW_HAS_FRAME && - (window == NULL || window->frame == NULL)) { - meta_bug ("No such frame window 0x%lx!\n", xwindow); - return; - } - - while (request != META_CORE_GET_END) { - - gpointer answer = va_arg (args, gpointer); - - switch (request) { - case META_CORE_WINDOW_HAS_FRAME: - *((gboolean*)answer) = window != NULL && window->frame != NULL; - if (!*((gboolean*)answer)) return; /* see above */ - break; - case META_CORE_GET_CLIENT_WIDTH: - *((gint*)answer) = window->rect.width; - break; - case META_CORE_GET_CLIENT_HEIGHT: - *((gint*)answer) = window->rect.height; - break; - case META_CORE_IS_TITLEBAR_ONSCREEN: - *((gboolean*)answer) = meta_window_titlebar_is_onscreen (window); - break; - case META_CORE_GET_CLIENT_XWINDOW: - *((Window*)answer) = window->xwindow; - break; - case META_CORE_GET_FRAME_FLAGS: - *((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame); - break; - case META_CORE_GET_FRAME_TYPE: - { - MetaFrameType base_type = META_FRAME_TYPE_LAST; - - switch (window->type) - { - case META_WINDOW_NORMAL: - base_type = META_FRAME_TYPE_NORMAL; - break; - - case META_WINDOW_DIALOG: - base_type = META_FRAME_TYPE_DIALOG; - break; - - case META_WINDOW_MODAL_DIALOG: - base_type = META_FRAME_TYPE_MODAL_DIALOG; - break; - - case META_WINDOW_MENU: - base_type = META_FRAME_TYPE_MENU; - break; - - case META_WINDOW_UTILITY: - base_type = META_FRAME_TYPE_UTILITY; - break; - - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_SPLASHSCREEN: - /* No frame */ - base_type = META_FRAME_TYPE_LAST; - break; - - } - - if (base_type == META_FRAME_TYPE_LAST) - { - /* can't add border if undecorated */ - *((MetaFrameType*)answer) = META_FRAME_TYPE_LAST; - } - else if (window->border_only) - { - /* override base frame type */ - *((MetaFrameType*)answer) = META_FRAME_TYPE_BORDER; - } - else - { - *((MetaFrameType*)answer) = base_type; - } - - break; - } - case META_CORE_GET_MINI_ICON: - *((GdkPixbuf**)answer) = window->mini_icon; - break; - case META_CORE_GET_ICON: - *((GdkPixbuf**)answer) = window->icon; - break; - case META_CORE_GET_X: - meta_window_get_position (window, (int*)answer, NULL); - break; - case META_CORE_GET_Y: - meta_window_get_position (window, NULL, (int*)answer); - break; - case META_CORE_GET_FRAME_WORKSPACE: - *((gint*)answer) = meta_window_get_net_wm_desktop (window); - break; - case META_CORE_GET_FRAME_X: - *((gint*)answer) = window->frame->rect.x; - break; - case META_CORE_GET_FRAME_Y: - *((gint*)answer) = window->frame->rect.y; - break; - case META_CORE_GET_FRAME_WIDTH: - *((gint*)answer) = window->frame->rect.width; - break; - case META_CORE_GET_FRAME_HEIGHT: - *((gint*)answer) = window->frame->rect.height; - break; - case META_CORE_GET_SCREEN_WIDTH: - *((gint*)answer) = window->screen->rect.width; - break; - case META_CORE_GET_SCREEN_HEIGHT: - *((gint*)answer) = window->screen->rect.height; - break; - - default: - meta_warning(_("Unknown window information request: %d"), request); - } - - request = va_arg (args, MetaCoreGetType); - } - - va_end (args); -} - -void -meta_core_queue_frame_resize (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); -} - -void -meta_core_user_move (Display *xdisplay, - Window frame_xwindow, - int x, - int y) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_move (window, TRUE, x, y); -} - -void -meta_core_user_resize (Display *xdisplay, - Window frame_xwindow, - int gravity, - int width, - int height) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_resize_with_gravity (window, TRUE, width, height, gravity); -} - -void -meta_core_user_raise (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_raise (window); -} - -void -meta_core_user_lower_and_unfocus (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_lower (window); - - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK && - meta_prefs_get_raise_on_click ()) - { - /* Move window to the back of the focusing workspace's MRU list. - * Do extra sanity checks to avoid possible race conditions. - * (Borrowed from window.c.) - */ - if (window->screen->active_workspace && - meta_window_located_on_workspace (window, - window->screen->active_workspace)) - { - GList* link; - link = g_list_find (window->screen->active_workspace->mru_list, - window); - g_assert (link); - - window->screen->active_workspace->mru_list = - g_list_remove_link (window->screen->active_workspace->mru_list, - link); - g_list_free (link); - - window->screen->active_workspace->mru_list = - g_list_append (window->screen->active_workspace->mru_list, - window); - } - } - - /* focus the default window, if needed */ - if (window->has_focus) - meta_workspace_focus_default_window (window->screen->active_workspace, - NULL, - timestamp); -} - -void -meta_core_user_focus (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_focus (window, timestamp); -} - -void -meta_core_minimize (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_minimize (window); -} - -void -meta_core_maximize (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); -} - -void -meta_core_toggle_maximize_vertically (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - - if (META_WINDOW_MAXIMIZED_VERTICALLY (window)) - meta_window_unmaximize (window, - META_MAXIMIZE_VERTICAL); - else - meta_window_maximize (window, - META_MAXIMIZE_VERTICAL); -} - -void -meta_core_toggle_maximize_horizontally (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - - if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window)) - meta_window_unmaximize (window, - META_MAXIMIZE_HORIZONTAL); - else - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL); -} - -void -meta_core_toggle_maximize (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - - if (META_WINDOW_MAXIMIZED (window)) - meta_window_unmaximize (window, - META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); - else - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); -} - -void -meta_core_unmaximize (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - - meta_window_unmaximize (window, - META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); -} - -void -meta_core_delete (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_delete (window, timestamp); -} - -void -meta_core_unshade (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_unshade (window, timestamp); -} - -void -meta_core_shade (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_shade (window, timestamp); -} - -void -meta_core_unstick (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_unstick (window); -} - -void -meta_core_make_above (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_make_above (window); -} - -void -meta_core_unmake_above (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_unmake_above (window); -} - -void -meta_core_stick (Display *xdisplay, - Window frame_xwindow) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_stick (window); -} - -void -meta_core_change_workspace (Display *xdisplay, - Window frame_xwindow, - int new_workspace) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - meta_window_change_workspace (window, - meta_screen_get_workspace_by_index (window->screen, - new_workspace)); -} - -int -meta_core_get_num_workspaces (Screen *xscreen) -{ - MetaScreen *screen; - - screen = meta_screen_for_x_screen (xscreen); - - return meta_screen_get_n_workspaces (screen); -} - -int -meta_core_get_active_workspace (Screen *xscreen) -{ - MetaScreen *screen; - - screen = meta_screen_for_x_screen (xscreen); - - return meta_workspace_index (screen->active_workspace); -} - -void -meta_core_show_window_menu (Display *xdisplay, - Window frame_xwindow, - int root_x, - int root_y, - int button, - guint32 timestamp) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_focus (window, timestamp); - - meta_window_show_menu (window, root_x, root_y, button, timestamp); -} - -void -meta_core_get_menu_accelerator (MetaMenuOp menu_op, - int workspace, - unsigned int *keysym, - MetaVirtualModifier *modifiers) -{ - const char *name; - - name = NULL; - - switch (menu_op) - { - case META_MENU_OP_DELETE: - name = "close"; - break; - case META_MENU_OP_MINIMIZE: - name = "minimize"; - break; - case META_MENU_OP_UNMAXIMIZE: - name = "unmaximize"; - break; - case META_MENU_OP_MAXIMIZE: - name = "maximize"; - break; - case META_MENU_OP_UNSHADE: - case META_MENU_OP_SHADE: - name = "toggle_shaded"; - break; - case META_MENU_OP_UNSTICK: - case META_MENU_OP_STICK: - name = "toggle_on_all_workspaces"; - break; - case META_MENU_OP_ABOVE: - case META_MENU_OP_UNABOVE: - name = "toggle_above"; - break; - case META_MENU_OP_WORKSPACES: - switch (workspace) - { - case 1: - name = "move_to_workspace_1"; - break; - case 2: - name = "move_to_workspace_2"; - break; - case 3: - name = "move_to_workspace_3"; - break; - case 4: - name = "move_to_workspace_4"; - break; - case 5: - name = "move_to_workspace_5"; - break; - case 6: - name = "move_to_workspace_6"; - break; - case 7: - name = "move_to_workspace_7"; - break; - case 8: - name = "move_to_workspace_8"; - break; - case 9: - name = "move_to_workspace_9"; - break; - case 10: - name = "move_to_workspace_10"; - break; - case 11: - name = "move_to_workspace_11"; - break; - case 12: - name = "move_to_workspace_12"; - break; - } - break; - case META_MENU_OP_MOVE: - name = "begin_move"; - break; - case META_MENU_OP_RESIZE: - name = "begin_resize"; - break; - case META_MENU_OP_MOVE_LEFT: - name = "move_to_workspace_left"; - break; - case META_MENU_OP_MOVE_RIGHT: - name = "move_to_workspace_right"; - break; - case META_MENU_OP_MOVE_UP: - name = "move_to_workspace_up"; - break; - case META_MENU_OP_MOVE_DOWN: - name = "move_to_workspace_down"; - break; - case META_MENU_OP_RECOVER: - /* No keybinding for this one */ - break; - } - - if (name) - { - meta_prefs_get_window_binding (name, keysym, modifiers); - } - else - { - *keysym = 0; - *modifiers = 0; - } -} - -const char* -meta_core_get_workspace_name_with_index (Display *xdisplay, - Window xroot, - int index) -{ - MetaDisplay *display; - MetaScreen *screen; - MetaWorkspace *workspace; - - display = meta_display_for_x_display (xdisplay); - screen = meta_display_screen_for_root (display, xroot); - g_assert (screen != NULL); - workspace = meta_screen_get_workspace_by_index (screen, index); - return workspace ? meta_workspace_get_name (workspace) : NULL; -} - -gboolean -meta_core_begin_grab_op (Display *xdisplay, - Window frame_xwindow, - MetaGrabOp op, - gboolean pointer_already_grabbed, - gboolean frame_action, - int button, - gulong modmask, - guint32 timestamp, - int root_x, - int root_y) -{ - MetaWindow *window = get_window (xdisplay, frame_xwindow); - MetaDisplay *display; - MetaScreen *screen; - - display = meta_display_for_x_display (xdisplay); - screen = meta_display_screen_for_xwindow (display, frame_xwindow); - - g_assert (screen != NULL); - - return meta_display_begin_grab_op (display, screen, window, - op, pointer_already_grabbed, - frame_action, - button, modmask, - timestamp, root_x, root_y); -} - -void -meta_core_end_grab_op (Display *xdisplay, - guint32 timestamp) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - - meta_display_end_grab_op (display, timestamp); -} - -MetaGrabOp -meta_core_get_grab_op (Display *xdisplay) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - - return display->grab_op; -} - -Window -meta_core_get_grab_frame (Display *xdisplay) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - - g_assert (display != NULL); - g_assert (display->grab_op == META_GRAB_OP_NONE || - display->grab_screen != NULL); - g_assert (display->grab_op == META_GRAB_OP_NONE || - display->grab_screen->display->xdisplay == xdisplay); - - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window && - display->grab_window->frame) - return display->grab_window->frame->xwindow; - else - return None; -} - -int -meta_core_get_grab_button (Display *xdisplay) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - - if (display->grab_op == META_GRAB_OP_NONE) - return -1; - - return display->grab_button; -} - -void -meta_core_grab_buttons (Display *xdisplay, - Window frame_xwindow) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - - meta_verbose ("Grabbing buttons on frame 0x%lx\n", frame_xwindow); - meta_display_grab_window_buttons (display, frame_xwindow); -} - -void -meta_core_set_screen_cursor (Display *xdisplay, - Window frame_on_screen, - MetaCursor cursor) -{ - MetaWindow *window = get_window (xdisplay, frame_on_screen); - - meta_frame_set_screen_cursor (window->frame, cursor); -} - -void -meta_core_increment_event_serial (Display *xdisplay) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - - meta_display_increment_event_serial (display); -} - -void -meta_invalidate_default_icons (void) -{ - MetaDisplay *display = meta_get_display (); - GSList *windows; - GSList *l; - - if (display == NULL) - return; /* We can validly be called before the display is opened. */ - - windows = meta_display_list_windows (display); - for (l = windows; l != NULL; l = l->next) - { - MetaWindow *window = (MetaWindow*)l->data; - - if (window->icon_cache.origin == USING_FALLBACK_ICON) - { - meta_icon_cache_free (&(window->icon_cache)); - meta_window_update_icon_now (window); - } - } - - g_slist_free (windows); -} - diff --git a/src/core/delete.c b/src/core/delete.c deleted file mode 100644 index abd1fd2c..00000000 --- a/src/core/delete.c +++ /dev/null @@ -1,505 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window deletion */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2004 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#define _GNU_SOURCE -#define _SVID_SOURCE /* for gethostname() */ - -#include <config.h> -#include "util.h" -#include "window-private.h" -#include "errors.h" -#include "workspace.h" - -#include <sys/types.h> -#include <signal.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -static void meta_window_present_delete_dialog (MetaWindow *window, - guint32 timestamp); - -static void -delete_ping_reply_func (MetaDisplay *display, - Window xwindow, - guint32 timestamp, - void *user_data) -{ - meta_topic (META_DEBUG_PING, - "Got reply to delete ping for %s\n", - ((MetaWindow*)user_data)->desc); - - /* we do nothing */ -} - -static Window -window_from_string (const char *str) -{ - char *end; - unsigned long l; - - end = NULL; - - l = strtoul (str, &end, 16); - - if (end == NULL || end == str) - { - meta_warning (_("Could not parse \"%s\" as an integer"), - str); - return None; - } - - if (*end != '\0') - { - meta_warning (_("Did not understand trailing characters \"%s\" in string \"%s\""), - end, str); - return None; - } - - return l; -} - -static int -pid_from_string (const char *str) -{ - char *end; - long l; - - end = NULL; - - l = strtol (str, &end, 10); - - if (end == NULL || end == str) - { - meta_warning (_("Could not parse \"%s\" as an integer"), - str); - return None; - } - - if (*end != '\0') - { - meta_warning (_("Did not understand trailing characters \"%s\" in string \"%s\""), - end, str); - return None; - } - - return l; -} - -static gboolean -parse_dialog_output (const char *str, - int *pid_out, - Window *win_out) -{ - char **split; - - split = g_strsplit (str, "\n", 2); - if (split && split[0] && split[1]) - { - g_strchomp (split[0]); - g_strchomp (split[1]); - - *pid_out = pid_from_string (split[0]); - *win_out = window_from_string (split[1]); - - g_strfreev (split); - - return TRUE; - } - else - { - g_strfreev (split); - meta_warning (_("Failed to parse message \"%s\" from dialog process\n"), - str); - return FALSE; - } -} - -static void -search_and_destroy_window (int pid, - Window xwindow) -{ - /* Find the window with the given dialog PID, - * double check that it matches "xwindow", then - * kill the window. - */ - GSList *tmp; - gboolean found = FALSE; - GSList *windows; - - if (xwindow == None) - { - meta_topic (META_DEBUG_PING, - "Window to destroy is None, doing nothing\n"); - return; - } - - windows = meta_display_list_windows (meta_get_display ()); - tmp = windows; - - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->dialog_pid == pid) - { - if (w->xwindow != xwindow) - meta_topic (META_DEBUG_PING, - "Dialog pid matches but not xwindow (0x%lx vs. 0x%lx)\n", - w->xwindow, xwindow); - else - { - meta_window_kill (w); - found = TRUE; - } - } - - tmp = tmp->next; - } - - g_slist_free (windows); - - if (!found) - meta_topic (META_DEBUG_PING, - "Did not find a window with dialog pid %d xwindow 0x%lx\n", - pid, xwindow); -} - -static void -release_window_with_fd (int fd) -{ - /* Find the window with the given dialog PID, - * double check that it matches "xwindow", then - * kill the window. - */ - gboolean found = FALSE; - - GSList *windows = meta_display_list_windows (meta_get_display ()); - GSList *tmp = windows; - - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->dialog_pid >= 0 && - w->dialog_pipe == fd) - { - meta_topic (META_DEBUG_PING, - "Removing dialog with fd %d pid %d from window %s\n", - fd, w->dialog_pid, w->desc); - meta_window_free_delete_dialog (w); - found = TRUE; - } - - tmp = tmp->next; - } - - g_slist_free (windows); - - if (!found) - meta_topic (META_DEBUG_PING, - "Did not find a window with a dialog pipe %d\n", - fd); -} - -static gboolean -io_from_ping_dialog (GIOChannel *channel, - GIOCondition condition, - gpointer data) -{ - meta_topic (META_DEBUG_PING, - "IO handler from ping dialog, condition = %x\n", - condition); - - if (condition & G_IO_IN) - { - char *str; - gsize len; - GError *err; - - /* Go ahead and block for all data from child */ - str = NULL; - len = 0; - err = NULL; - g_io_channel_read_to_end (channel, - &str, &len, - &err); - - if (err) - { - meta_warning (_("Error reading from dialog display process: %s\n"), - err->message); - g_error_free (err); - } - - meta_topic (META_DEBUG_PING, - "Read %" G_GSIZE_FORMAT " bytes strlen %d \"%s\" from child\n", - len, str ? (int) strlen (str) : 0, str ? str : "NULL"); - - if (len > 0) - { - /* We're supposed to kill the given window */ - int pid; - Window xwindow; - - if (parse_dialog_output (str, &pid, &xwindow)) - search_and_destroy_window (pid, xwindow); - } - - g_free (str); - } - - release_window_with_fd (g_io_channel_unix_get_fd (channel)); - - /* Remove the callback */ - return FALSE; -} - -static void -delete_ping_timeout_func (MetaDisplay *display, - Window xwindow, - guint32 timestamp, - void *user_data) -{ - MetaWindow *window = user_data; - GError *err; - int child_pid; - int outpipe; - char *argv[9]; - char numbuf[32]; - char timestampbuf[32]; - char *window_id_str; - char *window_title; - GIOChannel *channel; - - meta_topic (META_DEBUG_PING, - "Got delete ping timeout for %s\n", - window->desc); - - if (window->dialog_pid >= 0) - { - meta_window_present_delete_dialog (window, timestamp); - return; - } - - window_id_str = g_strdup_printf ("0x%lx", window->xwindow); - window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL); - - sprintf (numbuf, "%d", window->screen->number); - sprintf (timestampbuf, "%u", timestamp); - - argv[0] = METACITY_LIBEXECDIR"/metacity-dialog"; - argv[1] = "--screen"; - argv[2] = numbuf; - argv[3] = "--timestamp"; - argv[4] = timestampbuf; - argv[5] = "--kill-window-question"; - argv[6] = window_title; - argv[7] = window_id_str; - argv[8] = NULL; - - err = NULL; - if (!g_spawn_async_with_pipes ("/", - argv, - NULL, - 0, - NULL, NULL, - &child_pid, - NULL, - &outpipe, - NULL, - &err)) - { - meta_warning (_("Error launching metacity-dialog to ask about killing an application: %s\n"), - err->message); - g_error_free (err); - goto out; - } - - window->dialog_pid = child_pid; - window->dialog_pipe = outpipe; - - channel = g_io_channel_unix_new (window->dialog_pipe); - g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - io_from_ping_dialog, - NULL, NULL); - g_io_channel_unref (channel); - - out: - g_free (window_title); - g_free (window_id_str); -} - -void -meta_window_delete (MetaWindow *window, - guint32 timestamp) -{ - meta_error_trap_push (window->display); - if (window->delete_window) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Deleting %s with delete_window request\n", - window->desc); - meta_window_send_icccm_message (window, - window->display->atom_WM_DELETE_WINDOW, - timestamp); - } - else - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Deleting %s with explicit kill\n", - window->desc); - XKillClient (window->display->xdisplay, window->xwindow); - } - meta_error_trap_pop (window->display, FALSE); - - meta_display_ping_window (window->display, - window, - timestamp, - delete_ping_reply_func, - delete_ping_timeout_func, - window); - - if (window->has_focus) - { - /* FIXME Clean this up someday - * http://bugzilla.gnome.org/show_bug.cgi?id=108706 - */ -#if 0 - /* This is unfortunately going to result in weirdness - * if the window doesn't respond to the delete event. - * I don't know how to avoid that though. - */ - meta_topic (META_DEBUG_FOCUS, - "Focusing default window because focus window %s was deleted/killed\n", - window->desc); - meta_workspace_focus_default_window (window->screen->active_workspace, - window); -#else - meta_topic (META_DEBUG_FOCUS, - "Not unfocusing %s on delete/kill\n", - window->desc); -#endif - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Window %s was deleted/killed but didn't have focus\n", - window->desc); - } -} - - -void -meta_window_kill (MetaWindow *window) -{ - char buf[257]; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Killing %s brutally\n", - window->desc); - - if (window->wm_client_machine != NULL && - window->net_wm_pid > 0) - { - if (gethostname (buf, sizeof(buf)-1) == 0) - { - if (strcmp (buf, window->wm_client_machine) == 0) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Killing %s with kill()\n", - window->desc); - - if (kill (window->net_wm_pid, 9) < 0) - meta_topic (META_DEBUG_WINDOW_OPS, - "Failed to signal %s: %s\n", - window->desc, strerror (errno)); - } - } - else - { - meta_warning (_("Failed to get hostname: %s\n"), - strerror (errno)); - } - } - - meta_topic (META_DEBUG_WINDOW_OPS, - "Disconnecting %s with XKillClient()\n", - window->desc); - meta_error_trap_push (window->display); - XKillClient (window->display->xdisplay, window->xwindow); - meta_error_trap_pop (window->display, FALSE); -} - -void -meta_window_free_delete_dialog (MetaWindow *window) -{ - if (window->dialog_pid >= 0) - { - kill (window->dialog_pid, 9); - close (window->dialog_pipe); - window->dialog_pid = -1; - window->dialog_pipe = -1; - } -} - -static void -meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp) -{ - meta_topic (META_DEBUG_PING, - "Presenting existing ping dialog for %s\n", - window->desc); - - if (window->dialog_pid >= 0) - { - GSList *windows; - GSList *tmp; - - /* Activate transient for window that belongs to - * metacity-dialog - */ - - windows = meta_display_list_windows (window->display); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->xtransient_for == window->xwindow && - w->res_class && - g_ascii_strcasecmp (w->res_class, "metacity-dialog") == 0) - { - meta_window_activate (w, timestamp); - break; - } - - tmp = tmp->next; - } - - g_slist_free (windows); - } -} diff --git a/src/core/display-private.h b/src/core/display-private.h deleted file mode 100644 index 5f7dc487..00000000 --- a/src/core/display-private.h +++ /dev/null @@ -1,500 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X display handler */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_DISPLAY_PRIVATE_H -#define META_DISPLAY_PRIVATE_H - -#ifndef PACKAGE -#error "config.h not included" -#endif - -#include <glib.h> -#include <X11/Xlib.h> -#include "eventqueue.h" -#include "common.h" -#include "boxes.h" -#include "display.h" - -#ifdef HAVE_STARTUP_NOTIFICATION -#include <libsn/sn.h> -#endif - -#ifdef HAVE_XSYNC -#include <X11/extensions/sync.h> -#endif - -typedef struct _MetaKeyBinding MetaKeyBinding; -typedef struct _MetaStack MetaStack; -typedef struct _MetaUISlave MetaUISlave; -typedef struct _MetaWorkspace MetaWorkspace; - -typedef struct _MetaWindowPropHooks MetaWindowPropHooks; -typedef struct _MetaGroupPropHooks MetaGroupPropHooks; - -typedef struct MetaEdgeResistanceData MetaEdgeResistanceData; - -typedef void (* MetaWindowPingFunc) (MetaDisplay *display, - Window xwindow, - guint32 timestamp, - gpointer user_data); - - -#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ -#define _NET_WM_STATE_ADD 1 /* add/set property */ -#define _NET_WM_STATE_TOGGLE 2 /* toggle property */ - -/* This is basically a bogus number, just has to be large enough - * to handle the expected case of the alt+tab operation, where - * we want to ignore serials from UnmapNotify on the tab popup, - * and the LeaveNotify/EnterNotify from the pointer ungrab - */ -#define N_IGNORED_SERIALS 4 - -struct _MetaDisplay -{ - char *name; - Display *xdisplay; - - Window leader_window; - Window timestamp_pinging_window; - - /* Pull in all the names of atoms as fields; we will intern them when the - * class is constructed. - */ -#define item(x) Atom atom_##x; -#include "atomnames.h" -#undef item - - /* This is the actual window from focus events, - * not the one we last set - */ - MetaWindow *focus_window; - - /* window we are expecting a FocusIn event for or the current focus - * window if we are not expecting any FocusIn/FocusOut events; not - * perfect because applications can call XSetInputFocus directly. - * (It could also be messed up if a timestamp later than current - * time is sent to meta_display_set_input_focus_window, though that - * would be a programming error). See bug 154598 for more info. - */ - MetaWindow *expected_focus_window; - - /* last timestamp passed to XSetInputFocus */ - guint32 last_focus_time; - - /* last user interaction time in any app */ - guint32 last_user_time; - - /* whether we're using mousenav (only relevant for sloppy&mouse focus modes; - * !mouse_mode means "keynav mode") - */ - guint mouse_mode : 1; - - /* Helper var used when focus_new_windows setting is 'strict'; only - * relevant in 'strict' mode and if the focus window is a terminal. - * In that case, we don't allow new windows to take focus away from - * a terminal, but if the user explicitly did something that should - * allow a different window to gain focus (e.g. global keybinding or - * clicking on a dock), then we will allow the transfer. - */ - guint allow_terminal_deactivation : 1; - - guint static_gravity_works : 1; - - /*< private-ish >*/ - guint error_trap_synced_at_last_pop : 1; - MetaEventQueue *events; - GSList *screens; - MetaScreen *active_screen; - GHashTable *window_ids; - int error_traps; - int (* error_trap_handler) (Display *display, - XErrorEvent *error); - int server_grab_count; - - /* serials of leave/unmap events that may - * correspond to an enter event we should - * ignore - */ - unsigned long ignored_serials[N_IGNORED_SERIALS]; - Window ungrab_should_not_cause_focus_window; - - guint32 current_time; - - /* Pings which we're waiting for a reply from */ - GSList *pending_pings; - - /* Pending autoraise */ - guint autoraise_timeout_id; - MetaWindow* autoraise_window; - - /* Alt+click button grabs */ - unsigned int window_grab_modifiers; - - /* current window operation */ - MetaGrabOp grab_op; - MetaScreen *grab_screen; - MetaWindow *grab_window; - Window grab_xwindow; - int grab_button; - int grab_anchor_root_x; - int grab_anchor_root_y; - MetaRectangle grab_anchor_window_pos; - int grab_latest_motion_x; - int grab_latest_motion_y; - gulong grab_mask; - guint grab_have_pointer : 1; - guint grab_have_keyboard : 1; - guint grab_wireframe_active : 1; - guint grab_was_cancelled : 1; /* Only used in wireframe mode */ - guint grab_frame_action : 1; - MetaRectangle grab_wireframe_rect; - MetaRectangle grab_wireframe_last_xor_rect; - MetaRectangle grab_initial_window_pos; - int grab_initial_x, grab_initial_y; /* These are only relevant for */ - gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */ - MetaResizePopup *grab_resize_popup; - GTimeVal grab_last_moveresize_time; - guint32 grab_motion_notify_time; - int grab_wireframe_last_display_width; - int grab_wireframe_last_display_height; - GList* grab_old_window_stacking; - MetaEdgeResistanceData *grab_edge_resistance_data; - unsigned int grab_last_user_action_was_snap; - - /* we use property updates as sentinels for certain window focus events - * to avoid some race conditions on EnterNotify events - */ - int sentinel_counter; - -#ifdef HAVE_XKB - int xkb_base_event_type; - guint32 last_bell_time; -#endif -#ifdef HAVE_XSYNC - /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */ - XSyncAlarm grab_sync_request_alarm; -#endif - int grab_resize_timeout_id; - - /* Keybindings stuff */ - MetaKeyBinding *key_bindings; - int n_key_bindings; - int min_keycode; - int max_keycode; - KeySym *keymap; - int keysyms_per_keycode; - XModifierKeymap *modmap; - unsigned int ignored_modifier_mask; - unsigned int num_lock_mask; - unsigned int scroll_lock_mask; - unsigned int hyper_mask; - unsigned int super_mask; - unsigned int meta_mask; - - /* Xinerama cache */ - unsigned int xinerama_cache_invalidated : 1; - - /* Opening the display */ - unsigned int display_opening : 1; - - /* Closing down the display */ - int closing; - - /* Managed by group.c */ - GHashTable *groups_by_leader; - - /* currently-active window menu if any */ - MetaWindowMenu *window_menu; - MetaWindow *window_with_menu; - - /* Managed by window-props.c */ - MetaWindowPropHooks *prop_hooks; - - /* Managed by group-props.c */ - MetaGroupPropHooks *group_prop_hooks; - - /* Managed by compositor.c */ - MetaCompositor *compositor; - -#ifdef HAVE_STARTUP_NOTIFICATION - SnDisplay *sn_display; -#endif -#ifdef HAVE_XSYNC - int xsync_event_base; - int xsync_error_base; -#endif -#ifdef HAVE_SHAPE - int shape_event_base; - int shape_error_base; -#endif -#ifdef HAVE_RENDER - int render_event_base; - int render_error_base; -#endif -#ifdef HAVE_COMPOSITE_EXTENSIONS - int composite_event_base; - int composite_error_base; - int composite_major_version; - int composite_minor_version; - int damage_event_base; - int damage_error_base; - int xfixes_event_base; - int xfixes_error_base; -#endif -#ifdef HAVE_XSYNC - unsigned int have_xsync : 1; -#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync) -#else -#define META_DISPLAY_HAS_XSYNC(display) FALSE -#endif -#ifdef HAVE_SHAPE - unsigned int have_shape : 1; -#define META_DISPLAY_HAS_SHAPE(display) ((display)->have_shape) -#else -#define META_DISPLAY_HAS_SHAPE(display) FALSE -#endif -#ifdef HAVE_RENDER - unsigned int have_render : 1; -#define META_DISPLAY_HAS_RENDER(display) ((display)->have_render) -#else -#define META_DISPLAY_HAS_RENDER(display) FALSE -#endif -#ifdef HAVE_COMPOSITE_EXTENSIONS - unsigned int have_composite : 1; - unsigned int have_damage : 1; - unsigned int have_xfixes : 1; -#define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite) -#define META_DISPLAY_HAS_DAMAGE(display) ((display)->have_damage) -#define META_DISPLAY_HAS_XFIXES(display) ((display)->have_xfixes) -#else -#define META_DISPLAY_HAS_COMPOSITE(display) FALSE -#define META_DISPLAY_HAS_DAMAGE(display) FALSE -#define META_DISPLAY_HAS_XFIXES(display) FALSE -#endif -}; - -/* Xserver time can wraparound, thus comparing two timestamps needs to take - * this into account. Here's a little macro to help out. If no wraparound - * has occurred, this is equivalent to - * time1 < time2 - * Of course, the rest of the ugliness of this macro comes from accounting - * for the fact that wraparound can occur and the fact that a timestamp of - * 0 must be special-cased since it means older than anything else. - * - * Note that this is NOT an equivalent for time1 <= time2; if that's what - * you need then you'll need to swap the order of the arguments and negate - * the result. - */ -#define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \ - ( (( (time1) < (time2) ) && ( (time2) - (time1) < ((guint32)-1)/2 )) || \ - (( (time1) > (time2) ) && ( (time1) - (time2) > ((guint32)-1)/2 )) \ - ) -#define XSERVER_TIME_IS_BEFORE(time1, time2) \ - ( (time1) == 0 || \ - (XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) && \ - (time2) != 0) \ - ) - -gboolean meta_display_open (void); -void meta_display_close (MetaDisplay *display, - guint32 timestamp); -MetaScreen* meta_display_screen_for_x_screen (MetaDisplay *display, - Screen *screen); -MetaScreen* meta_display_screen_for_xwindow (MetaDisplay *display, - Window xindow); -void meta_display_grab (MetaDisplay *display); -void meta_display_ungrab (MetaDisplay *display); - -void meta_display_unmanage_screen (MetaDisplay *display, - MetaScreen *screen, - guint32 timestamp); - -void meta_display_unmanage_windows_for_screen (MetaDisplay *display, - MetaScreen *screen, - guint32 timestamp); - -/* Utility function to compare the stacking of two windows */ -int meta_display_stack_cmp (const void *a, - const void *b); - -/* A given MetaWindow may have various X windows that "belong" - * to it, such as the frame window. - */ -MetaWindow* meta_display_lookup_x_window (MetaDisplay *display, - Window xwindow); -void meta_display_register_x_window (MetaDisplay *display, - Window *xwindowp, - MetaWindow *window); -void meta_display_unregister_x_window (MetaDisplay *display, - Window xwindow); -/* Return whether the xwindow is a no focus window for any of the screens */ -gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display, - Window xwindow); - -GSList* meta_display_list_windows (MetaDisplay *display); - -MetaDisplay* meta_display_for_x_display (Display *xdisplay); -MetaDisplay* meta_get_display (void); - -Cursor meta_display_create_x_cursor (MetaDisplay *display, - MetaCursor cursor); - -void meta_display_set_grab_op_cursor (MetaDisplay *display, - MetaScreen *screen, - MetaGrabOp op, - gboolean change_pointer, - Window grab_xwindow, - guint32 timestamp); - -gboolean meta_display_begin_grab_op (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - MetaGrabOp op, - gboolean pointer_already_grabbed, - gboolean frame_action, - int button, - gulong modmask, - guint32 timestamp, - int root_x, - int root_y); -void meta_display_end_grab_op (MetaDisplay *display, - guint32 timestamp); - -void meta_display_check_threshold_reached (MetaDisplay *display, - int x, - int y); -void meta_display_grab_window_buttons (MetaDisplay *display, - Window xwindow); -void meta_display_ungrab_window_buttons (MetaDisplay *display, - Window xwindow); - -void meta_display_grab_focus_window_button (MetaDisplay *display, - MetaWindow *window); -void meta_display_ungrab_focus_window_button (MetaDisplay *display, - MetaWindow *window); - -/* Next two functions are defined in edge-resistance.c */ -void meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display); -void meta_display_cleanup_edges (MetaDisplay *display); - -/* make a request to ensure the event serial has changed */ -void meta_display_increment_event_serial (MetaDisplay *display); - -void meta_display_update_active_window_hint (MetaDisplay *display); - -guint32 meta_display_get_current_time (MetaDisplay *display); -guint32 meta_display_get_current_time_roundtrip (MetaDisplay *display); - -/* utility goo */ -const char* meta_event_mode_to_string (int m); -const char* meta_event_detail_to_string (int d); - -void meta_display_queue_retheme_all_windows (MetaDisplay *display); -void meta_display_retheme_all (void); - -void meta_display_set_cursor_theme (const char *theme, - int size); - -void meta_display_ping_window (MetaDisplay *display, - MetaWindow *window, - guint32 timestamp, - MetaWindowPingFunc ping_reply_func, - MetaWindowPingFunc ping_timeout_func, - void *user_data); -gboolean meta_display_window_has_pending_pings (MetaDisplay *display, - MetaWindow *window); - -typedef enum -{ - META_TAB_LIST_NORMAL, - META_TAB_LIST_DOCKS, - META_TAB_LIST_GROUP -} MetaTabList; - -typedef enum -{ - META_TAB_SHOW_ICON, /* Alt-Tab mode */ - META_TAB_SHOW_INSTANTLY /* Alt-Esc mode */ -} MetaTabShowType; - -GList* meta_display_get_tab_list (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace); - -MetaWindow* meta_display_get_tab_next (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace, - MetaWindow *window, - gboolean backward); - -MetaWindow* meta_display_get_tab_current (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace); - -int meta_resize_gravity_from_grab_op (MetaGrabOp op); - -gboolean meta_grab_op_is_moving (MetaGrabOp op); -gboolean meta_grab_op_is_resizing (MetaGrabOp op); - -void meta_display_devirtualize_modifiers (MetaDisplay *display, - MetaVirtualModifier modifiers, - unsigned int *mask); - -void meta_display_increment_focus_sentinel (MetaDisplay *display); -void meta_display_decrement_focus_sentinel (MetaDisplay *display); -gboolean meta_display_focus_sentinel_clear (MetaDisplay *display); - -/* meta_display_set_input_focus_window is like XSetInputFocus, except - * that (a) it can't detect timestamps later than the current time, - * since Metacity isn't part of the XServer, and thus gives erroneous - * behavior in this circumstance (so don't do it), (b) it uses - * display->last_focus_time since we don't have access to the true - * Xserver one, (c) it makes use of display->user_time since checking - * whether a window should be allowed to be focused should depend - * on user_time events (see bug 167358, comment 15 in particular) - */ -void meta_display_set_input_focus_window (MetaDisplay *display, - MetaWindow *window, - gboolean focus_frame, - guint32 timestamp); - -/* meta_display_focus_the_no_focus_window is called when the - * designated no_focus_window should be focused, but is otherwise the - * same as meta_display_set_input_focus_window - */ -void meta_display_focus_the_no_focus_window (MetaDisplay *display, - MetaScreen *screen, - guint32 timestamp); - -void meta_display_queue_autoraise_callback (MetaDisplay *display, - MetaWindow *window); -void meta_display_remove_autoraise_callback (MetaDisplay *display); - -#endif diff --git a/src/core/display.c b/src/core/display.c deleted file mode 100644 index daac23f3..00000000 --- a/src/core/display.c +++ /dev/null @@ -1,5189 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X display handler */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** - * \file display.c Handles operations on an X display. - * - * The display is represented as a MetaDisplay struct. - */ - -#include <config.h> -#include "display-private.h" -#include "util.h" -#include "main.h" -#include "screen-private.h" -#include "window-private.h" -#include "window-props.h" -#include "group-props.h" -#include "frame-private.h" -#include "errors.h" -#include "keybindings.h" -#include "prefs.h" -#include "resizepopup.h" -#include "xprops.h" -#include "workspace.h" -#include "bell.h" -#include "effects.h" -#include "compositor.h" -#include <X11/Xatom.h> -#include <X11/cursorfont.h> -#ifdef HAVE_SOLARIS_XINERAMA -#include <X11/extensions/xinerama.h> -#endif -#ifdef HAVE_XFREE_XINERAMA -#include <X11/extensions/Xinerama.h> -#endif -#ifdef HAVE_RANDR -#include <X11/extensions/Xrandr.h> -#endif -#ifdef HAVE_SHAPE -#include <X11/extensions/shape.h> -#endif -#ifdef HAVE_RENDER -#include <X11/extensions/Xrender.h> -#endif -#ifdef HAVE_XKB -#include <X11/XKBlib.h> -#endif -#ifdef HAVE_XCURSOR -#include <X11/Xcursor/Xcursor.h> -#endif -#ifdef HAVE_COMPOSITE_EXTENSIONS -#include <X11/extensions/Xcomposite.h> -#include <X11/extensions/Xdamage.h> -#include <X11/extensions/Xfixes.h> -#endif -#include <string.h> - -#define GRAB_OP_IS_WINDOW_SWITCH(g) \ - (g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \ - g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \ - g == META_GRAB_OP_KEYBOARD_TABBING_GROUP || \ - g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL || \ - g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK || \ - g == META_GRAB_OP_KEYBOARD_ESCAPING_GROUP) - -/** - * \defgroup pings Pings - * - * Sometimes we want to see whether a window is responding, - * so we send it a "ping" message and see whether it sends us back a "pong" - * message within a reasonable time. Here we have a system which lets us - * nominate one function to be called if we get the pong in time and another - * function if we don't. The system is rather more complicated than it needs - * to be, since we only ever use it to destroy windows which are asked to - * close themselves and don't do so within a reasonable amount of time, and - * therefore we always use the same callbacks. It's possible that we might - * use it for other things in future, or on the other hand we might decide - * that we're never going to do so and simplify it a bit. - */ - -/** - * Describes a ping on a window. When we send a ping to a window, we build - * one of these structs, and it eventually gets passed to the timeout function - * or to the function which handles the response from the window. If the window - * does or doesn't respond to the ping, we use this information to deal with - * these facts; we have a handler function for each. - * - * \ingroup pings - */ -typedef struct -{ - MetaDisplay *display; - Window xwindow; - guint32 timestamp; - MetaWindowPingFunc ping_reply_func; - MetaWindowPingFunc ping_timeout_func; - void *user_data; - guint ping_timeout_id; -} MetaPingData; - -typedef struct -{ - MetaDisplay *display; - Window xwindow; -} MetaAutoRaiseData; - -/** - * The display we're managing. This is a singleton object. (Historically, - * this was a list of displays, but there was never any way to add more - * than one element to it.) The goofy name is because we don't want it - * to shadow the parameter in its object methods. - */ -static MetaDisplay *the_display = NULL; - -static void meta_spew_event (MetaDisplay *display, - XEvent *event); - -static gboolean event_callback (XEvent *event, - gpointer data); -static Window event_get_modified_window (MetaDisplay *display, - XEvent *event); -static guint32 event_get_time (MetaDisplay *display, - XEvent *event); -static void process_request_frame_extents (MetaDisplay *display, - XEvent *event); -static void process_pong_message (MetaDisplay *display, - XEvent *event); -static void process_selection_request (MetaDisplay *display, - XEvent *event); -static void process_selection_clear (MetaDisplay *display, - XEvent *event); - -static void update_window_grab_modifiers (MetaDisplay *display); - -static void prefs_changed_callback (MetaPreference pref, - void *data); - -static void sanity_check_timestamps (MetaDisplay *display, - guint32 known_good_timestamp); - -MetaGroup* get_focussed_group (MetaDisplay *display); - -/** - * Destructor for MetaPingData structs. Will destroy the - * event source for the struct as well. - * - * \ingroup pings - */ -static void -ping_data_free (MetaPingData *ping_data) -{ - /* Remove the timeout */ - if (ping_data->ping_timeout_id != 0) - g_source_remove (ping_data->ping_timeout_id); - - g_free (ping_data); -} - -/** - * Frees every pending ping structure for the given X window on the - * given display. This means that we also destroy the timeouts. - * - * \param display The display the window appears on - * \param xwindow The X ID of the window whose pings we should remove - * - * \ingroup pings - * - */ -static void -remove_pending_pings_for_window (MetaDisplay *display, Window xwindow) -{ - GSList *tmp; - GSList *dead; - - /* could obviously be more efficient, don't care */ - - /* build list to be removed */ - dead = NULL; - for (tmp = display->pending_pings; tmp; tmp = tmp->next) - { - MetaPingData *ping_data = tmp->data; - - if (ping_data->xwindow == xwindow) - dead = g_slist_prepend (dead, ping_data); - } - - /* remove what we found */ - for (tmp = dead; tmp; tmp = tmp->next) - { - MetaPingData *ping_data = tmp->data; - - display->pending_pings = g_slist_remove (display->pending_pings, ping_data); - ping_data_free (ping_data); - } - - g_slist_free (dead); -} - - -#ifdef HAVE_STARTUP_NOTIFICATION -static void -sn_error_trap_push (SnDisplay *sn_display, - Display *xdisplay) -{ - MetaDisplay *display; - display = meta_display_for_x_display (xdisplay); - if (display != NULL) - meta_error_trap_push (display); -} - -static void -sn_error_trap_pop (SnDisplay *sn_display, - Display *xdisplay) -{ - MetaDisplay *display; - display = meta_display_for_x_display (xdisplay); - if (display != NULL) - meta_error_trap_pop (display, FALSE); -} -#endif - -static void -enable_compositor (MetaDisplay *display, - gboolean composite_windows) -{ - GSList *list; - - if (!META_DISPLAY_HAS_COMPOSITE (display) || - !META_DISPLAY_HAS_DAMAGE (display) || - !META_DISPLAY_HAS_XFIXES (display) || - !META_DISPLAY_HAS_RENDER (display)) - { - meta_warning (_("Missing %s extension required for compositing"), - !META_DISPLAY_HAS_COMPOSITE (display) ? "composite" : - !META_DISPLAY_HAS_DAMAGE (display) ? "damage" : - !META_DISPLAY_HAS_XFIXES (display) ? "xfixes" : "render"); - return; - } - - if (!display->compositor) - display->compositor = meta_compositor_new (display); - - if (!display->compositor) - return; - - for (list = display->screens; list != NULL; list = list->next) - { - MetaScreen *screen = list->data; - - meta_compositor_manage_screen (screen->display->compositor, - screen); - - if (composite_windows) - meta_screen_composite_all_windows (screen); - } -} - -static void -disable_compositor (MetaDisplay *display) -{ - GSList *list; - - if (!display->compositor) - return; - - for (list = display->screens; list != NULL; list = list->next) - { - MetaScreen *screen = list->data; - - meta_compositor_unmanage_screen (screen->display->compositor, - screen); - } - - meta_compositor_destroy (display->compositor); - display->compositor = NULL; -} - -/** - * Opens a new display, sets it up, initialises all the X extensions - * we will need, and adds it to the list of displays. - * - * \return True if the display was opened successfully, and False - * otherwise-- that is, if the display doesn't exist or it already - * has a window manager. - * - * \ingroup main - */ -gboolean -meta_display_open (void) -{ - Display *xdisplay; - GSList *screens; - GSList *tmp; - int i; - guint32 timestamp; - - /* A list of all atom names, so that we can intern them in one go. */ - char *atom_names[] = { -#define item(x) #x, -#include "atomnames.h" -#undef item - }; - Atom atoms[G_N_ELEMENTS(atom_names)]; - - meta_verbose ("Opening display '%s'\n", XDisplayName (NULL)); - - xdisplay = meta_ui_get_display (); - - if (xdisplay == NULL) - { - meta_warning (_("Failed to open X Window System display '%s'\n"), - XDisplayName (NULL)); - return FALSE; - } - - if (meta_is_syncing ()) - XSynchronize (xdisplay, True); - - g_assert (the_display == NULL); - the_display = g_new (MetaDisplay, 1); - - the_display->closing = 0; - - /* here we use XDisplayName which is what the user - * probably put in, vs. DisplayString(display) which is - * canonicalized by XOpenDisplay() - */ - the_display->name = g_strdup (XDisplayName (NULL)); - the_display->xdisplay = xdisplay; - the_display->error_trap_synced_at_last_pop = TRUE; - the_display->error_traps = 0; - the_display->error_trap_handler = NULL; - the_display->server_grab_count = 0; - the_display->display_opening = TRUE; - - the_display->pending_pings = NULL; - the_display->autoraise_timeout_id = 0; - the_display->autoraise_window = NULL; - the_display->focus_window = NULL; - the_display->expected_focus_window = NULL; - the_display->grab_old_window_stacking = NULL; - - the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */ - the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a - terminal has the focus */ - -#ifdef HAVE_XSYNC - the_display->grab_sync_request_alarm = None; -#endif - - /* FIXME copy the checks from GDK probably */ - the_display->static_gravity_works = g_getenv ("METACITY_USE_STATIC_GRAVITY") != NULL; - - meta_bell_init (the_display); - - meta_display_init_keys (the_display); - - update_window_grab_modifiers (the_display); - - meta_prefs_add_listener (prefs_changed_callback, the_display); - - meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names)); - XInternAtoms (the_display->xdisplay, atom_names, G_N_ELEMENTS (atom_names), - False, atoms); - { - int i = 0; -#define item(x) the_display->atom_##x = atoms[i++]; -#include "atomnames.h" -#undef item - } - - the_display->prop_hooks = NULL; - meta_display_init_window_prop_hooks (the_display); - the_display->group_prop_hooks = NULL; - meta_display_init_group_prop_hooks (the_display); - - /* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK, - * created in screen_new - */ - the_display->leader_window = None; - the_display->timestamp_pinging_window = None; - - the_display->xinerama_cache_invalidated = TRUE; - - the_display->groups_by_leader = NULL; - - the_display->window_with_menu = NULL; - the_display->window_menu = NULL; - - the_display->screens = NULL; - the_display->active_screen = NULL; - -#ifdef HAVE_STARTUP_NOTIFICATION - the_display->sn_display = sn_display_new (the_display->xdisplay, - sn_error_trap_push, - sn_error_trap_pop); -#endif - - the_display->events = NULL; - - /* Get events */ - meta_ui_add_event_func (the_display->xdisplay, - event_callback, - the_display); - - the_display->window_ids = g_hash_table_new (meta_unsigned_long_hash, - meta_unsigned_long_equal); - - i = 0; - while (i < N_IGNORED_SERIALS) - { - the_display->ignored_serials[i] = 0; - ++i; - } - the_display->ungrab_should_not_cause_focus_window = None; - - the_display->current_time = CurrentTime; - the_display->sentinel_counter = 0; - - the_display->grab_resize_timeout_id = 0; - the_display->grab_have_keyboard = FALSE; - -#ifdef HAVE_XKB - the_display->last_bell_time = 0; -#endif - - the_display->grab_op = META_GRAB_OP_NONE; - the_display->grab_wireframe_active = FALSE; - the_display->grab_window = NULL; - the_display->grab_screen = NULL; - the_display->grab_resize_popup = NULL; - - the_display->grab_edge_resistance_data = NULL; - -#ifdef HAVE_XSYNC - { - int major, minor; - - the_display->have_xsync = FALSE; - - the_display->xsync_error_base = 0; - the_display->xsync_event_base = 0; - - /* I don't think we really have to fill these in */ - major = SYNC_MAJOR_VERSION; - minor = SYNC_MINOR_VERSION; - - if (!XSyncQueryExtension (the_display->xdisplay, - &the_display->xsync_event_base, - &the_display->xsync_error_base) || - !XSyncInitialize (the_display->xdisplay, - &major, &minor)) - { - the_display->xsync_error_base = 0; - the_display->xsync_event_base = 0; - } - else - the_display->have_xsync = TRUE; - - meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n", - major, minor, - the_display->xsync_error_base, - the_display->xsync_event_base); - } -#else /* HAVE_XSYNC */ - meta_verbose ("Not compiled with Xsync support\n"); -#endif /* !HAVE_XSYNC */ - - -#ifdef HAVE_SHAPE - { - the_display->have_shape = FALSE; - - the_display->shape_error_base = 0; - the_display->shape_event_base = 0; - - if (!XShapeQueryExtension (the_display->xdisplay, - &the_display->shape_event_base, - &the_display->shape_error_base)) - { - the_display->shape_error_base = 0; - the_display->shape_event_base = 0; - } - else - the_display->have_shape = TRUE; - - meta_verbose ("Attempted to init Shape, found error base %d event base %d\n", - the_display->shape_error_base, - the_display->shape_event_base); - } -#else /* HAVE_SHAPE */ - meta_verbose ("Not compiled with Shape support\n"); -#endif /* !HAVE_SHAPE */ - -#ifdef HAVE_RENDER - { - the_display->have_render = FALSE; - - the_display->render_error_base = 0; - the_display->render_event_base = 0; - - if (!XRenderQueryExtension (the_display->xdisplay, - &the_display->render_event_base, - &the_display->render_error_base)) - { - the_display->render_error_base = 0; - the_display->render_event_base = 0; - } - else - the_display->have_render = TRUE; - - meta_verbose ("Attempted to init Render, found error base %d event base %d\n", - the_display->render_error_base, - the_display->render_event_base); - } -#else /* HAVE_RENDER */ - meta_verbose ("Not compiled with Render support\n"); -#endif /* !HAVE_RENDER */ - -#ifdef HAVE_COMPOSITE_EXTENSIONS - { - the_display->have_composite = FALSE; - - the_display->composite_error_base = 0; - the_display->composite_event_base = 0; - - if (!XCompositeQueryExtension (the_display->xdisplay, - &the_display->composite_event_base, - &the_display->composite_error_base)) - { - the_display->composite_error_base = 0; - the_display->composite_event_base = 0; - } - else - { - the_display->composite_major_version = 0; - the_display->composite_minor_version = 0; - if (XCompositeQueryVersion (the_display->xdisplay, - &the_display->composite_major_version, - &the_display->composite_minor_version)) - { - the_display->have_composite = TRUE; - } - else - { - the_display->composite_major_version = 0; - the_display->composite_minor_version = 0; - } - } - - meta_verbose ("Attempted to init Composite, found error base %d event base %d " - "extn ver %d %d\n", - the_display->composite_error_base, - the_display->composite_event_base, - the_display->composite_major_version, - the_display->composite_minor_version); - - the_display->have_damage = FALSE; - - the_display->damage_error_base = 0; - the_display->damage_event_base = 0; - - if (!XDamageQueryExtension (the_display->xdisplay, - &the_display->damage_event_base, - &the_display->damage_error_base)) - { - the_display->damage_error_base = 0; - the_display->damage_event_base = 0; - } - else - the_display->have_damage = TRUE; - - meta_verbose ("Attempted to init Damage, found error base %d event base %d\n", - the_display->damage_error_base, - the_display->damage_event_base); - - the_display->have_xfixes = FALSE; - - the_display->xfixes_error_base = 0; - the_display->xfixes_event_base = 0; - - if (!XFixesQueryExtension (the_display->xdisplay, - &the_display->xfixes_event_base, - &the_display->xfixes_error_base)) - { - the_display->xfixes_error_base = 0; - the_display->xfixes_event_base = 0; - } - else - the_display->have_xfixes = TRUE; - - meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n", - the_display->xfixes_error_base, - the_display->xfixes_event_base); - } -#else /* HAVE_COMPOSITE_EXTENSIONS */ - meta_verbose ("Not compiled with Composite support\n"); -#endif /* !HAVE_COMPOSITE_EXTENSIONS */ - -#ifdef HAVE_XCURSOR - { - XcursorSetTheme (the_display->xdisplay, meta_prefs_get_cursor_theme ()); - XcursorSetDefaultSize (the_display->xdisplay, meta_prefs_get_cursor_size ()); - } -#else /* HAVE_XCURSOR */ - meta_verbose ("Not compiled with Xcursor support\n"); -#endif /* !HAVE_XCURSOR */ - - /* Create the leader window here. Set its properties and - * use the timestamp from one of the PropertyNotify events - * that will follow. - */ - { - gulong data[1]; - XEvent event; - - /* We only care about the PropertyChangeMask in the next 30 or so lines of - * code. Note that gdk will at some point unset the PropertyChangeMask for - * this window, so we can't rely on it still being set later. See bug - * 354213 for details. - */ - the_display->leader_window = - meta_create_offscreen_window (the_display->xdisplay, - DefaultRootWindow (the_display->xdisplay), - PropertyChangeMask); - - meta_prop_set_utf8_string_hint (the_display, - the_display->leader_window, - the_display->atom__NET_WM_NAME, - "Metacity"); - - meta_prop_set_utf8_string_hint (the_display, - the_display->leader_window, - the_display->atom__METACITY_VERSION, - VERSION); - - data[0] = the_display->leader_window; - XChangeProperty (the_display->xdisplay, - the_display->leader_window, - the_display->atom__NET_SUPPORTING_WM_CHECK, - XA_WINDOW, - 32, PropModeReplace, (guchar*) data, 1); - - XWindowEvent (the_display->xdisplay, - the_display->leader_window, - PropertyChangeMask, - &event); - - timestamp = event.xproperty.time; - - /* Make it painfully clear that we can't rely on PropertyNotify events on - * this window, as per bug 354213. - */ - XSelectInput(the_display->xdisplay, - the_display->leader_window, - NoEventMask); - } - - /* Make a little window used only for pinging the server for timestamps; note - * that meta_create_offscreen_window already selects for PropertyChangeMask. - */ - the_display->timestamp_pinging_window = - meta_create_offscreen_window (the_display->xdisplay, - DefaultRootWindow (the_display->xdisplay), - PropertyChangeMask); - - the_display->last_focus_time = timestamp; - the_display->last_user_time = timestamp; - the_display->compositor = NULL; - - screens = NULL; - - i = 0; - while (i < ScreenCount (xdisplay)) - { - MetaScreen *screen; - - screen = meta_screen_new (the_display, i, timestamp); - - if (screen) - screens = g_slist_prepend (screens, screen); - ++i; - } - - the_display->screens = screens; - - if (screens == NULL) - { - /* This would typically happen because all the screens already - * have window managers. - */ - meta_display_close (the_display, timestamp); - return FALSE; - } - - /* We don't composite the windows here because they will be composited - faster with the call to meta_screen_manage_all_windows further down - the code */ - if (meta_prefs_get_compositing_manager ()) - enable_compositor (the_display, FALSE); - - meta_display_grab (the_display); - - /* Now manage all existing windows */ - tmp = the_display->screens; - while (tmp != NULL) - { - MetaScreen *screen = tmp->data; - - meta_screen_manage_all_windows (screen); - - tmp = tmp->next; - } - - { - Window focus; - int ret_to; - - /* kinda bogus because GetInputFocus has no possible errors */ - meta_error_trap_push (the_display); - - /* FIXME: This is totally broken; see comment 9 of bug 88194 about this */ - focus = None; - ret_to = RevertToPointerRoot; - XGetInputFocus (the_display->xdisplay, &focus, &ret_to); - - /* Force a new FocusIn (does this work?) */ - - /* Use the same timestamp that was passed to meta_screen_new(), - * as it is the most recent timestamp. - */ - if (focus == None || focus == PointerRoot) - /* Just focus the no_focus_window on the first screen */ - meta_display_focus_the_no_focus_window (the_display, - the_display->screens->data, - timestamp); - else - { - MetaWindow * window; - window = meta_display_lookup_x_window (the_display, focus); - if (window) - meta_display_set_input_focus_window (the_display, window, FALSE, timestamp); - else - /* Just focus the no_focus_window on the first screen */ - meta_display_focus_the_no_focus_window (the_display, - the_display->screens->data, - timestamp); - } - - meta_error_trap_pop (the_display, FALSE); - } - - meta_display_ungrab (the_display); - - /* Done opening new display */ - the_display->display_opening = FALSE; - - return TRUE; -} - -static void -listify_func (gpointer key, gpointer value, gpointer data) -{ - GSList **listp; - - listp = data; - *listp = g_slist_prepend (*listp, value); -} - -static gint -ptrcmp (gconstpointer a, gconstpointer b) -{ - if (a < b) - return -1; - else if (a > b) - return 1; - else - return 0; -} - -GSList* -meta_display_list_windows (MetaDisplay *display) -{ - GSList *winlist; - GSList *tmp; - GSList *prev; - - winlist = NULL; - g_hash_table_foreach (display->window_ids, - listify_func, - &winlist); - - /* Uniquify the list, since both frame windows and plain - * windows are in the hash - */ - winlist = g_slist_sort (winlist, ptrcmp); - - prev = NULL; - tmp = winlist; - while (tmp != NULL) - { - GSList *next; - - next = tmp->next; - - if (next && - next->data == tmp->data) - { - /* Delete tmp from list */ - - if (prev) - prev->next = next; - - if (tmp == winlist) - winlist = next; - - g_slist_free_1 (tmp); - - /* leave prev unchanged */ - } - else - { - prev = tmp; - } - - tmp = next; - } - - return winlist; -} - -void -meta_display_close (MetaDisplay *display, - guint32 timestamp) -{ - GSList *tmp; - - g_assert (display != NULL); - - if (display->closing != 0) - { - /* The display's already been closed. */ - return; - } - - if (display->error_traps > 0) - meta_bug ("Display closed with error traps pending\n"); - - display->closing += 1; - - meta_prefs_remove_listener (prefs_changed_callback, display); - - meta_display_remove_autoraise_callback (display); - - if (display->grab_old_window_stacking) - g_list_free (display->grab_old_window_stacking); - - /* Stop caring about events */ - meta_ui_remove_event_func (display->xdisplay, - event_callback, - display); - - /* Free all screens */ - tmp = display->screens; - while (tmp != NULL) - { - MetaScreen *screen = tmp->data; - meta_screen_free (screen, timestamp); - tmp = tmp->next; - } - - g_slist_free (display->screens); - display->screens = NULL; - -#ifdef HAVE_STARTUP_NOTIFICATION - if (display->sn_display) - { - sn_display_unref (display->sn_display); - display->sn_display = NULL; - } -#endif - - /* Must be after all calls to meta_window_free() since they - * unregister windows - */ - g_hash_table_destroy (display->window_ids); - - if (display->leader_window != None) - XDestroyWindow (display->xdisplay, display->leader_window); - - XFlush (display->xdisplay); - - meta_display_free_window_prop_hooks (display); - meta_display_free_group_prop_hooks (display); - - g_free (display->name); - - meta_display_shutdown_keys (display); - - if (display->compositor) - meta_compositor_destroy (display->compositor); - - g_free (display); - display = NULL; - - meta_quit (META_EXIT_SUCCESS); -} - -MetaScreen* -meta_display_screen_for_root (MetaDisplay *display, - Window xroot) -{ - GSList *tmp; - - tmp = display->screens; - while (tmp != NULL) - { - MetaScreen *screen = tmp->data; - - if (xroot == screen->xroot) - return screen; - - tmp = tmp->next; - } - - return NULL; -} - -MetaScreen* -meta_display_screen_for_xwindow (MetaDisplay *display, - Window xwindow) -{ - XWindowAttributes attr; - int result; - - meta_error_trap_push (display); - attr.screen = NULL; - result = XGetWindowAttributes (display->xdisplay, xwindow, &attr); - meta_error_trap_pop (display, TRUE); - - /* Note, XGetWindowAttributes is on all kinds of crack - * and returns 1 on success 0 on failure, rather than Success - * on success. - */ - if (result == 0 || attr.screen == NULL) - return NULL; - - return meta_display_screen_for_x_screen (display, attr.screen); -} - -MetaScreen* -meta_display_screen_for_x_screen (MetaDisplay *display, - Screen *xscreen) -{ - GSList *tmp; - - tmp = display->screens; - while (tmp != NULL) - { - MetaScreen *screen = tmp->data; - - if (xscreen == screen->xscreen) - return screen; - - tmp = tmp->next; - } - - return NULL; -} - -/* Grab/ungrab routines taken from fvwm */ -void -meta_display_grab (MetaDisplay *display) -{ - if (display->server_grab_count == 0) - { - XGrabServer (display->xdisplay); - } - display->server_grab_count += 1; - meta_verbose ("Grabbing display, grab count now %d\n", - display->server_grab_count); -} - -void -meta_display_ungrab (MetaDisplay *display) -{ - if (display->server_grab_count == 0) - meta_bug ("Ungrabbed non-grabbed server\n"); - - display->server_grab_count -= 1; - if (display->server_grab_count == 0) - { - /* FIXME we want to purge all pending "queued" stuff - * at this point, such as window hide/show - */ - XUngrabServer (display->xdisplay); - XFlush (display->xdisplay); - } - - meta_verbose ("Ungrabbing display, grab count now %d\n", - display->server_grab_count); -} - -/** - * Returns the singleton MetaDisplay if "xdisplay" matches the X display it's - * managing; otherwise gives a warning and returns NULL. When we were claiming - * to be able to manage multiple displays, this was supposed to find the - * display out of the list which matched that display. Now it's merely an - * extra sanity check. - * - * \param xdisplay An X display - * \return The singleton X display, or NULL if "xdisplay" isn't the one - * we're managing. - */ -MetaDisplay* -meta_display_for_x_display (Display *xdisplay) -{ - if (the_display->xdisplay == xdisplay) - return the_display; - - meta_warning ("Could not find display for X display %p, probably going to crash\n", - xdisplay); - - return NULL; -} - -/** - * Accessor for the singleton MetaDisplay. - * - * \return The only MetaDisplay there is. This can be NULL, but only - * during startup. - */ -MetaDisplay* -meta_get_display (void) -{ - return the_display; -} - -#ifdef WITH_VERBOSE_MODE -static gboolean dump_events = TRUE; -#endif - -static gboolean -grab_op_is_mouse_only (MetaGrabOp op) -{ - switch (op) - { - case META_GRAB_OP_MOVING: - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_E: - return TRUE; - - default: - return FALSE; - } -} - -static gboolean -grab_op_is_mouse (MetaGrabOp op) -{ - switch (op) - { - case META_GRAB_OP_MOVING: - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_MOVING: - return TRUE; - - default: - return FALSE; - } -} - -static gboolean -grab_op_is_keyboard (MetaGrabOp op) -{ - switch (op) - { - case META_GRAB_OP_KEYBOARD_MOVING: - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_TABBING_NORMAL: - case META_GRAB_OP_KEYBOARD_TABBING_DOCK: - case META_GRAB_OP_KEYBOARD_TABBING_GROUP: - case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: - case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: - case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: - case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: - return TRUE; - - default: - return FALSE; - } -} - -gboolean -meta_grab_op_is_resizing (MetaGrabOp op) -{ - switch (op) - { - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - return TRUE; - - default: - return FALSE; - } -} - -gboolean -meta_grab_op_is_moving (MetaGrabOp op) -{ - switch (op) - { - case META_GRAB_OP_MOVING: - case META_GRAB_OP_KEYBOARD_MOVING: - return TRUE; - - default: - return FALSE; - } -} - -/* Get time of current event, or CurrentTime if none. */ -guint32 -meta_display_get_current_time (MetaDisplay *display) -{ - return display->current_time; -} - -/* Get a timestamp, even if it means a roundtrip */ -guint32 -meta_display_get_current_time_roundtrip (MetaDisplay *display) -{ - guint32 timestamp; - - timestamp = meta_display_get_current_time (display); - if (timestamp == CurrentTime) - { - XEvent property_event; - - /* Using the property XA_PRIMARY because it's safe; nothing - * would use it as a property. The type doesn't matter. - */ - XChangeProperty (display->xdisplay, - display->timestamp_pinging_window, - XA_PRIMARY, XA_STRING, 8, - PropModeAppend, NULL, 0); - XWindowEvent (display->xdisplay, - display->timestamp_pinging_window, - PropertyChangeMask, - &property_event); - timestamp = property_event.xproperty.time; - } - - sanity_check_timestamps (display, timestamp); - - return timestamp; -} - -static void -add_ignored_serial (MetaDisplay *display, - unsigned long serial) -{ - int i; - - /* don't add the same serial more than once */ - if (display->ignored_serials[N_IGNORED_SERIALS-1] == serial) - return; - - /* shift serials to the left */ - i = 0; - while (i < (N_IGNORED_SERIALS - 1)) - { - display->ignored_serials[i] = display->ignored_serials[i+1]; - ++i; - } - /* put new one on the end */ - display->ignored_serials[i] = serial; -} - -static gboolean -serial_is_ignored (MetaDisplay *display, - unsigned long serial) -{ - int i; - - i = 0; - while (i < N_IGNORED_SERIALS) - { - if (display->ignored_serials[i] == serial) - return TRUE; - ++i; - } - return FALSE; -} - -static void -reset_ignores (MetaDisplay *display) -{ - int i; - - i = 0; - while (i < N_IGNORED_SERIALS) - { - display->ignored_serials[i] = 0; - ++i; - } - - display->ungrab_should_not_cause_focus_window = None; -} - -static gboolean -window_raise_with_delay_callback (void *data) -{ - MetaWindow *window; - MetaAutoRaiseData *auto_raise; - - auto_raise = data; - - meta_topic (META_DEBUG_FOCUS, - "In autoraise callback for window 0x%lx\n", - auto_raise->xwindow); - - auto_raise->display->autoraise_timeout_id = 0; - auto_raise->display->autoraise_window = NULL; - - window = meta_display_lookup_x_window (auto_raise->display, - auto_raise->xwindow); - - if (window == NULL) - return FALSE; - - /* If we aren't already on top, check whether the pointer is inside - * the window and raise the window if so. - */ - if (meta_stack_get_top (window->screen->stack) != window) - { - int x, y, root_x, root_y; - Window root, child; - unsigned int mask; - gboolean same_screen; - gboolean point_in_window; - - meta_error_trap_push (window->display); - same_screen = XQueryPointer (window->display->xdisplay, - window->xwindow, - &root, &child, - &root_x, &root_y, &x, &y, &mask); - meta_error_trap_pop (window->display, TRUE); - - point_in_window = - (window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) || - (window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect)); - if (same_screen && point_in_window) - meta_window_raise (window); - else - meta_topic (META_DEBUG_FOCUS, - "Pointer not inside window, not raising %s\n", - window->desc); - } - - return FALSE; -} - -void -meta_display_queue_autoraise_callback (MetaDisplay *display, - MetaWindow *window) -{ - MetaAutoRaiseData *auto_raise_data; - - meta_topic (META_DEBUG_FOCUS, - "Queuing an autoraise timeout for %s with delay %d\n", - window->desc, - meta_prefs_get_auto_raise_delay ()); - - auto_raise_data = g_new (MetaAutoRaiseData, 1); - auto_raise_data->display = window->display; - auto_raise_data->xwindow = window->xwindow; - - if (display->autoraise_timeout_id != 0) - g_source_remove (display->autoraise_timeout_id); - - display->autoraise_timeout_id = - g_timeout_add_full (G_PRIORITY_DEFAULT, - meta_prefs_get_auto_raise_delay (), - window_raise_with_delay_callback, - auto_raise_data, - g_free); - display->autoraise_window = window; -} - -#if 0 -static void -handle_net_restack_window (MetaDisplay* display, - XEvent *event) -{ - MetaWindow *window; - - window = meta_display_lookup_x_window (display, - event->xclient.window); - - if (window) - { - /* FIXME: The EWMH includes a sibling for the restack request, but we - * (stupidly) don't currently support these types of raises. - * - * Also, unconditionally following these is REALLY stupid--we should - * combine this code with the stuff in - * meta_window_configure_request() which is smart about whether to - * follow the request or do something else (though not smart enough - * and is also too stupid to handle the sibling stuff). - */ - switch (event->xclient.data.l[2]) - { - case Above: - meta_window_raise (window); - break; - case Below: - meta_window_lower (window); - break; - case TopIf: - case BottomIf: - case Opposite: - break; - } - } -} -#endif - -/** - * This is the most important function in the whole program. It is the heart, - * it is the nexus, it is the Grand Central Station of Metacity's world. - * When we create a MetaDisplay, we ask GDK to pass *all* events for *all* - * windows to this function. So every time anything happens that we might - * want to know about, this function gets called. You see why it gets a bit - * busy around here. Most of this function is a ginormous switch statement - * dealing with all the kinds of events that might turn up. - * - * \param event The event that just happened - * \param data The MetaDisplay that events are coming from, cast to a gpointer - * so that it can be sent to a callback - * - * \ingroup main - */ -static gboolean -event_callback (XEvent *event, - gpointer data) -{ - MetaWindow *window; - MetaWindow *property_for_window; - MetaDisplay *display; - Window modified; - gboolean frame_was_receiver; - gboolean filter_out_event; - - display = data; - -#ifdef WITH_VERBOSE_MODE - if (dump_events) - meta_spew_event (display, event); -#endif - -#ifdef HAVE_STARTUP_NOTIFICATION - sn_display_process_event (display->sn_display, event); -#endif - - filter_out_event = FALSE; - display->current_time = event_get_time (display, event); - display->xinerama_cache_invalidated = TRUE; - - modified = event_get_modified_window (display, event); - - if (event->type == ButtonPress) - { - /* filter out scrollwheel */ - if (event->xbutton.button == 4 || - event->xbutton.button == 5) - return FALSE; - } - else if (event->type == UnmapNotify) - { - if (meta_ui_window_should_not_cause_focus (display->xdisplay, - modified)) - { - add_ignored_serial (display, event->xany.serial); - meta_topic (META_DEBUG_FOCUS, - "Adding EnterNotify serial %lu to ignored focus serials\n", - event->xany.serial); - } - } - else if (event->type == LeaveNotify && - event->xcrossing.mode == NotifyUngrab && - modified == display->ungrab_should_not_cause_focus_window) - { - add_ignored_serial (display, event->xany.serial); - meta_topic (META_DEBUG_FOCUS, - "Adding LeaveNotify serial %lu to ignored focus serials\n", - event->xany.serial); - } - - if (modified != None) - window = meta_display_lookup_x_window (display, modified); - else - window = NULL; - - /* We only want to respond to _NET_WM_USER_TIME property notify - * events on _NET_WM_USER_TIME_WINDOW windows; in particular, - * responding to UnmapNotify events is kind of bad. - */ - property_for_window = NULL; - if (window && modified == window->user_time_window) - { - property_for_window = window; - window = NULL; - } - - - frame_was_receiver = FALSE; - if (window && - window->frame && - modified == window->frame->xwindow) - { - /* Note that if the frame and the client both have an - * XGrabButton (as is normal with our setup), the event - * goes to the frame. - */ - frame_was_receiver = TRUE; - meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n", - window->desc); - } - -#ifdef HAVE_XSYNC - if (META_DISPLAY_HAS_XSYNC (display) && - event->type == (display->xsync_event_base + XSyncAlarmNotify) && - ((XSyncAlarmNotifyEvent*)event)->alarm == display->grab_sync_request_alarm) - { - filter_out_event = TRUE; /* GTK doesn't want to see this really */ - - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window != NULL && - grab_op_is_mouse (display->grab_op)) - meta_window_handle_mouse_grab_op_event (display->grab_window, event); - } -#endif /* HAVE_XSYNC */ - -#ifdef HAVE_SHAPE - if (META_DISPLAY_HAS_SHAPE (display) && - event->type == (display->shape_event_base + ShapeNotify)) - { - filter_out_event = TRUE; /* GTK doesn't want to see this really */ - - if (window && !frame_was_receiver) - { - XShapeEvent *sev = (XShapeEvent*) event; - - if (sev->kind == ShapeBounding) - { - if (sev->shaped && !window->has_shape) - { - window->has_shape = TRUE; - meta_topic (META_DEBUG_SHAPES, - "Window %s now has a shape\n", - window->desc); - } - else if (!sev->shaped && window->has_shape) - { - window->has_shape = FALSE; - meta_topic (META_DEBUG_SHAPES, - "Window %s no longer has a shape\n", - window->desc); - } - else - { - meta_topic (META_DEBUG_SHAPES, - "Window %s shape changed\n", - window->desc); - } - - if (window->frame) - { - window->frame->need_reapply_frame_shape = TRUE; - meta_warning("from event callback\n"); - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - } - } - } - else - { - meta_topic (META_DEBUG_SHAPES, - "ShapeNotify not on a client window (window %s frame_was_receiver = %d)\n", - window ? window->desc : "(none)", - frame_was_receiver); - } - } -#endif /* HAVE_SHAPE */ - - if (window && ((event->type == KeyPress) || (event->type == ButtonPress))) - { - if (CurrentTime == display->current_time) - { - /* We can't use missing (i.e. invalid) timestamps to set user time, - * nor do we want to use them to sanity check other timestamps. - * See bug 313490 for more details. - */ - meta_warning ("Event has no timestamp! You may be using a broken " - "program such as xse. Please ask the authors of that " - "program to fix it.\n"); - } - else - { - meta_window_set_user_time (window, display->current_time); - sanity_check_timestamps (display, display->current_time); - } - } - - switch (event->type) - { - case KeyPress: - case KeyRelease: - meta_display_process_key_event (display, window, event); - break; - case ButtonPress: - if ((window && - grab_op_is_mouse (display->grab_op) && - display->grab_button != (int) event->xbutton.button && - display->grab_window == window) || - grab_op_is_keyboard (display->grab_op)) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Ending grab op %u on window %s due to button press\n", - display->grab_op, - (display->grab_window ? - display->grab_window->desc : - "none")); - if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) - { - MetaScreen *screen; - meta_topic (META_DEBUG_WINDOW_OPS, - "Syncing to old stack positions.\n"); - screen = - meta_display_screen_for_root (display, event->xany.window); - - if (screen!=NULL) - meta_stack_set_positions (screen->stack, - display->grab_old_window_stacking); - } - meta_display_end_grab_op (display, - event->xbutton.time); - } - else if (window && display->grab_op == META_GRAB_OP_NONE) - { - gboolean begin_move = FALSE; - unsigned int grab_mask; - gboolean unmodified; - - grab_mask = display->window_grab_modifiers; - if (g_getenv ("METACITY_DEBUG_BUTTON_GRABS")) - grab_mask |= ControlMask; - - /* Two possible sources of an unmodified event; one is a - * client that's letting button presses pass through to the - * frame, the other is our focus_window_grab on unmodified - * button 1. So for all such events we focus the window. - */ - unmodified = (event->xbutton.state & grab_mask) == 0; - - if (unmodified || - event->xbutton.button == 1) - { - /* don't focus if frame received, will be lowered in - * frames.c or special-cased if the click was on a - * minimize/close button. - */ - if (!frame_was_receiver) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - else - meta_topic (META_DEBUG_FOCUS, - "Not raising window on click due to don't-raise-on-click option\n"); - - /* Don't focus panels--they must explicitly request focus. - * See bug 160470 - */ - if (window->type != META_WINDOW_DOCK) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing %s due to unmodified button %u press (display.c)\n", - window->desc, event->xbutton.button); - meta_window_focus (window, event->xbutton.time); - } - else - /* However, do allow terminals to lose focus due to new - * window mappings after the user clicks on a panel. - */ - display->allow_terminal_deactivation = TRUE; - } - - /* you can move on alt-click but not on - * the click-to-focus - */ - if (!unmodified) - begin_move = TRUE; - } - else if (!unmodified && event->xbutton.button == 2) - { - if (window->has_resize_func) - { - gboolean north, south; - gboolean west, east; - int root_x, root_y; - MetaGrabOp op; - - meta_window_get_position (window, &root_x, &root_y); - - west = event->xbutton.x_root < (root_x + 1 * window->rect.width / 3); - east = event->xbutton.x_root > (root_x + 2 * window->rect.width / 3); - north = event->xbutton.y_root < (root_y + 1 * window->rect.height / 3); - south = event->xbutton.y_root > (root_y + 2 * window->rect.height / 3); - - if (north && west) - op = META_GRAB_OP_RESIZING_NW; - else if (north && east) - op = META_GRAB_OP_RESIZING_NE; - else if (south && west) - op = META_GRAB_OP_RESIZING_SW; - else if (south && east) - op = META_GRAB_OP_RESIZING_SE; - else if (north) - op = META_GRAB_OP_RESIZING_N; - else if (west) - op = META_GRAB_OP_RESIZING_W; - else if (east) - op = META_GRAB_OP_RESIZING_E; - else if (south) - op = META_GRAB_OP_RESIZING_S; - else /* Middle region is no-op to avoid user triggering wrong action */ - op = META_GRAB_OP_NONE; - - if (op != META_GRAB_OP_NONE) - meta_display_begin_grab_op (display, - window->screen, - window, - op, - TRUE, - FALSE, - event->xbutton.button, - 0, - event->xbutton.time, - event->xbutton.x_root, - event->xbutton.y_root); - } - } - else if (event->xbutton.button == 3) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_show_menu (window, - event->xbutton.x_root, - event->xbutton.y_root, - event->xbutton.button, - event->xbutton.time); - } - - if (!frame_was_receiver && unmodified) - { - /* This is from our synchronous grab since - * it has no modifiers and was on the client window - */ - int mode; - - /* When clicking a different app in click-to-focus - * in application-based mode, and the different - * app is not a dock or desktop, eat the focus click. - */ - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK && - meta_prefs_get_application_based () && - !window->has_focus && - window->type != META_WINDOW_DOCK && - window->type != META_WINDOW_DESKTOP && - (display->focus_window == NULL || - !meta_window_same_application (window, - display->focus_window))) - mode = AsyncPointer; /* eat focus click */ - else - mode = ReplayPointer; /* give event back */ - - meta_verbose ("Allowing events mode %s time %u\n", - mode == AsyncPointer ? "AsyncPointer" : "ReplayPointer", - (unsigned int)event->xbutton.time); - - XAllowEvents (display->xdisplay, - mode, event->xbutton.time); - } - - if (begin_move && window->has_move_func) - { - meta_display_begin_grab_op (display, - window->screen, - window, - META_GRAB_OP_MOVING, - TRUE, - FALSE, - event->xbutton.button, - 0, - event->xbutton.time, - event->xbutton.x_root, - event->xbutton.y_root); - } - } - break; - case ButtonRelease: - if (display->grab_window == window && - grab_op_is_mouse (display->grab_op)) - meta_window_handle_mouse_grab_op_event (window, event); - break; - case MotionNotify: - if (display->grab_window == window && - grab_op_is_mouse (display->grab_op)) - meta_window_handle_mouse_grab_op_event (window, event); - break; - case EnterNotify: - if (display->grab_window == window && - grab_op_is_mouse (display->grab_op)) - { - meta_window_handle_mouse_grab_op_event (window, event); - break; - } - - /* If the mouse switches screens, active the default window on the new - * screen; this will make keybindings and workspace-launched items - * actually appear on the right screen. - */ - { - MetaScreen *new_screen = - meta_display_screen_for_root (display, event->xcrossing.root); - - if (new_screen != NULL && display->active_screen != new_screen) - meta_workspace_focus_default_window (new_screen->active_workspace, - NULL, - event->xcrossing.time); - } - - /* Check if we've entered a window; do this even if window->has_focus to - * avoid races. - */ - if (window && !serial_is_ignored (display, event->xany.serial) && - event->xcrossing.mode != NotifyGrab && - event->xcrossing.mode != NotifyUngrab && - event->xcrossing.detail != NotifyInferior && - meta_display_focus_sentinel_clear (display)) - { - switch (meta_prefs_get_focus_mode ()) - { - case META_FOCUS_MODE_SLOPPY: - case META_FOCUS_MODE_MOUSE: - display->mouse_mode = TRUE; - if (window->type != META_WINDOW_DOCK && - window->type != META_WINDOW_DESKTOP) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing %s due to enter notify with serial %lu " - "at time %lu, and setting display->mouse_mode to " - "TRUE.\n", - window->desc, - event->xany.serial, - event->xcrossing.time); - - meta_window_focus (window, event->xcrossing.time); - - /* stop ignoring stuff */ - reset_ignores (display); - - if (meta_prefs_get_auto_raise ()) - { - meta_display_queue_autoraise_callback (display, window); - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Auto raise is disabled\n"); - } - } - /* In mouse focus mode, we defocus when the mouse *enters* - * the DESKTOP window, instead of defocusing on LeaveNotify. - * This is because having the mouse enter override-redirect - * child windows unfortunately causes LeaveNotify events that - * we can't distinguish from the mouse actually leaving the - * toplevel window as we expect. But, since we filter out - * EnterNotify events on override-redirect windows, this - * alternative mechanism works great. - */ - if (window->type == META_WINDOW_DESKTOP && - meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE && - display->expected_focus_window != NULL) - { - meta_topic (META_DEBUG_FOCUS, - "Unsetting focus from %s due to mouse entering " - "the DESKTOP window\n", - display->expected_focus_window->desc); - meta_display_focus_the_no_focus_window (display, - window->screen, - event->xcrossing.time); - } - break; - case META_FOCUS_MODE_CLICK: - break; - } - - if (window->type == META_WINDOW_DOCK) - meta_window_raise (window); - } - break; - case LeaveNotify: - if (display->grab_window == window && - grab_op_is_mouse (display->grab_op)) - meta_window_handle_mouse_grab_op_event (window, event); - else if (window != NULL) - { - if (window->type == META_WINDOW_DOCK && - event->xcrossing.mode != NotifyGrab && - event->xcrossing.mode != NotifyUngrab && - !window->has_focus) - meta_window_lower (window); - } - break; - case FocusIn: - case FocusOut: - if (window) - { - meta_window_notify_focus (window, event); - } - else if (meta_display_xwindow_is_a_no_focus_window (display, - event->xany.window)) - { - meta_topic (META_DEBUG_FOCUS, - "Focus %s event received on no_focus_window 0x%lx " - "mode %s detail %s\n", - event->type == FocusIn ? "in" : - event->type == FocusOut ? "out" : - "???", - event->xany.window, - meta_event_mode_to_string (event->xfocus.mode), - meta_event_detail_to_string (event->xfocus.detail)); - } - else - { - MetaScreen *screen = - meta_display_screen_for_root(display, - event->xany.window); - if (screen == NULL) - break; - - meta_topic (META_DEBUG_FOCUS, - "Focus %s event received on root window 0x%lx " - "mode %s detail %s\n", - event->type == FocusIn ? "in" : - event->type == FocusOut ? "out" : - "???", - event->xany.window, - meta_event_mode_to_string (event->xfocus.mode), - meta_event_detail_to_string (event->xfocus.detail)); - - if (event->type == FocusIn && - event->xfocus.detail == NotifyDetailNone) - { - meta_topic (META_DEBUG_FOCUS, - "Focus got set to None, probably due to " - "brain-damage in the X protocol (see bug " - "125492). Setting the default focus window.\n"); - meta_workspace_focus_default_window (screen->active_workspace, - NULL, - meta_display_get_current_time_roundtrip (display)); - } - else if (event->type == FocusIn && - event->xfocus.mode == NotifyNormal && - event->xfocus.detail == NotifyInferior) - { - meta_topic (META_DEBUG_FOCUS, - "Focus got set to root window, probably due to " - "gnome-session logout dialog usage (see bug " - "153220). Setting the default focus window.\n"); - meta_workspace_focus_default_window (screen->active_workspace, - NULL, - meta_display_get_current_time_roundtrip (display)); - } - - } - break; - case KeymapNotify: - break; - case Expose: - break; - case GraphicsExpose: - break; - case NoExpose: - break; - case VisibilityNotify: - break; - case CreateNotify: - break; - - case DestroyNotify: - if (window) - { - /* FIXME: It sucks that DestroyNotify events don't come with - * a timestamp; could we do something better here? Maybe X - * will change one day? - */ - guint32 timestamp; - timestamp = meta_display_get_current_time_roundtrip (display); - - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window == window) - meta_display_end_grab_op (display, timestamp); - - if (frame_was_receiver) - { - meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n", - window->frame->xwindow); - meta_error_trap_push (display); - meta_window_destroy_frame (window->frame->window); - meta_error_trap_pop (display, FALSE); - } - else - { - /* Unmanage destroyed window */ - meta_window_free (window, timestamp); - window = NULL; - } - } - break; - case UnmapNotify: - if (window) - { - /* FIXME: It sucks that UnmapNotify events don't come with - * a timestamp; could we do something better here? Maybe X - * will change one day? - */ - guint32 timestamp; - timestamp = meta_display_get_current_time_roundtrip (display); - - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window == window && - ((window->frame == NULL) || !window->frame->mapped)) - meta_display_end_grab_op (display, timestamp); - - if (!frame_was_receiver) - { - if (window->unmaps_pending == 0) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "Window %s withdrawn\n", - window->desc); - - meta_effect_run_close (window, NULL, NULL); - - /* Unmanage withdrawn window */ - window->withdrawn = TRUE; - meta_window_free (window, timestamp); - window = NULL; - } - else - { - window->unmaps_pending -= 1; - meta_topic (META_DEBUG_WINDOW_STATE, - "Received pending unmap, %d now pending\n", - window->unmaps_pending); - } - } - - /* Unfocus on UnmapNotify, do this after the possible - * window_free above so that window_free can see if window->has_focus - * and move focus to another window - */ - if (window) - meta_window_notify_focus (window, event); - } - break; - case MapNotify: - break; - case MapRequest: - if (window == NULL) - { - window = meta_window_new (display, event->xmaprequest.window, - FALSE); - } - /* if frame was receiver it's some malicious send event or something */ - else if (!frame_was_receiver && window) - { - meta_verbose ("MapRequest on %s mapped = %d minimized = %d\n", - window->desc, window->mapped, window->minimized); - if (window->minimized) - { - meta_window_unminimize (window); - if (window->workspace != window->screen->active_workspace) - { - meta_verbose ("Changing workspace due to MapRequest mapped = %d minimized = %d\n", - window->mapped, window->minimized); - meta_window_change_workspace (window, - window->screen->active_workspace); - } - } - } - break; - case ReparentNotify: - break; - case ConfigureNotify: - /* Handle screen resize */ - { - MetaScreen *screen; - - screen = meta_display_screen_for_root (display, - event->xconfigure.window); - - if (screen != NULL) - { -#ifdef HAVE_RANDR - /* do the resize the official way */ - XRRUpdateConfiguration (event); -#else - /* poke around in Xlib */ - screen->xscreen->width = event->xconfigure.width; - screen->xscreen->height = event->xconfigure.height; -#endif - - meta_screen_resize (screen, - event->xconfigure.width, - event->xconfigure.height); - } - } - break; - case ConfigureRequest: - /* This comment and code is found in both twm and fvwm */ - /* - * According to the July 27, 1988 ICCCM draft, we should ignore size and - * position fields in the WM_NORMAL_HINTS property when we map a window. - * Instead, we'll read the current geometry. Therefore, we should respond - * to configuration requests for windows which have never been mapped. - */ - if (window == NULL) - { - unsigned int xwcm; - XWindowChanges xwc; - - xwcm = event->xconfigurerequest.value_mask & - (CWX | CWY | CWWidth | CWHeight | CWBorderWidth); - - xwc.x = event->xconfigurerequest.x; - xwc.y = event->xconfigurerequest.y; - xwc.width = event->xconfigurerequest.width; - xwc.height = event->xconfigurerequest.height; - xwc.border_width = event->xconfigurerequest.border_width; - - meta_verbose ("Configuring withdrawn window to %d,%d %dx%d border %d (some values may not be in mask)\n", - xwc.x, xwc.y, xwc.width, xwc.height, xwc.border_width); - meta_error_trap_push (display); - XConfigureWindow (display->xdisplay, event->xconfigurerequest.window, - xwcm, &xwc); - meta_error_trap_pop (display, FALSE); - } - else - { - if (!frame_was_receiver) - meta_window_configure_request (window, event); - } - break; - case GravityNotify: - break; - case ResizeRequest: - break; - case CirculateNotify: - break; - case CirculateRequest: - break; - case PropertyNotify: - { - MetaGroup *group; - MetaScreen *screen; - - if (window && !frame_was_receiver) - meta_window_property_notify (window, event); - else if (property_for_window && !frame_was_receiver) - meta_window_property_notify (property_for_window, event); - - group = meta_display_lookup_group (display, - event->xproperty.window); - if (group != NULL) - meta_group_property_notify (group, event); - - screen = NULL; - if (window == NULL && - group == NULL) /* window/group != NULL means it wasn't a root window */ - screen = meta_display_screen_for_root (display, - event->xproperty.window); - - if (screen != NULL) - { - if (event->xproperty.atom == - display->atom__NET_DESKTOP_LAYOUT) - meta_screen_update_workspace_layout (screen); - else if (event->xproperty.atom == - display->atom__NET_DESKTOP_NAMES) - meta_screen_update_workspace_names (screen); -#if 0 - else if (event->xproperty.atom == - display->atom__NET_RESTACK_WINDOW) - handle_net_restack_window (display, event); -#endif - - /* we just use this property as a sentinel to avoid - * certain race conditions. See the comment for the - * sentinel_counter variable declaration in display.h - */ - if (event->xproperty.atom == - display->atom__METACITY_SENTINEL) - { - meta_display_decrement_focus_sentinel (display); - } - } - } - break; - case SelectionClear: - /* do this here instead of at end of function - * so we can return - */ - - /* FIXME: Clearing display->current_time here makes no sense to - * me; who put this here and why? - */ - display->current_time = CurrentTime; - - process_selection_clear (display, event); - /* Note that processing that may have resulted in - * closing the display... so return right away. - */ - return FALSE; - case SelectionRequest: - process_selection_request (display, event); - break; - case SelectionNotify: - break; - case ColormapNotify: - if (window && !frame_was_receiver) - window->colormap = event->xcolormap.colormap; - break; - case ClientMessage: - if (window) - { - if (!frame_was_receiver) - meta_window_client_message (window, event); - } - else - { - MetaScreen *screen; - - screen = meta_display_screen_for_root (display, - event->xclient.window); - - if (screen) - { - if (event->xclient.message_type == - display->atom__NET_CURRENT_DESKTOP) - { - int space; - MetaWorkspace *workspace; - guint32 time; - - space = event->xclient.data.l[0]; - time = event->xclient.data.l[1]; - - meta_verbose ("Request to change current workspace to %d with " - "specified timestamp of %u\n", - space, time); - - workspace = - meta_screen_get_workspace_by_index (screen, - space); - - /* Handle clients using the older version of the spec... */ - if (time == 0 && workspace) - { - meta_warning ("Received a NET_CURRENT_DESKTOP message " - "from a broken (outdated) client who sent " - "a 0 timestamp\n"); - time = meta_display_get_current_time_roundtrip (display); - } - - if (workspace) - meta_workspace_activate (workspace, time); - else - meta_verbose ("Don't know about workspace %d\n", space); - } - else if (event->xclient.message_type == - display->atom__NET_NUMBER_OF_DESKTOPS) - { - int num_spaces; - - num_spaces = event->xclient.data.l[0]; - - meta_verbose ("Request to set number of workspaces to %d\n", - num_spaces); - - meta_prefs_set_num_workspaces (num_spaces); - } - else if (event->xclient.message_type == - display->atom__NET_SHOWING_DESKTOP) - { - gboolean showing_desktop; - guint32 timestamp; - - showing_desktop = event->xclient.data.l[0] != 0; - /* FIXME: Braindead protocol doesn't have a timestamp */ - timestamp = meta_display_get_current_time_roundtrip (display); - meta_verbose ("Request to %s desktop\n", - showing_desktop ? "show" : "hide"); - - if (showing_desktop) - meta_screen_show_desktop (screen, timestamp); - else - { - meta_screen_unshow_desktop (screen); - meta_workspace_focus_default_window (screen->active_workspace, NULL, timestamp); - } - } - else if (event->xclient.message_type == - display->atom__METACITY_RESTART_MESSAGE) - { - meta_verbose ("Received restart request\n"); - meta_restart (); - } - else if (event->xclient.message_type == - display->atom__METACITY_RELOAD_THEME_MESSAGE) - { - meta_verbose ("Received reload theme request\n"); - meta_ui_set_current_theme (meta_prefs_get_theme (), - TRUE); - meta_display_retheme_all (); - } - else if (event->xclient.message_type == - display->atom__METACITY_SET_KEYBINDINGS_MESSAGE) - { - meta_verbose ("Received set keybindings request = %d\n", - (int) event->xclient.data.l[0]); - meta_set_keybindings_disabled (!event->xclient.data.l[0]); - } - else if (event->xclient.message_type == - display->atom__METACITY_TOGGLE_VERBOSE) - { - meta_verbose ("Received toggle verbose message\n"); - meta_set_verbose (!meta_is_verbose ()); - } - else if (event->xclient.message_type == - display->atom_WM_PROTOCOLS) - { - meta_verbose ("Received WM_PROTOCOLS message\n"); - - if ((Atom)event->xclient.data.l[0] == display->atom__NET_WM_PING) - { - process_pong_message (display, event); - - /* We don't want ping reply events going into - * the GTK+ event loop because gtk+ will treat - * them as ping requests and send more replies. - */ - filter_out_event = TRUE; - } - } - } - - if (event->xclient.message_type == - display->atom__NET_REQUEST_FRAME_EXTENTS) - { - meta_verbose ("Received _NET_REQUEST_FRAME_EXTENTS message\n"); - process_request_frame_extents (display, event); - } - } - break; - case MappingNotify: - { - gboolean ignore_current; - - ignore_current = FALSE; - - /* Check whether the next event is an identical MappingNotify - * event. If it is, ignore the current event, we'll update - * when we get the next one. - */ - if (XPending (display->xdisplay)) - { - XEvent next_event; - - XPeekEvent (display->xdisplay, &next_event); - - if (next_event.type == MappingNotify && - next_event.xmapping.request == event->xmapping.request) - ignore_current = TRUE; - } - - if (!ignore_current) - { - /* Let XLib know that there is a new keyboard mapping. - */ - XRefreshKeyboardMapping (&event->xmapping); - meta_display_process_mapping_event (display, event); - } - } - break; - default: -#ifdef HAVE_XKB - if (event->type == display->xkb_base_event_type) - { - XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event; - - switch (xkb_ev->xkb_type) - { - case XkbBellNotify: - if (XSERVER_TIME_IS_BEFORE(display->last_bell_time, - xkb_ev->time - 1000)) - { - display->last_bell_time = xkb_ev->time; - meta_bell_notify (display, xkb_ev); - } - break; - } - } -#endif - break; - } - - if (display->compositor) - { - meta_compositor_process_event (display->compositor, - event, - window); - } - - display->current_time = CurrentTime; - return filter_out_event; -} - -/* Return the window this has to do with, if any, rather - * than the frame or root window that was selecting - * for substructure - */ -static Window -event_get_modified_window (MetaDisplay *display, - XEvent *event) -{ - switch (event->type) - { - case KeyPress: - case KeyRelease: - case ButtonPress: - case ButtonRelease: - case MotionNotify: - case FocusIn: - case FocusOut: - case KeymapNotify: - case Expose: - case GraphicsExpose: - case NoExpose: - case VisibilityNotify: - case ResizeRequest: - case PropertyNotify: - case SelectionClear: - case SelectionRequest: - case SelectionNotify: - case ColormapNotify: - case ClientMessage: - case EnterNotify: - case LeaveNotify: - return event->xany.window; - - case CreateNotify: - return event->xcreatewindow.window; - - case DestroyNotify: - return event->xdestroywindow.window; - - case UnmapNotify: - return event->xunmap.window; - - case MapNotify: - return event->xmap.window; - - case MapRequest: - return event->xmaprequest.window; - - case ReparentNotify: - return event->xreparent.window; - - case ConfigureNotify: - return event->xconfigure.window; - - case ConfigureRequest: - return event->xconfigurerequest.window; - - case GravityNotify: - return event->xgravity.window; - - case CirculateNotify: - return event->xcirculate.window; - - case CirculateRequest: - return event->xcirculaterequest.window; - - case MappingNotify: - return None; - - default: -#ifdef HAVE_SHAPE - if (META_DISPLAY_HAS_SHAPE (display) && - event->type == (display->shape_event_base + ShapeNotify)) - { - XShapeEvent *sev = (XShapeEvent*) event; - return sev->window; - } -#endif - - return None; - } -} - -static guint32 -event_get_time (MetaDisplay *display, - XEvent *event) -{ - switch (event->type) - { - case KeyPress: - case KeyRelease: - return event->xkey.time; - - case ButtonPress: - case ButtonRelease: - return event->xbutton.time; - - case MotionNotify: - return event->xmotion.time; - - case PropertyNotify: - return event->xproperty.time; - - case SelectionClear: - case SelectionRequest: - case SelectionNotify: - return event->xselection.time; - - case EnterNotify: - case LeaveNotify: - return event->xcrossing.time; - - case FocusIn: - case FocusOut: - case KeymapNotify: - case Expose: - case GraphicsExpose: - case NoExpose: - case MapNotify: - case UnmapNotify: - case VisibilityNotify: - case ResizeRequest: - case ColormapNotify: - case ClientMessage: - case CreateNotify: - case DestroyNotify: - case MapRequest: - case ReparentNotify: - case ConfigureNotify: - case ConfigureRequest: - case GravityNotify: - case CirculateNotify: - case CirculateRequest: - case MappingNotify: - default: - return CurrentTime; - } -} - -#ifdef WITH_VERBOSE_MODE -const char* -meta_event_detail_to_string (int d) -{ - const char *detail = "???"; - switch (d) - { - /* We are an ancestor in the A<->B focus change relationship */ - case NotifyAncestor: - detail = "NotifyAncestor"; - break; - case NotifyDetailNone: - detail = "NotifyDetailNone"; - break; - /* We are a descendant in the A<->B focus change relationship */ - case NotifyInferior: - detail = "NotifyInferior"; - break; - case NotifyNonlinear: - detail = "NotifyNonlinear"; - break; - case NotifyNonlinearVirtual: - detail = "NotifyNonlinearVirtual"; - break; - case NotifyPointer: - detail = "NotifyPointer"; - break; - case NotifyPointerRoot: - detail = "NotifyPointerRoot"; - break; - case NotifyVirtual: - detail = "NotifyVirtual"; - break; - } - - return detail; -} -#endif /* WITH_VERBOSE_MODE */ - -#ifdef WITH_VERBOSE_MODE -const char* -meta_event_mode_to_string (int m) -{ - const char *mode = "???"; - switch (m) - { - case NotifyNormal: - mode = "NotifyNormal"; - break; - case NotifyGrab: - mode = "NotifyGrab"; - break; - case NotifyUngrab: - mode = "NotifyUngrab"; - break; - /* not sure any X implementations are missing this, but - * it seems to be absent from some docs. - */ -#ifdef NotifyWhileGrabbed - case NotifyWhileGrabbed: - mode = "NotifyWhileGrabbed"; - break; -#endif - } - - return mode; -} -#endif /* WITH_VERBOSE_MODE */ - -#ifdef WITH_VERBOSE_MODE -static const char* -stack_mode_to_string (int mode) -{ - switch (mode) - { - case Above: - return "Above"; - case Below: - return "Below"; - case TopIf: - return "TopIf"; - case BottomIf: - return "BottomIf"; - case Opposite: - return "Opposite"; - } - - return "Unknown"; -} -#endif /* WITH_VERBOSE_MODE */ - -#ifdef WITH_VERBOSE_MODE -static char* -key_event_description (Display *xdisplay, - XEvent *event) -{ - KeySym keysym; - const char *str; - - keysym = XKeycodeToKeysym (xdisplay, event->xkey.keycode, 0); - - str = XKeysymToString (keysym); - - return g_strdup_printf ("Key '%s' state 0x%x", - str ? str : "none", event->xkey.state); -} -#endif /* WITH_VERBOSE_MODE */ - -#ifdef HAVE_XSYNC -#ifdef WITH_VERBOSE_MODE -static gint64 -sync_value_to_64 (const XSyncValue *value) -{ - gint64 v; - - v = XSyncValueLow32 (*value); - v |= (((gint64)XSyncValueHigh32 (*value)) << 32); - - return v; -} -#endif /* WITH_VERBOSE_MODE */ - -#ifdef WITH_VERBOSE_MODE -static const char* -alarm_state_to_string (XSyncAlarmState state) -{ - switch (state) - { - case XSyncAlarmActive: - return "Active"; - case XSyncAlarmInactive: - return "Inactive"; - case XSyncAlarmDestroyed: - return "Destroyed"; - default: - return "(unknown)"; - } -} -#endif /* WITH_VERBOSE_MODE */ - -#endif /* HAVE_XSYNC */ - -#ifdef WITH_VERBOSE_MODE -static void -meta_spew_event (MetaDisplay *display, - XEvent *event) -{ - const char *name = NULL; - char *extra = NULL; - char *winname; - MetaScreen *screen; - - if (!meta_is_verbose()) - return; - - /* filter overnumerous events */ - if (event->type == Expose || event->type == MotionNotify || - event->type == NoExpose) - return; - - switch (event->type) - { - case KeyPress: - name = "KeyPress"; - extra = key_event_description (display->xdisplay, event); - break; - case KeyRelease: - name = "KeyRelease"; - extra = key_event_description (display->xdisplay, event); - break; - case ButtonPress: - name = "ButtonPress"; - extra = g_strdup_printf ("button %u state 0x%x x %d y %d root 0x%lx same_screen %d", - event->xbutton.button, - event->xbutton.state, - event->xbutton.x, - event->xbutton.y, - event->xbutton.root, - event->xbutton.same_screen); - break; - case ButtonRelease: - name = "ButtonRelease"; - extra = g_strdup_printf ("button %u state 0x%x x %d y %d root 0x%lx same_screen %d", - event->xbutton.button, - event->xbutton.state, - event->xbutton.x, - event->xbutton.y, - event->xbutton.root, - event->xbutton.same_screen); - break; - case MotionNotify: - name = "MotionNotify"; - extra = g_strdup_printf ("win: 0x%lx x: %d y: %d", - event->xmotion.window, - event->xmotion.x, - event->xmotion.y); - break; - case EnterNotify: - name = "EnterNotify"; - extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %s detail: %s focus: %d x: %d y: %d", - event->xcrossing.window, - event->xcrossing.root, - event->xcrossing.subwindow, - meta_event_mode_to_string (event->xcrossing.mode), - meta_event_detail_to_string (event->xcrossing.detail), - event->xcrossing.focus, - event->xcrossing.x, - event->xcrossing.y); - break; - case LeaveNotify: - name = "LeaveNotify"; - extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %s detail: %s focus: %d x: %d y: %d", - event->xcrossing.window, - event->xcrossing.root, - event->xcrossing.subwindow, - meta_event_mode_to_string (event->xcrossing.mode), - meta_event_detail_to_string (event->xcrossing.detail), - event->xcrossing.focus, - event->xcrossing.x, - event->xcrossing.y); - break; - case FocusIn: - name = "FocusIn"; - extra = g_strdup_printf ("detail: %s mode: %s\n", - meta_event_detail_to_string (event->xfocus.detail), - meta_event_mode_to_string (event->xfocus.mode)); - break; - case FocusOut: - name = "FocusOut"; - extra = g_strdup_printf ("detail: %s mode: %s\n", - meta_event_detail_to_string (event->xfocus.detail), - meta_event_mode_to_string (event->xfocus.mode)); - break; - case KeymapNotify: - name = "KeymapNotify"; - break; - case Expose: - name = "Expose"; - break; - case GraphicsExpose: - name = "GraphicsExpose"; - break; - case NoExpose: - name = "NoExpose"; - break; - case VisibilityNotify: - name = "VisibilityNotify"; - break; - case CreateNotify: - name = "CreateNotify"; - extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx", - event->xcreatewindow.parent, - event->xcreatewindow.window); - break; - case DestroyNotify: - name = "DestroyNotify"; - extra = g_strdup_printf ("event: 0x%lx window: 0x%lx", - event->xdestroywindow.event, - event->xdestroywindow.window); - break; - case UnmapNotify: - name = "UnmapNotify"; - extra = g_strdup_printf ("event: 0x%lx window: 0x%lx from_configure: %d", - event->xunmap.event, - event->xunmap.window, - event->xunmap.from_configure); - break; - case MapNotify: - name = "MapNotify"; - extra = g_strdup_printf ("event: 0x%lx window: 0x%lx override_redirect: %d", - event->xmap.event, - event->xmap.window, - event->xmap.override_redirect); - break; - case MapRequest: - name = "MapRequest"; - extra = g_strdup_printf ("window: 0x%lx parent: 0x%lx\n", - event->xmaprequest.window, - event->xmaprequest.parent); - break; - case ReparentNotify: - name = "ReparentNotify"; - extra = g_strdup_printf ("window: 0x%lx parent: 0x%lx event: 0x%lx\n", - event->xreparent.window, - event->xreparent.parent, - event->xreparent.event); - break; - case ConfigureNotify: - name = "ConfigureNotify"; - extra = g_strdup_printf ("x: %d y: %d w: %d h: %d above: 0x%lx override_redirect: %d", - event->xconfigure.x, - event->xconfigure.y, - event->xconfigure.width, - event->xconfigure.height, - event->xconfigure.above, - event->xconfigure.override_redirect); - break; - case ConfigureRequest: - name = "ConfigureRequest"; - extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx x: %d %sy: %d %sw: %d %sh: %d %sborder: %d %sabove: %lx %sstackmode: %s %s", - event->xconfigurerequest.parent, - event->xconfigurerequest.window, - event->xconfigurerequest.x, - event->xconfigurerequest.value_mask & - CWX ? "" : "(unset) ", - event->xconfigurerequest.y, - event->xconfigurerequest.value_mask & - CWY ? "" : "(unset) ", - event->xconfigurerequest.width, - event->xconfigurerequest.value_mask & - CWWidth ? "" : "(unset) ", - event->xconfigurerequest.height, - event->xconfigurerequest.value_mask & - CWHeight ? "" : "(unset) ", - event->xconfigurerequest.border_width, - event->xconfigurerequest.value_mask & - CWBorderWidth ? "" : "(unset)", - event->xconfigurerequest.above, - event->xconfigurerequest.value_mask & - CWSibling ? "" : "(unset)", - stack_mode_to_string (event->xconfigurerequest.detail), - event->xconfigurerequest.value_mask & - CWStackMode ? "" : "(unset)"); - break; - case GravityNotify: - name = "GravityNotify"; - break; - case ResizeRequest: - name = "ResizeRequest"; - extra = g_strdup_printf ("width = %d height = %d", - event->xresizerequest.width, - event->xresizerequest.height); - break; - case CirculateNotify: - name = "CirculateNotify"; - break; - case CirculateRequest: - name = "CirculateRequest"; - break; - case PropertyNotify: - { - char *str; - const char *state; - - name = "PropertyNotify"; - - meta_error_trap_push (display); - str = XGetAtomName (display->xdisplay, - event->xproperty.atom); - meta_error_trap_pop (display, TRUE); - - if (event->xproperty.state == PropertyNewValue) - state = "PropertyNewValue"; - else if (event->xproperty.state == PropertyDelete) - state = "PropertyDelete"; - else - state = "???"; - - extra = g_strdup_printf ("atom: %s state: %s", - str ? str : "(unknown atom)", - state); - meta_XFree (str); - } - break; - case SelectionClear: - name = "SelectionClear"; - break; - case SelectionRequest: - name = "SelectionRequest"; - break; - case SelectionNotify: - name = "SelectionNotify"; - break; - case ColormapNotify: - name = "ColormapNotify"; - break; - case ClientMessage: - { - char *str; - name = "ClientMessage"; - meta_error_trap_push (display); - str = XGetAtomName (display->xdisplay, - event->xclient.message_type); - meta_error_trap_pop (display, TRUE); - extra = g_strdup_printf ("type: %s format: %d\n", - str ? str : "(unknown atom)", - event->xclient.format); - meta_XFree (str); - } - break; - case MappingNotify: - name = "MappingNotify"; - break; - default: -#ifdef HAVE_XSYNC - if (META_DISPLAY_HAS_XSYNC (display) && - event->type == (display->xsync_event_base + XSyncAlarmNotify)) - { - XSyncAlarmNotifyEvent *aevent = (XSyncAlarmNotifyEvent*) event; - - name = "XSyncAlarmNotify"; - extra = - g_strdup_printf ("alarm: 0x%lx" - " counter_value: %" G_GINT64_FORMAT - " alarm_value: %" G_GINT64_FORMAT - " time: %u alarm state: %s", - aevent->alarm, - (gint64) sync_value_to_64 (&aevent->counter_value), - (gint64) sync_value_to_64 (&aevent->alarm_value), - (unsigned int)aevent->time, - alarm_state_to_string (aevent->state)); - } - else -#endif /* HAVE_XSYNC */ -#ifdef HAVE_SHAPE - if (META_DISPLAY_HAS_SHAPE (display) && - event->type == (display->shape_event_base + ShapeNotify)) - { - XShapeEvent *sev = (XShapeEvent*) event; - - name = "ShapeNotify"; - - extra = - g_strdup_printf ("kind: %s " - "x: %d y: %d w: %u h: %u " - "shaped: %d", - sev->kind == ShapeBounding ? - "ShapeBounding" : - (sev->kind == ShapeClip ? - "ShapeClip" : "(unknown)"), - sev->x, sev->y, sev->width, sev->height, - sev->shaped); - } - else -#endif /* HAVE_SHAPE */ - { - name = "(Unknown event)"; - extra = g_strdup_printf ("type: %d", event->xany.type); - } - break; - } - - screen = meta_display_screen_for_root (display, event->xany.window); - - if (screen) - winname = g_strdup_printf ("root %d", screen->number); - else - winname = g_strdup_printf ("0x%lx", event->xany.window); - - meta_topic (META_DEBUG_EVENTS, - "%s on %s%s %s %sserial %lu\n", name, winname, - extra ? ":" : "", extra ? extra : "", - event->xany.send_event ? "SEND " : "", - event->xany.serial); - - g_free (winname); - - if (extra) - g_free (extra); -} -#endif /* WITH_VERBOSE_MODE */ - -MetaWindow* -meta_display_lookup_x_window (MetaDisplay *display, - Window xwindow) -{ - return g_hash_table_lookup (display->window_ids, &xwindow); -} - -void -meta_display_register_x_window (MetaDisplay *display, - Window *xwindowp, - MetaWindow *window) -{ - g_return_if_fail (g_hash_table_lookup (display->window_ids, xwindowp) == NULL); - - g_hash_table_insert (display->window_ids, xwindowp, window); -} - -void -meta_display_unregister_x_window (MetaDisplay *display, - Window xwindow) -{ - g_return_if_fail (g_hash_table_lookup (display->window_ids, &xwindow) != NULL); - - g_hash_table_remove (display->window_ids, &xwindow); - - /* Remove any pending pings */ - remove_pending_pings_for_window (display, xwindow); -} - -gboolean -meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display, - Window xwindow) -{ - gboolean is_a_no_focus_window = FALSE; - GSList *temp = display->screens; - while (temp != NULL) { - MetaScreen *screen = temp->data; - if (screen->no_focus_window == xwindow) { - is_a_no_focus_window = TRUE; - break; - } - temp = temp->next; - } - - return is_a_no_focus_window; -} - -Cursor -meta_display_create_x_cursor (MetaDisplay *display, - MetaCursor cursor) -{ - Cursor xcursor; - guint glyph; - - switch (cursor) - { - case META_CURSOR_DEFAULT: - glyph = XC_left_ptr; - break; - case META_CURSOR_NORTH_RESIZE: - glyph = XC_top_side; - break; - case META_CURSOR_SOUTH_RESIZE: - glyph = XC_bottom_side; - break; - case META_CURSOR_WEST_RESIZE: - glyph = XC_left_side; - break; - case META_CURSOR_EAST_RESIZE: - glyph = XC_right_side; - break; - case META_CURSOR_SE_RESIZE: - glyph = XC_bottom_right_corner; - break; - case META_CURSOR_SW_RESIZE: - glyph = XC_bottom_left_corner; - break; - case META_CURSOR_NE_RESIZE: - glyph = XC_top_right_corner; - break; - case META_CURSOR_NW_RESIZE: - glyph = XC_top_left_corner; - break; - case META_CURSOR_MOVE_OR_RESIZE_WINDOW: - glyph = XC_fleur; - break; - case META_CURSOR_BUSY: - glyph = XC_watch; - break; - - default: - g_assert_not_reached (); - glyph = 0; /* silence compiler */ - break; - } - - xcursor = XCreateFontCursor (display->xdisplay, glyph); - - return xcursor; -} - -static Cursor -xcursor_for_op (MetaDisplay *display, - MetaGrabOp op) -{ - MetaCursor cursor = META_CURSOR_DEFAULT; - - switch (op) - { - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - cursor = META_CURSOR_SE_RESIZE; - break; - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - cursor = META_CURSOR_SOUTH_RESIZE; - break; - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - cursor = META_CURSOR_SW_RESIZE; - break; - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - cursor = META_CURSOR_NORTH_RESIZE; - break; - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - cursor = META_CURSOR_NE_RESIZE; - break; - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - cursor = META_CURSOR_NW_RESIZE; - break; - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - cursor = META_CURSOR_WEST_RESIZE; - break; - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - cursor = META_CURSOR_EAST_RESIZE; - break; - case META_GRAB_OP_MOVING: - case META_GRAB_OP_KEYBOARD_MOVING: - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - cursor = META_CURSOR_MOVE_OR_RESIZE_WINDOW; - break; - - default: - break; - } - - if (cursor == META_CURSOR_DEFAULT) - return None; - return meta_display_create_x_cursor (display, cursor); -} - -void -meta_display_set_grab_op_cursor (MetaDisplay *display, - MetaScreen *screen, - MetaGrabOp op, - gboolean change_pointer, - Window grab_xwindow, - guint32 timestamp) -{ - Cursor cursor; - - cursor = xcursor_for_op (display, op); - -#define GRAB_MASK (PointerMotionMask | \ - ButtonPressMask | ButtonReleaseMask | \ - EnterWindowMask | LeaveWindowMask) - - if (change_pointer) - { - meta_error_trap_push_with_return (display); - XChangeActivePointerGrab (display->xdisplay, - GRAB_MASK, - cursor, - timestamp); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Changed pointer with XChangeActivePointerGrab()\n"); - - if (meta_error_trap_pop_with_return (display, FALSE) != Success) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Error trapped from XChangeActivePointerGrab()\n"); - if (display->grab_have_pointer) - display->grab_have_pointer = FALSE; - } - } - else - { - g_assert (screen != NULL); - - meta_error_trap_push (display); - if (XGrabPointer (display->xdisplay, - grab_xwindow, - False, - GRAB_MASK, - GrabModeAsync, GrabModeAsync, - screen->xroot, - cursor, - timestamp) == GrabSuccess) - { - display->grab_have_pointer = TRUE; - meta_topic (META_DEBUG_WINDOW_OPS, - "XGrabPointer() returned GrabSuccess time %u\n", - timestamp); - } - else - { - meta_topic (META_DEBUG_WINDOW_OPS, - "XGrabPointer() failed time %u\n", - timestamp); - } - meta_error_trap_pop (display, TRUE); - } - -#undef GRAB_MASK - - if (cursor != None) - XFreeCursor (display->xdisplay, cursor); -} - -gboolean -meta_display_begin_grab_op (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - MetaGrabOp op, - gboolean pointer_already_grabbed, - gboolean frame_action, - int button, - gulong modmask, - guint32 timestamp, - int root_x, - int root_y) -{ - Window grab_xwindow; - - if (grab_op_is_mouse (op) && meta_grab_op_is_moving (op)) - { - if (display->compositor) - { - meta_compositor_begin_move (display->compositor, - window, &window->rect, - root_x, root_y); - } - } - - meta_topic (META_DEBUG_WINDOW_OPS, - "Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n", - op, window ? window->desc : "none", button, pointer_already_grabbed, - root_x, root_y); - - if (display->grab_op != META_GRAB_OP_NONE) - { - if (window) - meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect\n", - op, window->desc, display->grab_op, - display->grab_window ? display->grab_window->desc : "none"); - return FALSE; - } - - if (window && - (meta_grab_op_is_moving (op) || meta_grab_op_is_resizing (op))) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - else - { - display->grab_initial_x = root_x; - display->grab_initial_y = root_y; - display->grab_threshold_movement_reached = FALSE; - } - } - - /* FIXME: - * If we have no MetaWindow we do our best - * and try to do the grab on the RootWindow. - * This will fail if anyone else has any - * key grab on the RootWindow. - */ - if (window) - grab_xwindow = window->frame ? window->frame->xwindow : window->xwindow; - else - grab_xwindow = screen->xroot; - - display->grab_have_pointer = FALSE; - - if (pointer_already_grabbed) - display->grab_have_pointer = TRUE; - - meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow, - timestamp); - - if (!display->grab_have_pointer) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "XGrabPointer() failed\n"); - return FALSE; - } - - /* Grab keys for keyboard ops and mouse move/resizes; see #126497 */ - if (grab_op_is_keyboard (op) || grab_op_is_mouse_only (op)) - { - if (window) - display->grab_have_keyboard = - meta_window_grab_all_keys (window, timestamp); - - else - display->grab_have_keyboard = - meta_screen_grab_all_keys (screen, timestamp); - - if (!display->grab_have_keyboard) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "grabbing all keys failed, ungrabbing pointer\n"); - XUngrabPointer (display->xdisplay, timestamp); - display->grab_have_pointer = FALSE; - return FALSE; - } - } - - display->grab_op = op; - display->grab_window = window; - display->grab_screen = screen; - display->grab_xwindow = grab_xwindow; - display->grab_button = button; - display->grab_mask = modmask; - display->grab_anchor_root_x = root_x; - display->grab_anchor_root_y = root_y; - display->grab_latest_motion_x = root_x; - display->grab_latest_motion_y = root_y; - display->grab_last_moveresize_time.tv_sec = 0; - display->grab_last_moveresize_time.tv_usec = 0; - display->grab_motion_notify_time = 0; - display->grab_old_window_stacking = NULL; -#ifdef HAVE_XSYNC - display->grab_sync_request_alarm = None; - display->grab_last_user_action_was_snap = FALSE; -#endif - display->grab_was_cancelled = FALSE; - display->grab_frame_action = frame_action; - - if (display->grab_resize_timeout_id) - { - g_source_remove (display->grab_resize_timeout_id); - display->grab_resize_timeout_id = 0; - } - - if (display->grab_window) - { - meta_window_get_client_root_coords (display->grab_window, - &display->grab_initial_window_pos); - display->grab_anchor_window_pos = display->grab_initial_window_pos; - - display->grab_wireframe_active = - (meta_prefs_get_reduced_resources () && !meta_prefs_get_gnome_accessibility ()) && - (meta_grab_op_is_resizing (display->grab_op) || - meta_grab_op_is_moving (display->grab_op)); - - if (display->grab_wireframe_active) - { - meta_window_calc_showing (display->grab_window); - meta_window_begin_wireframe (window); - } - -#ifdef HAVE_XSYNC - if (!display->grab_wireframe_active && - meta_grab_op_is_resizing (display->grab_op) && - display->grab_window->sync_request_counter != None) - { - XSyncAlarmAttributes values; - XSyncValue init; - - meta_error_trap_push_with_return (display); - - /* Set the counter to 0, so we know that the application's - * responses to the client messages will always trigger - * a PositiveTransition - */ - - XSyncIntToValue (&init, 0); - XSyncSetCounter (display->xdisplay, - display->grab_window->sync_request_counter, init); - - display->grab_window->sync_request_serial = 0; - display->grab_window->sync_request_time.tv_sec = 0; - display->grab_window->sync_request_time.tv_usec = 0; - - values.trigger.counter = display->grab_window->sync_request_counter; - values.trigger.value_type = XSyncAbsolute; - values.trigger.test_type = XSyncPositiveTransition; - XSyncIntToValue (&values.trigger.wait_value, - display->grab_window->sync_request_serial + 1); - - /* After triggering, increment test_value by this. - * (NOT wait_value above) - */ - XSyncIntToValue (&values.delta, 1); - - /* we want events (on by default anyway) */ - values.events = True; - - display->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay, - XSyncCACounter | - XSyncCAValueType | - XSyncCAValue | - XSyncCATestType | - XSyncCADelta | - XSyncCAEvents, - &values); - - if (meta_error_trap_pop_with_return (display, FALSE) != Success) - display->grab_sync_request_alarm = None; - - meta_topic (META_DEBUG_RESIZING, - "Created update alarm 0x%lx\n", - display->grab_sync_request_alarm); - } -#endif - } - - meta_topic (META_DEBUG_WINDOW_OPS, - "Grab op %u on window %s successful\n", - display->grab_op, window ? window->desc : "(null)"); - - g_assert (display->grab_window != NULL || display->grab_screen != NULL); - g_assert (display->grab_op != META_GRAB_OP_NONE); - - /* If this is a move or resize, cache the window edges for - * resistance/snapping - */ - if (meta_grab_op_is_resizing (display->grab_op) || - meta_grab_op_is_moving (display->grab_op)) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Computing edges to resist-movement or snap-to for %s.\n", - window->desc); - meta_display_compute_resistance_and_snapping_edges (display); - } - - /* Save the old stacking */ - if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Saving old stack positions; old pointer was %p.\n", - display->grab_old_window_stacking); - display->grab_old_window_stacking = - meta_stack_get_positions (screen->stack); - } - - /* Do this last, after everything is set up. */ - switch (op) - { - case META_GRAB_OP_KEYBOARD_TABBING_NORMAL: - meta_screen_ensure_tab_popup (screen, - META_TAB_LIST_NORMAL, - META_TAB_SHOW_ICON); - break; - case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: - meta_screen_ensure_tab_popup (screen, - META_TAB_LIST_NORMAL, - META_TAB_SHOW_INSTANTLY); - break; - - case META_GRAB_OP_KEYBOARD_TABBING_DOCK: - meta_screen_ensure_tab_popup (screen, - META_TAB_LIST_DOCKS, - META_TAB_SHOW_ICON); - break; - case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: - meta_screen_ensure_tab_popup (screen, - META_TAB_LIST_DOCKS, - META_TAB_SHOW_INSTANTLY); - break; - case META_GRAB_OP_KEYBOARD_TABBING_GROUP: - meta_screen_ensure_tab_popup (screen, - META_TAB_LIST_GROUP, - META_TAB_SHOW_ICON); - break; - case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: - meta_screen_ensure_tab_popup (screen, - META_TAB_LIST_GROUP, - META_TAB_SHOW_INSTANTLY); - - case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: - meta_screen_ensure_workspace_popup (screen); - break; - - default: - break; - } - - if (display->grab_window) - { - meta_window_refresh_resize_popup (display->grab_window); - } - - return TRUE; -} - -void -meta_display_end_grab_op (MetaDisplay *display, - guint32 timestamp) -{ - meta_topic (META_DEBUG_WINDOW_OPS, - "Ending grab op %u at time %u\n", display->grab_op, timestamp); - - if (display->grab_op == META_GRAB_OP_NONE) - return; - - if (display->grab_window != NULL) - display->grab_window->shaken_loose = FALSE; - - if (display->grab_window != NULL && - !meta_prefs_get_raise_on_click () && - (meta_grab_op_is_moving (display->grab_op) || - meta_grab_op_is_resizing (display->grab_op))) - { - /* Only raise the window in orthogonal raise - * ('do-not-raise-on-click') mode if the user didn't try to move - * or resize the given window by at least a threshold amount. - * For raise on click mode, the window was raised at the - * beginning of the grab_op. - */ - if (!display->grab_threshold_movement_reached) - meta_window_raise (display->grab_window); - } - - if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) || - display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING) - { - meta_ui_tab_popup_free (display->grab_screen->tab_popup); - display->grab_screen->tab_popup = NULL; - - /* If the ungrab here causes an EnterNotify, ignore it for - * sloppy focus - */ - display->ungrab_should_not_cause_focus_window = display->grab_xwindow; - } - - /* If this was a move or resize clear out the edge cache */ - if (meta_grab_op_is_resizing (display->grab_op) || - meta_grab_op_is_moving (display->grab_op)) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Clearing out the edges for resistance/snapping"); - meta_display_cleanup_edges (display); - } - - if (display->grab_old_window_stacking != NULL) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Clearing out the old stack position, which was %p.\n", - display->grab_old_window_stacking); - g_list_free (display->grab_old_window_stacking); - display->grab_old_window_stacking = NULL; - } - - if (display->grab_wireframe_active) - { - display->grab_wireframe_active = FALSE; - meta_window_end_wireframe (display->grab_window); - - if (!display->grab_was_cancelled) - { - if (meta_grab_op_is_moving (display->grab_op)) - meta_window_move (display->grab_window, - TRUE, - display->grab_wireframe_rect.x, - display->grab_wireframe_rect.y); - if (meta_grab_op_is_resizing (display->grab_op)) - meta_window_resize_with_gravity (display->grab_window, - TRUE, - display->grab_wireframe_rect.width, - display->grab_wireframe_rect.height, - meta_resize_gravity_from_grab_op (display->grab_op)); - } - meta_window_calc_showing (display->grab_window); - } - - if (display->compositor && - display->grab_window && - grab_op_is_mouse (display->grab_op) && - meta_grab_op_is_moving (display->grab_op)) - { - meta_compositor_end_move (display->compositor, - display->grab_window); - } - - if (display->grab_have_pointer) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Ungrabbing pointer with timestamp %u\n", timestamp); - XUngrabPointer (display->xdisplay, timestamp); - } - - if (display->grab_have_keyboard) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Ungrabbing all keys timestamp %u\n", timestamp); - if (display->grab_window) - meta_window_ungrab_all_keys (display->grab_window, timestamp); - else - meta_screen_ungrab_all_keys (display->grab_screen, timestamp); - } - -#ifdef HAVE_XSYNC - if (display->grab_sync_request_alarm != None) - { - XSyncDestroyAlarm (display->xdisplay, - display->grab_sync_request_alarm); - display->grab_sync_request_alarm = None; - } -#endif /* HAVE_XSYNC */ - - display->grab_window = NULL; - display->grab_screen = NULL; - display->grab_xwindow = None; - display->grab_op = META_GRAB_OP_NONE; - - if (display->grab_resize_popup) - { - meta_ui_resize_popup_free (display->grab_resize_popup); - display->grab_resize_popup = NULL; - } - - if (display->grab_resize_timeout_id) - { - g_source_remove (display->grab_resize_timeout_id); - display->grab_resize_timeout_id = 0; - } -} - -void -meta_display_check_threshold_reached (MetaDisplay *display, - int x, - int y) -{ - /* Don't bother doing the check again if we've already reached the threshold */ - if (meta_prefs_get_raise_on_click () || - display->grab_threshold_movement_reached) - return; - - if (ABS (display->grab_initial_x - x) >= 8 || - ABS (display->grab_initial_y - y) >= 8) - display->grab_threshold_movement_reached = TRUE; -} - -static void -meta_change_button_grab (MetaDisplay *display, - Window xwindow, - gboolean grab, - gboolean sync, - int button, - int modmask) -{ - unsigned int ignored_mask; - - meta_verbose ("%s 0x%lx sync = %d button = %d modmask 0x%x\n", - grab ? "Grabbing" : "Ungrabbing", - xwindow, - sync, button, modmask); - - meta_error_trap_push (display); - - ignored_mask = 0; - while (ignored_mask <= display->ignored_modifier_mask) - { - if (ignored_mask & ~(display->ignored_modifier_mask)) - { - /* Not a combination of ignored modifiers - * (it contains some non-ignored modifiers) - */ - ++ignored_mask; - continue; - } - - if (meta_is_debugging ()) - meta_error_trap_push_with_return (display); - - /* GrabModeSync means freeze until XAllowEvents */ - - if (grab) - XGrabButton (display->xdisplay, button, modmask | ignored_mask, - xwindow, False, - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | PointerMotionHintMask, - sync ? GrabModeSync : GrabModeAsync, - GrabModeAsync, - False, None); - else - XUngrabButton (display->xdisplay, button, modmask | ignored_mask, - xwindow); - - if (meta_is_debugging ()) - { - int result; - - result = meta_error_trap_pop_with_return (display, FALSE); - - if (result != Success) - meta_verbose ("Failed to %s button %d with mask 0x%x for window 0x%lx error code %d\n", - grab ? "grab" : "ungrab", - button, modmask | ignored_mask, xwindow, result); - } - - ++ignored_mask; - } - - meta_error_trap_pop (display, FALSE); -} - -void -meta_display_grab_window_buttons (MetaDisplay *display, - Window xwindow) -{ - /* Grab Alt + button1 for moving window. - * Grab Alt + button2 for resizing window. - * Grab Alt + button3 for popping up window menu. - * Grab Alt + Shift + button1 for snap-moving window. - */ - meta_verbose ("Grabbing window buttons for 0x%lx\n", xwindow); - - /* FIXME If we ignored errors here instead of spewing, we could - * put one big error trap around the loop and avoid a bunch of - * XSync() - */ - - if (display->window_grab_modifiers != 0) - { - gboolean debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL; - int i; - for (i = 1; i < 4; i++) - { - meta_change_button_grab (display, xwindow, - TRUE, - FALSE, - i, display->window_grab_modifiers); - - /* This is for debugging, since I end up moving the Xnest - * otherwise ;-) - */ - if (debug) - meta_change_button_grab (display, xwindow, - TRUE, - FALSE, - i, ControlMask); - } - - /* In addition to grabbing Alt+Button1 for moving the window, - * grab Alt+Shift+Button1 for snap-moving the window. See bug - * 112478. Unfortunately, this doesn't work with - * Shift+Alt+Button1 for some reason; so at least part of the - * order still matters, which sucks (please FIXME). - */ - meta_change_button_grab (display, xwindow, - TRUE, - FALSE, - 1, display->window_grab_modifiers | ShiftMask); - } -} - -void -meta_display_ungrab_window_buttons (MetaDisplay *display, - Window xwindow) -{ - gboolean debug; - int i; - - if (display->window_grab_modifiers == 0) - return; - - debug = g_getenv ("METACITY_DEBUG_BUTTON_GRABS") != NULL; - i = 1; - while (i < 4) - { - meta_change_button_grab (display, xwindow, - FALSE, FALSE, i, - display->window_grab_modifiers); - - if (debug) - meta_change_button_grab (display, xwindow, - FALSE, FALSE, i, ControlMask); - - ++i; - } -} - -/* Grab buttons we only grab while unfocused in click-to-focus mode */ -#define MAX_FOCUS_BUTTON 4 -void -meta_display_grab_focus_window_button (MetaDisplay *display, - MetaWindow *window) -{ - /* Grab button 1 for activating unfocused windows */ - meta_verbose ("Grabbing unfocused window buttons for %s\n", window->desc); - -#if 0 - /* FIXME:115072 */ - /* Don't grab at all unless in click to focus mode. In click to - * focus, we may sometimes be clever about intercepting and eating - * the focus click. But in mouse focus, we never do that since the - * focus window may not be raised, and who wants to think about - * mouse focus anyway. - */ - if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK) - { - meta_verbose (" (well, not grabbing since not in click to focus mode)\n"); - return; - } -#endif - - if (window->have_focus_click_grab) - { - meta_verbose (" (well, not grabbing since we already have the grab)\n"); - return; - } - - /* FIXME If we ignored errors here instead of spewing, we could - * put one big error trap around the loop and avoid a bunch of - * XSync() - */ - - { - int i = 1; - while (i < MAX_FOCUS_BUTTON) - { - meta_change_button_grab (display, - window->xwindow, - TRUE, TRUE, - i, 0); - - ++i; - } - - window->have_focus_click_grab = TRUE; - } -} - -void -meta_display_ungrab_focus_window_button (MetaDisplay *display, - MetaWindow *window) -{ - meta_verbose ("Ungrabbing unfocused window buttons for %s\n", window->desc); - - if (!window->have_focus_click_grab) - return; - - { - int i = 1; - while (i < MAX_FOCUS_BUTTON) - { - meta_change_button_grab (display, window->xwindow, - FALSE, FALSE, i, 0); - - ++i; - } - - window->have_focus_click_grab = FALSE; - } -} - -void -meta_display_increment_event_serial (MetaDisplay *display) -{ - /* We just make some random X request */ - XDeleteProperty (display->xdisplay, display->leader_window, - display->atom__MOTIF_WM_HINTS); -} - -void -meta_display_update_active_window_hint (MetaDisplay *display) -{ - GSList *tmp; - - gulong data[1]; - - if (display->focus_window) - data[0] = display->focus_window->xwindow; - else - data[0] = None; - - tmp = display->screens; - while (tmp != NULL) - { - MetaScreen *screen = tmp->data; - - meta_error_trap_push (display); - XChangeProperty (display->xdisplay, screen->xroot, - display->atom__NET_ACTIVE_WINDOW, - XA_WINDOW, - 32, PropModeReplace, (guchar*) data, 1); - - meta_error_trap_pop (display, FALSE); - - tmp = tmp->next; - } -} - -void -meta_display_queue_retheme_all_windows (MetaDisplay *display) -{ - GSList* windows; - GSList *tmp; - - windows = meta_display_list_windows (display); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - if (window->frame) - { - window->frame->need_reapply_frame_shape = TRUE; - - meta_frame_queue_draw (window->frame); - } - - tmp = tmp->next; - } - - g_slist_free (windows); -} - -void -meta_display_retheme_all (void) -{ - meta_display_queue_retheme_all_windows (meta_get_display ()); -} - -void -meta_display_set_cursor_theme (const char *theme, - int size) -{ -#ifdef HAVE_XCURSOR - GSList *tmp; - - MetaDisplay *display = meta_get_display (); - - XcursorSetTheme (display->xdisplay, theme); - XcursorSetDefaultSize (display->xdisplay, size); - - tmp = display->screens; - while (tmp != NULL) - { - MetaScreen *screen = tmp->data; - - meta_screen_update_cursor (screen); - - tmp = tmp->next; - } - -#endif -} - -/** - * Stores whether syncing is currently enabled. - */ -static gboolean is_syncing = FALSE; - -/** - * Returns whether X synchronisation is currently enabled. - * - * \return true if we must wait for events whenever we send X requests; - * false otherwise. - * - * \bug This is *only* called by meta_display_open, but by that time - * we have already turned syncing on or off on startup, and we don't - * have any way to do so while Metacity is running, so it's rather - * pointless. - */ -gboolean -meta_is_syncing (void) -{ - return is_syncing; -} - -/** - * A handy way to turn on synchronisation on or off for every display. - * - * \bug Of course there is only one display ever anyway, so this can - * be rather hugely simplified. - */ -void -meta_set_syncing (gboolean setting) -{ - if (setting != is_syncing) - { - is_syncing = setting; - - XSynchronize (meta_get_display ()->xdisplay, is_syncing); - } -} - -/** - * How long, in milliseconds, we should wait after pinging a window - * before deciding it's not going to get back to us. - */ -#define PING_TIMEOUT_DELAY 2250 - -/** - * Does whatever it is we decided to do when a window didn't respond - * to a ping. We also remove the ping from the display's list of - * pending pings. This function is called by the event loop when the timeout - * times out which we created at the start of the ping. - * - * \param data All the information about this ping. It is a MetaPingData - * cast to a void* in order to be passable to a timeout function. - * This function will also free this parameter. - * - * \return Always returns false, because this function is called as a - * timeout and we don't want to run the timer again. - * - * \ingroup pings - */ -static gboolean -meta_display_ping_timeout (gpointer data) -{ - MetaPingData *ping_data; - - ping_data = data; - - ping_data->ping_timeout_id = 0; - - meta_topic (META_DEBUG_PING, - "Ping %u on window %lx timed out\n", - ping_data->timestamp, ping_data->xwindow); - - (* ping_data->ping_timeout_func) (ping_data->display, ping_data->xwindow, - ping_data->timestamp, ping_data->user_data); - - ping_data->display->pending_pings = - g_slist_remove (ping_data->display->pending_pings, - ping_data); - ping_data_free (ping_data); - - return FALSE; -} - -/** - * Sends a ping request to a window. The window must respond to - * the request within a certain amount of time. If it does, we - * will call one callback; if the time passes and we haven't had - * a response, we call a different callback. The window must have - * the hint showing that it can respond to a ping; if it doesn't, - * we call the "got a response" callback immediately and return. - * This function returns straight away after setting things up; - * the callbacks will be called from the event loop. - * - * \param display The MetaDisplay that the window is on - * \param window The MetaWindow to send the ping to - * \param timestamp The timestamp of the ping. Used for uniqueness. - * Cannot be CurrentTime; use a real timestamp! - * \param ping_reply_func The callback to call if we get a response. - * \param ping_timeout_func The callback to call if we don't get a response. - * \param user_data Arbitrary data that will be passed to the callback - * function. (In practice it's often a pointer to - * the window.) - * - * \bug This should probably be a method on windows, rather than displays - * for one of their windows. - * - * \ingroup pings - */ -void -meta_display_ping_window (MetaDisplay *display, - MetaWindow *window, - guint32 timestamp, - MetaWindowPingFunc ping_reply_func, - MetaWindowPingFunc ping_timeout_func, - gpointer user_data) -{ - MetaPingData *ping_data; - - if (timestamp == CurrentTime) - { - meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n"); - return; - } - - if (!window->net_wm_ping) - { - if (ping_reply_func) - (* ping_reply_func) (display, window->xwindow, timestamp, user_data); - - return; - } - - ping_data = g_new (MetaPingData, 1); - ping_data->display = display; - ping_data->xwindow = window->xwindow; - ping_data->timestamp = timestamp; - ping_data->ping_reply_func = ping_reply_func; - ping_data->ping_timeout_func = ping_timeout_func; - ping_data->user_data = user_data; - ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY, - meta_display_ping_timeout, - ping_data); - - display->pending_pings = g_slist_prepend (display->pending_pings, ping_data); - - meta_topic (META_DEBUG_PING, - "Sending ping with timestamp %u to window %s\n", - timestamp, window->desc); - meta_window_send_icccm_message (window, - display->atom__NET_WM_PING, - timestamp); -} - -static void -process_request_frame_extents (MetaDisplay *display, - XEvent *event) -{ - /* The X window whose frame extents will be set. */ - Window xwindow = event->xclient.window; - unsigned long data[4] = { 0, 0, 0, 0 }; - - MotifWmHints *hints = NULL; - gboolean hints_set = FALSE; - - meta_verbose ("Setting frame extents for 0x%lx\n", xwindow); - - /* See if the window is decorated. */ - hints_set = meta_prop_get_motif_hints (display, - xwindow, - display->atom__MOTIF_WM_HINTS, - &hints); - if ((hints_set && hints->decorations) || !hints_set) - { - int top = 0; - int bottom = 0; - int left = 0; - int right = 0; - - MetaScreen *screen; - - screen = meta_display_screen_for_xwindow (display, - event->xclient.window); - if (screen == NULL) - { - meta_warning ("Received request to set _NET_FRAME_EXTENTS " - "on 0x%lx which is on a screen we are not managing\n", - event->xclient.window); - meta_XFree (hints); - return; - } - - /* Return estimated frame extents for a normal window. */ - meta_ui_theme_get_frame_borders (screen->ui, - META_FRAME_TYPE_NORMAL, - 0, - &top, - &bottom, - &left, - &right); - - data[0] = left; - data[1] = right; - data[2] = top; - data[3] = bottom; - } - - meta_topic (META_DEBUG_GEOMETRY, - "Setting _NET_FRAME_EXTENTS on unmanaged window 0x%lx " - "to top = %lu, left = %lu, bottom = %lu, right = %lu\n", - xwindow, data[0], data[1], data[2], data[3]); - - meta_error_trap_push (display); - XChangeProperty (display->xdisplay, xwindow, - display->atom__NET_FRAME_EXTENTS, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 4); - meta_error_trap_pop (display, FALSE); - - meta_XFree (hints); -} - -/** - * Process the pong (the response message) from the ping we sent - * to the window. This involves removing the timeout, calling the - * reply handler function, and freeing memory. - * - * \param display the display we got the pong from - * \param event the XEvent which is a pong; we can tell which - * ping it corresponds to because it bears the - * same timestamp. - * - * \ingroup pings - */ -static void -process_pong_message (MetaDisplay *display, - XEvent *event) -{ - GSList *tmp; - guint32 timestamp = event->xclient.data.l[1]; - - meta_topic (META_DEBUG_PING, "Received a pong with timestamp %u\n", - timestamp); - - for (tmp = display->pending_pings; tmp; tmp = tmp->next) - { - MetaPingData *ping_data = tmp->data; - - if (timestamp == ping_data->timestamp) - { - meta_topic (META_DEBUG_PING, - "Matching ping found for pong %u\n", - ping_data->timestamp); - - /* Remove the ping data from the list */ - display->pending_pings = g_slist_remove (display->pending_pings, - ping_data); - - /* Remove the timeout */ - if (ping_data->ping_timeout_id != 0) - { - g_source_remove (ping_data->ping_timeout_id); - ping_data->ping_timeout_id = 0; - } - - /* Call callback */ - (* ping_data->ping_reply_func) (display, - ping_data->xwindow, - ping_data->timestamp, - ping_data->user_data); - - ping_data_free (ping_data); - - break; - } - } -} - -/** - * Finds whether a window has any pings waiting on it. - * - * \param display The MetaDisplay of the window. - * \param window The MetaWindow whose pings we want to know about. - * - * \return True if there is at least one ping which has been sent - * to the window without getting a response; false otherwise. - * - * \bug This should probably be a method on windows, rather than displays - * for one of their windows. - * - * \ingroup pings - */ -gboolean -meta_display_window_has_pending_pings (MetaDisplay *display, - MetaWindow *window) -{ - GSList *tmp; - - for (tmp = display->pending_pings; tmp; tmp = tmp->next) - { - MetaPingData *ping_data = tmp->data; - - if (ping_data->xwindow == window->xwindow) - return TRUE; - } - - return FALSE; -} - -MetaGroup* -get_focussed_group (MetaDisplay *display) -{ - if (display->focus_window) - return display->focus_window->group; - else - return NULL; -} - -#define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \ - || ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \ - || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focussed_group(w->display)))) - -static MetaWindow* -find_tab_forward (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace, - GList *start, - gboolean skip_first) -{ - GList *tmp; - - g_return_val_if_fail (start != NULL, NULL); - g_return_val_if_fail (workspace != NULL, NULL); - - tmp = start; - if (skip_first) - tmp = tmp->next; - - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (window->screen == screen && - IN_TAB_CHAIN (window, type)) - return window; - - tmp = tmp->next; - } - - tmp = workspace->mru_list; - while (tmp != start) - { - MetaWindow *window = tmp->data; - - if (IN_TAB_CHAIN (window, type)) - return window; - - tmp = tmp->next; - } - - return NULL; -} - -static MetaWindow* -find_tab_backward (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace, - GList *start, - gboolean skip_last) -{ - GList *tmp; - - g_return_val_if_fail (start != NULL, NULL); - g_return_val_if_fail (workspace != NULL, NULL); - - tmp = start; - if (skip_last) - tmp = tmp->prev; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (window->screen == screen && - IN_TAB_CHAIN (window, type)) - return window; - - tmp = tmp->prev; - } - - tmp = g_list_last (workspace->mru_list); - while (tmp != start) - { - MetaWindow *window = tmp->data; - - if (IN_TAB_CHAIN (window, type)) - return window; - - tmp = tmp->prev; - } - - return NULL; -} - -GList* -meta_display_get_tab_list (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace) -{ - GList *tab_list; - - g_return_val_if_fail (workspace != NULL, NULL); - - /* Windows sellout mode - MRU order. Collect unminimized windows - * then minimized so minimized windows aren't in the way so much. - */ - { - GList *tmp; - - tab_list = NULL; - tmp = workspace->mru_list; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (!window->minimized && - window->screen == screen && - IN_TAB_CHAIN (window, type)) - tab_list = g_list_prepend (tab_list, window); - - tmp = tmp->next; - } - } - - { - GList *tmp; - - tmp = workspace->mru_list; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (window->minimized && - window->screen == screen && - IN_TAB_CHAIN (window, type)) - tab_list = g_list_prepend (tab_list, window); - - tmp = tmp->next; - } - } - - tab_list = g_list_reverse (tab_list); - - { - GSList *tmp; - MetaWindow *l_window; - - tmp = meta_display_list_windows (display); - - /* Go through all windows */ - while (tmp != NULL) - { - l_window=tmp->data; - - /* Check to see if it demands attention */ - if (l_window->wm_state_demands_attention && - l_window->workspace!=workspace) - { - /* if it does, add it to the popup */ - tab_list = g_list_prepend (tab_list, l_window); - } - - tmp = tmp->next; - } /* End while tmp!=NULL */ - } - - return tab_list; -} - -MetaWindow* -meta_display_get_tab_next (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace, - MetaWindow *window, - gboolean backward) -{ - gboolean skip; - GList *tab_list; - MetaWindow *ret; - tab_list = meta_display_get_tab_list(display, - type, - screen, - workspace); - - if (tab_list == NULL) - return NULL; - - if (window != NULL) - { - g_assert (window->display == display); - - if (backward) - ret = find_tab_backward (display, type, screen, workspace, - g_list_find (tab_list, - window), - TRUE); - else - ret = find_tab_forward (display, type, screen, workspace, - g_list_find (tab_list, - window), - TRUE); - } - else - { - skip = display->focus_window != NULL && - IN_TAB_CHAIN (display->focus_window, type); - if (backward) - ret = find_tab_backward (display, type, screen, workspace, - tab_list, skip); - else - ret = find_tab_forward (display, type, screen, workspace, - tab_list, skip); - } - - g_list_free (tab_list); - return ret; -} - -MetaWindow* -meta_display_get_tab_current (MetaDisplay *display, - MetaTabList type, - MetaScreen *screen, - MetaWorkspace *workspace) -{ - MetaWindow *window; - - window = display->focus_window; - - if (window != NULL && - window->screen == screen && - IN_TAB_CHAIN (window, type) && - (workspace == NULL || - meta_window_located_on_workspace (window, workspace))) - return window; - else - return NULL; -} - -int -meta_resize_gravity_from_grab_op (MetaGrabOp op) -{ - int gravity; - - gravity = -1; - switch (op) - { - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - gravity = NorthWestGravity; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_RESIZING_S: - gravity = NorthGravity; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_RESIZING_SW: - gravity = NorthEastGravity; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_RESIZING_N: - gravity = SouthGravity; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_RESIZING_NE: - gravity = SouthWestGravity; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - case META_GRAB_OP_RESIZING_NW: - gravity = SouthEastGravity; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_RESIZING_E: - gravity = WestGravity; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_RESIZING_W: - gravity = EastGravity; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - gravity = CenterGravity; - break; - default: - break; - } - - return gravity; -} - -static MetaScreen* -find_screen_for_selection (MetaDisplay *display, - Window owner, - Atom selection) -{ - GSList *tmp; - - tmp = display->screens; - while (tmp != NULL) - { - MetaScreen *screen = tmp->data; - - if (screen->wm_sn_selection_window == owner && - screen->wm_sn_atom == selection) - return screen; - - tmp = tmp->next; - } - - return NULL; -} - -/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */ -static gboolean -convert_property (MetaDisplay *display, - MetaScreen *screen, - Window w, - Atom target, - Atom property) -{ -#define N_TARGETS 4 - Atom conversion_targets[N_TARGETS]; - long icccm_version[] = { 2, 0 }; - - conversion_targets[0] = display->atom_TARGETS; - conversion_targets[1] = display->atom_MULTIPLE; - conversion_targets[2] = display->atom_TIMESTAMP; - conversion_targets[3] = display->atom_VERSION; - - meta_error_trap_push_with_return (display); - if (target == display->atom_TARGETS) - XChangeProperty (display->xdisplay, w, property, - XA_ATOM, 32, PropModeReplace, - (unsigned char *)conversion_targets, N_TARGETS); - else if (target == display->atom_TIMESTAMP) - XChangeProperty (display->xdisplay, w, property, - XA_INTEGER, 32, PropModeReplace, - (unsigned char *)&screen->wm_sn_timestamp, 1); - else if (target == display->atom_VERSION) - XChangeProperty (display->xdisplay, w, property, - XA_INTEGER, 32, PropModeReplace, - (unsigned char *)icccm_version, 2); - else - { - meta_error_trap_pop_with_return (display, FALSE); - return FALSE; - } - - if (meta_error_trap_pop_with_return (display, FALSE) != Success) - return FALSE; - - /* Be sure the PropertyNotify has arrived so we - * can send SelectionNotify - */ - /* FIXME the error trap pop synced anyway, right? */ - meta_topic (META_DEBUG_SYNC, "Syncing on %s\n", G_STRFUNC); - XSync (display->xdisplay, False); - - return TRUE; -} - -/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */ -static void -process_selection_request (MetaDisplay *display, - XEvent *event) -{ - XSelectionEvent reply; - MetaScreen *screen; - - screen = find_screen_for_selection (display, - event->xselectionrequest.owner, - event->xselectionrequest.selection); - - if (screen == NULL) - { - char *str; - - meta_error_trap_push (display); - str = XGetAtomName (display->xdisplay, - event->xselectionrequest.selection); - meta_error_trap_pop (display, TRUE); - - meta_verbose ("Selection request with selection %s window 0x%lx not a WM_Sn selection we recognize\n", - str ? str : "(bad atom)", event->xselectionrequest.owner); - - meta_XFree (str); - - return; - } - - reply.type = SelectionNotify; - reply.display = display->xdisplay; - reply.requestor = event->xselectionrequest.requestor; - reply.selection = event->xselectionrequest.selection; - reply.target = event->xselectionrequest.target; - reply.property = None; - reply.time = event->xselectionrequest.time; - - if (event->xselectionrequest.target == display->atom_MULTIPLE) - { - if (event->xselectionrequest.property != None) - { - Atom type, *adata; - int i, format; - unsigned long num, rest; - unsigned char *data; - - meta_error_trap_push_with_return (display); - if (XGetWindowProperty (display->xdisplay, - event->xselectionrequest.requestor, - event->xselectionrequest.property, 0, 256, False, - display->atom_ATOM_PAIR, - &type, &format, &num, &rest, &data) != Success) - { - meta_error_trap_pop_with_return (display, TRUE); - return; - } - - if (meta_error_trap_pop_with_return (display, TRUE) == Success) - { - /* FIXME: to be 100% correct, should deal with rest > 0, - * but since we have 4 possible targets, we will hardly ever - * meet multiple requests with a length > 8 - */ - adata = (Atom*)data; - i = 0; - while (i < (int) num) - { - if (!convert_property (display, screen, - event->xselectionrequest.requestor, - adata[i], adata[i+1])) - adata[i+1] = None; - i += 2; - } - - meta_error_trap_push (display); - XChangeProperty (display->xdisplay, - event->xselectionrequest.requestor, - event->xselectionrequest.property, - display->atom_ATOM_PAIR, - 32, PropModeReplace, data, num); - meta_error_trap_pop (display, FALSE); - meta_XFree (data); - } - } - } - else - { - if (event->xselectionrequest.property == None) - event->xselectionrequest.property = event->xselectionrequest.target; - - if (convert_property (display, screen, - event->xselectionrequest.requestor, - event->xselectionrequest.target, - event->xselectionrequest.property)) - reply.property = event->xselectionrequest.property; - } - - XSendEvent (display->xdisplay, - event->xselectionrequest.requestor, - False, 0L, (XEvent*)&reply); - - meta_verbose ("Handled selection request\n"); -} - -static void -process_selection_clear (MetaDisplay *display, - XEvent *event) -{ - /* We need to unmanage the screen on which we lost the selection */ - MetaScreen *screen; - - screen = find_screen_for_selection (display, - event->xselectionclear.window, - event->xselectionclear.selection); - - - if (screen != NULL) - { - meta_verbose ("Got selection clear for screen %d on display %s\n", - screen->number, display->name); - - meta_display_unmanage_screen (display, - screen, - event->xselectionclear.time); - - /* display and screen may both be invalid memory... */ - - return; - } - - { - char *str; - - meta_error_trap_push (display); - str = XGetAtomName (display->xdisplay, - event->xselectionclear.selection); - meta_error_trap_pop (display, TRUE); - - meta_verbose ("Selection clear with selection %s window 0x%lx not a WM_Sn selection we recognize\n", - str ? str : "(bad atom)", event->xselectionclear.window); - - meta_XFree (str); - } -} - -void -meta_display_unmanage_screen (MetaDisplay *display, - MetaScreen *screen, - guint32 timestamp) -{ - meta_verbose ("Unmanaging screen %d on display %s\n", - screen->number, display->name); - - g_return_if_fail (g_slist_find (display->screens, screen) != NULL); - - meta_screen_free (screen, timestamp); - display->screens = g_slist_remove (display->screens, screen); - - if (display->screens == NULL) - meta_display_close (display, timestamp); -} - -void -meta_display_unmanage_windows_for_screen (MetaDisplay *display, - MetaScreen *screen, - guint32 timestamp) -{ - GSList *tmp; - GSList *winlist; - - winlist = meta_display_list_windows (display); - winlist = g_slist_sort (winlist, meta_display_stack_cmp); - - /* Unmanage all windows */ - tmp = winlist; - while (tmp != NULL) - { - meta_window_free (tmp->data, timestamp); - - tmp = tmp->next; - } - g_slist_free (winlist); -} - -int -meta_display_stack_cmp (const void *a, - const void *b) -{ - MetaWindow *aw = (void*) a; - MetaWindow *bw = (void*) b; - - if (aw->screen == bw->screen) - return meta_stack_windows_cmp (aw->screen->stack, aw, bw); - /* Then assume screens are stacked by number */ - else if (aw->screen->number < bw->screen->number) - return -1; - else if (aw->screen->number > bw->screen->number) - return 1; - else - return 0; /* not reached in theory, if windows on same display */ -} - -void -meta_display_devirtualize_modifiers (MetaDisplay *display, - MetaVirtualModifier modifiers, - unsigned int *mask) -{ - *mask = 0; - - if (modifiers & META_VIRTUAL_SHIFT_MASK) - *mask |= ShiftMask; - if (modifiers & META_VIRTUAL_CONTROL_MASK) - *mask |= ControlMask; - if (modifiers & META_VIRTUAL_ALT_MASK) - *mask |= Mod1Mask; - if (modifiers & META_VIRTUAL_META_MASK) - *mask |= display->meta_mask; - if (modifiers & META_VIRTUAL_HYPER_MASK) - *mask |= display->hyper_mask; - if (modifiers & META_VIRTUAL_SUPER_MASK) - *mask |= display->super_mask; - if (modifiers & META_VIRTUAL_MOD2_MASK) - *mask |= Mod2Mask; - if (modifiers & META_VIRTUAL_MOD3_MASK) - *mask |= Mod3Mask; - if (modifiers & META_VIRTUAL_MOD4_MASK) - *mask |= Mod4Mask; - if (modifiers & META_VIRTUAL_MOD5_MASK) - *mask |= Mod5Mask; -} - -static void -update_window_grab_modifiers (MetaDisplay *display) - -{ - MetaVirtualModifier virtual_mods; - unsigned int mods; - - virtual_mods = meta_prefs_get_mouse_button_mods (); - meta_display_devirtualize_modifiers (display, virtual_mods, - &mods); - - display->window_grab_modifiers = mods; -} - -static void -prefs_changed_callback (MetaPreference pref, - void *data) -{ - MetaDisplay *display = data; - - /* It may not be obvious why we regrab on focus mode - * change; it's because we handle focus clicks a - * bit differently for the different focus modes. - */ - if (pref == META_PREF_MOUSE_BUTTON_MODS || - pref == META_PREF_FOCUS_MODE) - { - MetaDisplay *display = data; - GSList *windows; - GSList *tmp; - - windows = meta_display_list_windows (display); - - /* Ungrab all */ - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - meta_display_ungrab_window_buttons (display, w->xwindow); - meta_display_ungrab_focus_window_button (display, w); - tmp = tmp->next; - } - - /* change our modifier */ - if (pref == META_PREF_MOUSE_BUTTON_MODS) - update_window_grab_modifiers (display); - - /* Grab all */ - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - if (w->type != META_WINDOW_DOCK) - { - meta_display_grab_focus_window_button (display, w); - meta_display_grab_window_buttons (display, w->xwindow); - } - tmp = tmp->next; - } - - g_slist_free (windows); - } - else if (pref == META_PREF_AUDIBLE_BELL) - { - meta_bell_set_audible (display, meta_prefs_bell_is_audible ()); - } - else if (pref == META_PREF_COMPOSITING_MANAGER) - { - gboolean cm = meta_prefs_get_compositing_manager (); - - if (cm) - enable_compositor (display, TRUE); - else - disable_compositor (display); - } -} - -void -meta_display_increment_focus_sentinel (MetaDisplay *display) -{ - unsigned long data[1]; - - data[0] = meta_display_get_current_time (display); - - XChangeProperty (display->xdisplay, - ((MetaScreen*) display->screens->data)->xroot, - display->atom__METACITY_SENTINEL, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - - display->sentinel_counter += 1; -} - -void -meta_display_decrement_focus_sentinel (MetaDisplay *display) -{ - display->sentinel_counter -= 1; - - if (display->sentinel_counter < 0) - display->sentinel_counter = 0; -} - -gboolean -meta_display_focus_sentinel_clear (MetaDisplay *display) -{ - return (display->sentinel_counter == 0); -} - -static void -sanity_check_timestamps (MetaDisplay *display, - guint32 timestamp) -{ - if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time)) - { - meta_warning ("last_focus_time (%u) is greater than comparison " - "timestamp (%u). This most likely represents a buggy " - "client sending inaccurate timestamps in messages such as " - "_NET_ACTIVE_WINDOW. Trying to work around...\n", - display->last_focus_time, timestamp); - display->last_focus_time = timestamp; - } - if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time)) - { - GSList *windows; - GSList *tmp; - - meta_warning ("last_user_time (%u) is greater than comparison " - "timestamp (%u). This most likely represents a buggy " - "client sending inaccurate timestamps in messages such as " - "_NET_ACTIVE_WINDOW. Trying to work around...\n", - display->last_user_time, timestamp); - display->last_user_time = timestamp; - - windows = meta_display_list_windows (display); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time)) - { - meta_warning ("%s appears to be one of the offending windows " - "with a timestamp of %u. Working around...\n", - window->desc, window->net_wm_user_time); - window->net_wm_user_time = timestamp; - } - - tmp = tmp->next; - } - - g_slist_free (windows); - } -} - -static gboolean -timestamp_too_old (MetaDisplay *display, - MetaWindow *window, - guint32 *timestamp) -{ - /* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow - * us to sanity check the timestamp here and ensure it doesn't correspond to - * a future time (though we would want to rename to - * timestamp_too_old_or_in_future). - */ - - if (*timestamp == CurrentTime) - { - meta_warning ("Got a request to focus %s with a timestamp of 0. This " - "shouldn't happen!\n", - window ? window->desc : "the no_focus_window"); - meta_print_backtrace (); - *timestamp = meta_display_get_current_time_roundtrip (display); - return FALSE; - } - else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time)) - { - if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time)) - { - meta_topic (META_DEBUG_FOCUS, - "Ignoring focus request for %s since %u " - "is less than %u and %u.\n", - window ? window->desc : "the no_focus_window", - *timestamp, - display->last_user_time, - display->last_focus_time); - return TRUE; - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Received focus request for %s which is newer than most " - "recent user_time, but less recent than " - "last_focus_time (%u < %u < %u); adjusting " - "accordingly. (See bug 167358)\n", - window ? window->desc : "the no_focus_window", - display->last_user_time, - *timestamp, - display->last_focus_time); - *timestamp = display->last_focus_time; - return FALSE; - } - } - - return FALSE; -} - -void -meta_display_set_input_focus_window (MetaDisplay *display, - MetaWindow *window, - gboolean focus_frame, - guint32 timestamp) -{ - if (timestamp_too_old (display, window, ×tamp)) - return; - - meta_error_trap_push (display); - XSetInputFocus (display->xdisplay, - focus_frame ? window->frame->xwindow : window->xwindow, - RevertToPointerRoot, - timestamp); - meta_error_trap_pop (display, FALSE); - - display->expected_focus_window = window; - display->last_focus_time = timestamp; - display->active_screen = window->screen; - - if (window != display->autoraise_window) - meta_display_remove_autoraise_callback (window->display); -} - -void -meta_display_focus_the_no_focus_window (MetaDisplay *display, - MetaScreen *screen, - guint32 timestamp) -{ - if (timestamp_too_old (display, NULL, ×tamp)) - return; - - XSetInputFocus (display->xdisplay, - screen->no_focus_window, - RevertToPointerRoot, - timestamp); - display->expected_focus_window = NULL; - display->last_focus_time = timestamp; - display->active_screen = screen; - - meta_display_remove_autoraise_callback (display); -} - -void -meta_display_remove_autoraise_callback (MetaDisplay *display) -{ - if (display->autoraise_timeout_id != 0) - { - g_source_remove (display->autoraise_timeout_id); - display->autoraise_timeout_id = 0; - display->autoraise_window = NULL; - } -} - -#ifdef HAVE_COMPOSITE_EXTENSIONS -void -meta_display_get_compositor_version (MetaDisplay *display, - int *major, - int *minor) -{ - *major = display->composite_major_version; - *minor = display->composite_minor_version; -} -#endif - -Display * -meta_display_get_xdisplay (MetaDisplay *display) -{ - return display->xdisplay; -} - -MetaCompositor * -meta_display_get_compositor (MetaDisplay *display) -{ - return display->compositor; -} - -GSList * -meta_display_get_screens (MetaDisplay *display) -{ - return display->screens; -} - -gboolean -meta_display_has_shape (MetaDisplay *display) -{ - return META_DISPLAY_HAS_SHAPE (display); -} - -MetaWindow * -meta_display_get_focus_window (MetaDisplay *display) -{ - return display->focus_window; -} - -#ifdef HAVE_COMPOSITE_EXTENSIONS -int -meta_display_get_damage_event_base (MetaDisplay *display) -{ - return display->damage_event_base; -} -#endif - -#ifdef HAVE_COMPOSITE_EXTENSIONS -#ifdef HAVE_SHAPE -int -meta_display_get_shape_event_base (MetaDisplay *display) -{ - return display->shape_event_base; -} -#endif -#endif diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c deleted file mode 100644 index fb7c2d2e..00000000 --- a/src/core/edge-resistance.c +++ /dev/null @@ -1,1277 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Edge resistance for move/resize operations */ - -/* - * Copyright (C) 2005, 2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "edge-resistance.h" -#include "boxes.h" -#include "display-private.h" -#include "workspace.h" - -/* A simple macro for whether a given window's edges are potentially - * relevant for resistance/snapping during a move/resize operation - */ -#define WINDOW_EDGES_RELEVANT(window, display) \ - meta_window_should_be_showing (window) && \ - window->screen == display->grab_screen && \ - window != display->grab_window && \ - window->type != META_WINDOW_DESKTOP && \ - window->type != META_WINDOW_MENU && \ - window->type != META_WINDOW_SPLASHSCREEN - -struct ResistanceDataForAnEdge -{ - gboolean timeout_setup; - guint timeout_id; - int timeout_edge_pos; - gboolean timeout_over; - GSourceFunc timeout_func; - MetaWindow *window; - int keyboard_buildup; -}; -typedef struct ResistanceDataForAnEdge ResistanceDataForAnEdge; - -struct MetaEdgeResistanceData -{ - GArray *left_edges; - GArray *right_edges; - GArray *top_edges; - GArray *bottom_edges; - - ResistanceDataForAnEdge left_data; - ResistanceDataForAnEdge right_data; - ResistanceDataForAnEdge top_data; - ResistanceDataForAnEdge bottom_data; -}; - -/* !WARNING!: this function can return invalid indices (namely, either -1 or - * edges->len); this is by design, but you need to remember this. - */ -static int -find_index_of_edge_near_position (const GArray *edges, - int position, - gboolean want_interval_min, - gboolean horizontal) -{ - /* This is basically like a binary search, except that we're trying to - * find a range instead of an exact value. So, if we have in our array - * Value: 3 27 316 316 316 505 522 800 1213 - * Index: 0 1 2 3 4 5 6 7 8 - * and we call this function with position=500 & want_interval_min=TRUE - * then we should get 5 (because 505 is the first value bigger than 500). - * If we call this function with position=805 and want_interval_min=FALSE - * then we should get 7 (because 800 is the last value smaller than 800). - * A couple more, to make things clear: - * position want_interval_min correct_answer - * 316 TRUE 2 - * 316 FALSE 4 - * 2 FALSE -1 - * 2000 TRUE 9 - */ - int low, high, mid; - int compare; - MetaEdge *edge; - - /* Initialize mid, edge, & compare in the off change that the array only - * has one element. - */ - mid = 0; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - - /* Begin the search... */ - low = 0; - high = edges->len - 1; - while (low < high) - { - mid = low + (high - low)/2; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - - if (compare == position) - break; - - if (compare > position) - high = mid - 1; - else - low = mid + 1; - } - - /* mid should now be _really_ close to the index we want, so we start - * linearly searching. However, note that we don't know if mid is less - * than or greater than what we need and it's possible that there are - * several equal values equal to what we were searching for and we ended - * up in the middle of them instead of at the end. So we may need to - * move mid multiple locations over. - */ - if (want_interval_min) - { - while (compare >= position && mid > 0) - { - mid--; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - } - while (compare < position && mid < (int)edges->len - 1) - { - mid++; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - } - - /* Special case for no values in array big enough */ - if (compare < position) - return edges->len; - - /* Return the found value */ - return mid; - } - else - { - while (compare <= position && mid < (int)edges->len - 1) - { - mid++; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - } - while (compare > position && mid > 0) - { - mid--; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - } - - /* Special case for no values in array small enough */ - if (compare > position) - return -1; - - /* Return the found value */ - return mid; - } -} - -static gboolean -points_on_same_side (int ref, int pt1, int pt2) -{ - return (pt1 - ref) * (pt2 - ref) > 0; -} - -static int -find_nearest_position (const GArray *edges, - int position, - int old_position, - const MetaRectangle *new_rect, - gboolean horizontal, - gboolean only_forward) -{ - /* This is basically just a binary search except that we're looking - * for the value closest to position, rather than finding that - * actual value. Also, we ignore any edges that aren't relevant - * given the horizontal/vertical position of new_rect. - */ - int low, high, mid; - int compare; - MetaEdge *edge; - int best, best_dist, i; - gboolean edges_align; - - /* Initialize mid, edge, & compare in the off change that the array only - * has one element. - */ - mid = 0; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - - /* Begin the search... */ - low = 0; - high = edges->len - 1; - while (low < high) - { - mid = low + (high - low)/2; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - - if (compare == position) - break; - - if (compare > position) - high = mid - 1; - else - low = mid + 1; - } - - /* mid should now be _really_ close to the index we want, so we - * start searching nearby for something that overlaps and is closer - * than the original position. - */ - best = old_position; - best_dist = INT_MAX; - - /* Start the search at mid */ - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - edges_align = meta_rectangle_edge_aligns (new_rect, edge); - if (edges_align && - (!only_forward || !points_on_same_side (position, compare, old_position))) - { - int dist = ABS (compare - position); - if (dist < best_dist) - { - best = compare; - best_dist = dist; - } - } - - /* Now start searching higher than mid */ - for (i = mid + 1; i < (int)edges->len; i++) - { - edge = g_array_index (edges, MetaEdge*, i); - compare = horizontal ? edge->rect.x : edge->rect.y; - - edges_align = horizontal ? - meta_rectangle_vert_overlap (&edge->rect, new_rect) : - meta_rectangle_horiz_overlap (&edge->rect, new_rect); - - if (edges_align && - (!only_forward || - !points_on_same_side (position, compare, old_position))) - { - int dist = ABS (compare - position); - if (dist < best_dist) - { - best = compare; - best_dist = dist; - } - break; - } - } - - /* Now start searching lower than mid */ - for (i = mid-1; i >= 0; i--) - { - edge = g_array_index (edges, MetaEdge*, i); - compare = horizontal ? edge->rect.x : edge->rect.y; - - edges_align = horizontal ? - meta_rectangle_vert_overlap (&edge->rect, new_rect) : - meta_rectangle_horiz_overlap (&edge->rect, new_rect); - - if (edges_align && - (!only_forward || - !points_on_same_side (position, compare, old_position))) - { - int dist = ABS (compare - position); - if (dist < best_dist) - { - best = compare; - best_dist = dist; - } - break; - } - } - - /* Return the best one found */ - return best; -} - -static gboolean -movement_towards_edge (MetaDirection side, int increment) -{ - switch (side) - { - case META_DIRECTION_LEFT: - case META_DIRECTION_TOP: - return increment < 0; - case META_DIRECTION_RIGHT: - case META_DIRECTION_BOTTOM: - return increment > 0; - default: - g_assert_not_reached (); - } -} - -static gboolean -edge_resistance_timeout (gpointer data) -{ - ResistanceDataForAnEdge *resistance_data = data; - - resistance_data->timeout_over = TRUE; - resistance_data->timeout_id = 0; - (*resistance_data->timeout_func)(resistance_data->window); - - return FALSE; -} - -static int -apply_edge_resistance (MetaWindow *window, - int old_pos, - int new_pos, - const MetaRectangle *old_rect, - const MetaRectangle *new_rect, - GArray *edges, - ResistanceDataForAnEdge *resistance_data, - GSourceFunc timeout_func, - gboolean xdir, - gboolean keyboard_op) -{ - int i, begin, end; - int last_edge; - gboolean increasing = new_pos > old_pos; - int increment = increasing ? 1 : -1; - - const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW = 16; - const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW = 0; - const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA = 32; - const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA = 0; - const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN = 32; - const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN = 0; - const int TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW = 0; - const int TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA = 0; - const int TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN = 0; - - /* Quit if no movement was specified */ - if (old_pos == new_pos) - return new_pos; - - /* Remove the old timeout if it's no longer relevant */ - if (resistance_data->timeout_setup && - ((resistance_data->timeout_edge_pos > old_pos && - resistance_data->timeout_edge_pos > new_pos) || - (resistance_data->timeout_edge_pos < old_pos && - resistance_data->timeout_edge_pos < new_pos))) - { - resistance_data->timeout_setup = FALSE; - if (resistance_data->timeout_id != 0) - { - g_source_remove (resistance_data->timeout_id); - resistance_data->timeout_id = 0; - } - } - - /* Get the range of indices in the edge array that we move past/to. */ - begin = find_index_of_edge_near_position (edges, old_pos, increasing, xdir); - end = find_index_of_edge_near_position (edges, new_pos, !increasing, xdir); - - /* begin and end can be outside the array index, if the window is partially - * off the screen - */ - last_edge = edges->len - 1; - begin = CLAMP (begin, 0, last_edge); - end = CLAMP (end, 0, last_edge); - - /* Loop over all these edges we're moving past/to. */ - i = begin; - while ((increasing && i <= end) || - (!increasing && i >= end)) - { - gboolean edges_align; - MetaEdge *edge = g_array_index (edges, MetaEdge*, i); - int compare = xdir ? edge->rect.x : edge->rect.y; - - /* Find out if this edge is relevant */ - edges_align = meta_rectangle_edge_aligns (new_rect, edge) || - meta_rectangle_edge_aligns (old_rect, edge); - - /* Nothing to do unless the edges align */ - if (!edges_align) - { - /* Go to the next edge in the range */ - i += increment; - continue; - } - - /* Rest is easier to read if we split on keyboard vs. mouse op */ - if (keyboard_op) - { - if ((old_pos < compare && compare < new_pos) || - (old_pos > compare && compare > new_pos)) - return compare; - } - else /* mouse op */ - { - int threshold; - - /* TIMEOUT RESISTANCE: If the edge is relevant and we're moving - * towards it, then we may want to have some kind of time delay - * before the user can move past this edge. - */ - if (movement_towards_edge (edge->side_type, increment)) - { - /* First, determine the length of time for the resistance */ - int timeout_length_ms = 0; - switch (edge->edge_type) - { - case META_EDGE_WINDOW: - timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW; - break; - case META_EDGE_XINERAMA: - timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA; - break; - case META_EDGE_SCREEN: - timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN; - break; - } - - if (!resistance_data->timeout_setup && - timeout_length_ms != 0) - { - resistance_data->timeout_id = - g_timeout_add (timeout_length_ms, - edge_resistance_timeout, - resistance_data); - resistance_data->timeout_setup = TRUE; - resistance_data->timeout_edge_pos = compare; - resistance_data->timeout_over = FALSE; - resistance_data->timeout_func = timeout_func; - resistance_data->window = window; - } - if (!resistance_data->timeout_over && - timeout_length_ms != 0) - return compare; - } - - /* PIXEL DISTANCE MOUSE RESISTANCE: If the edge matters and the - * user hasn't moved at least threshold pixels past this edge, - * stop movement at this edge. (Note that this is different from - * keyboard resistance precisely because keyboard move ops are - * relative to previous positions, whereas mouse move ops are - * relative to differences in mouse position and mouse position - * is an absolute quantity rather than a relative quantity) - */ - - /* First, determine the threshold */ - threshold = 0; - switch (edge->edge_type) - { - case META_EDGE_WINDOW: - if (movement_towards_edge (edge->side_type, increment)) - threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW; - else - threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW; - break; - case META_EDGE_XINERAMA: - if (movement_towards_edge (edge->side_type, increment)) - threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA; - else - threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA; - break; - case META_EDGE_SCREEN: - if (movement_towards_edge (edge->side_type, increment)) - threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN; - else - threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN; - break; - } - - if (ABS (compare - new_pos) < threshold) - return compare; - } - - /* Go to the next edge in the range */ - i += increment; - } - - return new_pos; -} - -static int -apply_edge_snapping (int old_pos, - int new_pos, - const MetaRectangle *new_rect, - GArray *edges, - gboolean xdir, - gboolean keyboard_op) -{ - int snap_to; - - if (old_pos == new_pos) - return new_pos; - - snap_to = find_nearest_position (edges, - new_pos, - old_pos, - new_rect, - xdir, - keyboard_op); - - /* If mouse snap-moving, the user could easily accidentally move just a - * couple pixels in a direction they didn't mean to move; so ignore snap - * movement in those cases unless it's only a small number of pixels - * anyway. - */ - if (!keyboard_op && - ABS (snap_to - old_pos) >= 8 && - ABS (new_pos - old_pos) < 8) - return old_pos; - else - /* Otherwise, return the snapping position found */ - return snap_to; -} - -/* This function takes the position (including any frame) of the window and - * a proposed new position (ignoring edge resistance/snapping), and then - * applies edge resistance to EACH edge (separately) updating new_outer. - * It returns true if new_outer is modified, false otherwise. - * - * display->grab_edge_resistance_data MUST already be setup or calling this - * function will cause a crash. - */ -static gboolean -apply_edge_resistance_to_each_side (MetaDisplay *display, - MetaWindow *window, - const MetaRectangle *old_outer, - MetaRectangle *new_outer, - GSourceFunc timeout_func, - gboolean auto_snap, - gboolean keyboard_op, - gboolean is_resize) -{ - MetaEdgeResistanceData *edge_data; - MetaRectangle modified_rect; - gboolean modified; - int new_left, new_right, new_top, new_bottom; - - g_assert (display->grab_edge_resistance_data != NULL); - edge_data = display->grab_edge_resistance_data; - - if (auto_snap) - { - /* Do the auto snapping instead of normal edge resistance; in all - * cases, we allow snapping to opposite kinds of edges (e.g. left - * sides of windows to both left and right edges. - */ - - new_left = apply_edge_snapping (BOX_LEFT (*old_outer), - BOX_LEFT (*new_outer), - new_outer, - edge_data->left_edges, - TRUE, - keyboard_op); - - new_right = apply_edge_snapping (BOX_RIGHT (*old_outer), - BOX_RIGHT (*new_outer), - new_outer, - edge_data->right_edges, - TRUE, - keyboard_op); - - new_top = apply_edge_snapping (BOX_TOP (*old_outer), - BOX_TOP (*new_outer), - new_outer, - edge_data->top_edges, - FALSE, - keyboard_op); - - new_bottom = apply_edge_snapping (BOX_BOTTOM (*old_outer), - BOX_BOTTOM (*new_outer), - new_outer, - edge_data->bottom_edges, - FALSE, - keyboard_op); - } - else - { - /* Disable edge resistance for resizes when windows have size - * increment hints; see #346782. For all other cases, apply - * them. - */ - if (!is_resize || window->size_hints.width_inc == 1) - { - /* Now, apply the normal horizontal edge resistance */ - new_left = apply_edge_resistance (window, - BOX_LEFT (*old_outer), - BOX_LEFT (*new_outer), - old_outer, - new_outer, - edge_data->left_edges, - &edge_data->left_data, - timeout_func, - TRUE, - keyboard_op); - new_right = apply_edge_resistance (window, - BOX_RIGHT (*old_outer), - BOX_RIGHT (*new_outer), - old_outer, - new_outer, - edge_data->right_edges, - &edge_data->right_data, - timeout_func, - TRUE, - keyboard_op); - } - else - { - new_left = new_outer->x; - new_right = new_outer->x + new_outer->width; - } - /* Same for vertical resizes... */ - if (!is_resize || window->size_hints.height_inc == 1) - { - new_top = apply_edge_resistance (window, - BOX_TOP (*old_outer), - BOX_TOP (*new_outer), - old_outer, - new_outer, - edge_data->top_edges, - &edge_data->top_data, - timeout_func, - FALSE, - keyboard_op); - new_bottom = apply_edge_resistance (window, - BOX_BOTTOM (*old_outer), - BOX_BOTTOM (*new_outer), - old_outer, - new_outer, - edge_data->bottom_edges, - &edge_data->bottom_data, - timeout_func, - FALSE, - keyboard_op); - } - else - { - new_top = new_outer->y; - new_bottom = new_outer->y + new_outer->height; - } - } - - /* Determine whether anything changed, and save the changes */ - modified_rect = meta_rect (new_left, - new_top, - new_right - new_left, - new_bottom - new_top); - modified = !meta_rectangle_equal (new_outer, &modified_rect); - *new_outer = modified_rect; - return modified; -} - -void -meta_display_cleanup_edges (MetaDisplay *display) -{ - guint i,j; - MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data; - GHashTable *edges_to_be_freed; - - g_assert (edge_data != NULL); - - /* We first need to clean out any window edges */ - edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal, - g_free, NULL); - for (i = 0; i < 4; i++) - { - GArray *tmp = NULL; - MetaDirection dir; - switch (i) - { - case 0: - tmp = edge_data->left_edges; - dir = META_DIRECTION_LEFT; - break; - case 1: - tmp = edge_data->right_edges; - dir = META_DIRECTION_RIGHT; - break; - case 2: - tmp = edge_data->top_edges; - dir = META_DIRECTION_TOP; - break; - case 3: - tmp = edge_data->bottom_edges; - dir = META_DIRECTION_BOTTOM; - break; - default: - g_assert_not_reached (); - } - - for (j = 0; j < tmp->len; j++) - { - MetaEdge *edge = g_array_index (tmp, MetaEdge*, j); - if (edge->edge_type == META_EDGE_WINDOW && - edge->side_type == dir) - { - /* The same edge will appear in two arrays, and we can't free - * it yet we still need to compare edge->side_type for the other - * array that it is in. So store it in a hash table for later - * freeing. Could also do this in a simple linked list. - */ - g_hash_table_insert (edges_to_be_freed, edge, edge); - } - } - } - - /* Now free all the window edges (the key destroy function is g_free) */ - g_hash_table_destroy (edges_to_be_freed); - - /* Now free the arrays and data */ - g_array_free (edge_data->left_edges, TRUE); - g_array_free (edge_data->right_edges, TRUE); - g_array_free (edge_data->top_edges, TRUE); - g_array_free (edge_data->bottom_edges, TRUE); - edge_data->left_edges = NULL; - edge_data->right_edges = NULL; - edge_data->top_edges = NULL; - edge_data->bottom_edges = NULL; - - /* Cleanup the timeouts */ - if (edge_data->left_data.timeout_setup && - edge_data->left_data.timeout_id != 0) - g_source_remove (edge_data->left_data.timeout_id); - if (edge_data->right_data.timeout_setup && - edge_data->right_data.timeout_id != 0) - g_source_remove (edge_data->right_data.timeout_id); - if (edge_data->top_data.timeout_setup && - edge_data->top_data.timeout_id != 0) - g_source_remove (edge_data->top_data.timeout_id); - if (edge_data->bottom_data.timeout_setup && - edge_data->bottom_data.timeout_id != 0) - g_source_remove (edge_data->bottom_data.timeout_id); - - g_free (display->grab_edge_resistance_data); - display->grab_edge_resistance_data = NULL; -} - -static int -stupid_sort_requiring_extra_pointer_dereference (gconstpointer a, - gconstpointer b) -{ - const MetaEdge * const *a_edge = a; - const MetaEdge * const *b_edge = b; - return meta_rectangle_edge_cmp_ignore_type (*a_edge, *b_edge); -} - -static void -cache_edges (MetaDisplay *display, - GList *window_edges, - GList *xinerama_edges, - GList *screen_edges) -{ - MetaEdgeResistanceData *edge_data; - GList *tmp; - int num_left, num_right, num_top, num_bottom; - int i; - - /* - * 0th: Print debugging information to the log about the edges - */ -#ifdef WITH_VERBOSE_MODE - if (meta_is_verbose()) - { - int max_edges = MAX (MAX( g_list_length (window_edges), - g_list_length (xinerama_edges)), - g_list_length (screen_edges)); - char big_buffer[(EDGE_LENGTH+2)*max_edges]; - - meta_rectangle_edge_list_to_string (window_edges, ", ", big_buffer); - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "Window edges for resistance : %s\n", big_buffer); - - meta_rectangle_edge_list_to_string (xinerama_edges, ", ", big_buffer); - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "Xinerama edges for resistance: %s\n", big_buffer); - - meta_rectangle_edge_list_to_string (screen_edges, ", ", big_buffer); - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "Screen edges for resistance : %s\n", big_buffer); - } -#endif - - /* - * 1st: Get the total number of each kind of edge - */ - num_left = num_right = num_top = num_bottom = 0; - for (i = 0; i < 3; i++) - { - tmp = NULL; - switch (i) - { - case 0: - tmp = window_edges; - break; - case 1: - tmp = xinerama_edges; - break; - case 2: - tmp = screen_edges; - break; - default: - g_assert_not_reached (); - } - - while (tmp) - { - MetaEdge *edge = tmp->data; - switch (edge->side_type) - { - case META_DIRECTION_LEFT: - num_left++; - break; - case META_DIRECTION_RIGHT: - num_right++; - break; - case META_DIRECTION_TOP: - num_top++; - break; - case META_DIRECTION_BOTTOM: - num_bottom++; - break; - default: - g_assert_not_reached (); - } - tmp = tmp->next; - } - } - - /* - * 2nd: Allocate the edges - */ - g_assert (display->grab_edge_resistance_data == NULL); - display->grab_edge_resistance_data = g_new (MetaEdgeResistanceData, 1); - edge_data = display->grab_edge_resistance_data; - edge_data->left_edges = g_array_sized_new (FALSE, - FALSE, - sizeof(MetaEdge*), - num_left + num_right); - edge_data->right_edges = g_array_sized_new (FALSE, - FALSE, - sizeof(MetaEdge*), - num_left + num_right); - edge_data->top_edges = g_array_sized_new (FALSE, - FALSE, - sizeof(MetaEdge*), - num_top + num_bottom); - edge_data->bottom_edges = g_array_sized_new (FALSE, - FALSE, - sizeof(MetaEdge*), - num_top + num_bottom); - - /* - * 3rd: Add the edges to the arrays - */ - for (i = 0; i < 3; i++) - { - tmp = NULL; - switch (i) - { - case 0: - tmp = window_edges; - break; - case 1: - tmp = xinerama_edges; - break; - case 2: - tmp = screen_edges; - break; - default: - g_assert_not_reached (); - } - - while (tmp) - { - MetaEdge *edge = tmp->data; - switch (edge->side_type) - { - case META_DIRECTION_LEFT: - case META_DIRECTION_RIGHT: - g_array_append_val (edge_data->left_edges, edge); - g_array_append_val (edge_data->right_edges, edge); - break; - case META_DIRECTION_TOP: - case META_DIRECTION_BOTTOM: - g_array_append_val (edge_data->top_edges, edge); - g_array_append_val (edge_data->bottom_edges, edge); - break; - default: - g_assert_not_reached (); - } - tmp = tmp->next; - } - } - - /* - * 4th: Sort the arrays (FIXME: This is kinda dumb since the arrays were - * individually sorted earlier and we could have done this faster and - * avoided this sort by sticking them into the array with some simple - * merging of the lists). - */ - g_array_sort (display->grab_edge_resistance_data->left_edges, - stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->right_edges, - stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->top_edges, - stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->bottom_edges, - stupid_sort_requiring_extra_pointer_dereference); -} - -static void -initialize_grab_edge_resistance_data (MetaDisplay *display) -{ - MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data; - - edge_data->left_data.timeout_setup = FALSE; - edge_data->right_data.timeout_setup = FALSE; - edge_data->top_data.timeout_setup = FALSE; - edge_data->bottom_data.timeout_setup = FALSE; - - edge_data->left_data.keyboard_buildup = 0; - edge_data->right_data.keyboard_buildup = 0; - edge_data->top_data.keyboard_buildup = 0; - edge_data->bottom_data.keyboard_buildup = 0; -} - -void -meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display) -{ - GList *stacked_windows; - GList *cur_window_iter; - GList *edges; - /* Lists of window positions (rects) and their relative stacking positions */ - int stack_position; - GSList *obscuring_windows, *window_stacking; - /* The portions of the above lists that still remain at the stacking position - * in the layer that we are working on - */ - GSList *rem_windows, *rem_win_stacking; - - /* - * 1st: Get the list of relevant windows, from bottom to top - */ - stacked_windows = - meta_stack_list_windows (display->grab_screen->stack, - display->grab_screen->active_workspace); - - /* - * 2nd: we need to separate that stacked list into a list of windows that - * can obscure other edges. To make sure we only have windows obscuring - * those below it instead of going both ways, we also need to keep a - * counter list. Messy, I know. - */ - obscuring_windows = window_stacking = NULL; - cur_window_iter = stacked_windows; - stack_position = 0; - while (cur_window_iter != NULL) - { - MetaWindow *cur_window = cur_window_iter->data; - if (WINDOW_EDGES_RELEVANT (cur_window, display)) - { - MetaRectangle *new_rect; - new_rect = g_new (MetaRectangle, 1); - meta_window_get_outer_rect (cur_window, new_rect); - obscuring_windows = g_slist_prepend (obscuring_windows, new_rect); - window_stacking = - g_slist_prepend (window_stacking, GINT_TO_POINTER (stack_position)); - } - - stack_position++; - cur_window_iter = cur_window_iter->next; - } - /* Put 'em in bottom to top order */ - rem_windows = g_slist_reverse (obscuring_windows); - rem_win_stacking = g_slist_reverse (window_stacking); - - /* - * 3rd: loop over the windows again, this time getting the edges from - * them and removing intersections with the relevant obscuring_windows & - * obscuring_docks. - */ - edges = NULL; - stack_position = 0; - cur_window_iter = stacked_windows; - while (cur_window_iter != NULL) - { - MetaRectangle cur_rect; - MetaWindow *cur_window = cur_window_iter->data; - meta_window_get_outer_rect (cur_window, &cur_rect); - - /* Check if we want to use this window's edges for edge - * resistance (note that dock edges are considered screen edges - * which are handled separately - */ - if (WINDOW_EDGES_RELEVANT (cur_window, display) && - cur_window->type != META_WINDOW_DOCK) - { - GList *new_edges; - MetaEdge *new_edge; - MetaRectangle reduced; - - /* We don't care about snapping to any portion of the window that - * is offscreen (we also don't care about parts of edges covered - * by other windows or DOCKS, but that's handled below). - */ - meta_rectangle_intersect (&cur_rect, - &display->grab_screen->rect, - &reduced); - - new_edges = NULL; - - /* Left side of this window is resistance for the right edge of - * the window being moved. - */ - new_edge = g_new (MetaEdge, 1); - new_edge->rect = reduced; - new_edge->rect.width = 0; - new_edge->side_type = META_DIRECTION_RIGHT; - new_edge->edge_type = META_EDGE_WINDOW; - new_edges = g_list_prepend (new_edges, new_edge); - - /* Right side of this window is resistance for the left edge of - * the window being moved. - */ - new_edge = g_new (MetaEdge, 1); - new_edge->rect = reduced; - new_edge->rect.x += new_edge->rect.width; - new_edge->rect.width = 0; - new_edge->side_type = META_DIRECTION_LEFT; - new_edge->edge_type = META_EDGE_WINDOW; - new_edges = g_list_prepend (new_edges, new_edge); - - /* Top side of this window is resistance for the bottom edge of - * the window being moved. - */ - new_edge = g_new (MetaEdge, 1); - new_edge->rect = reduced; - new_edge->rect.height = 0; - new_edge->side_type = META_DIRECTION_BOTTOM; - new_edge->edge_type = META_EDGE_WINDOW; - new_edges = g_list_prepend (new_edges, new_edge); - - /* Top side of this window is resistance for the bottom edge of - * the window being moved. - */ - new_edge = g_new (MetaEdge, 1); - new_edge->rect = reduced; - new_edge->rect.y += new_edge->rect.height; - new_edge->rect.height = 0; - new_edge->side_type = META_DIRECTION_TOP; - new_edge->edge_type = META_EDGE_WINDOW; - new_edges = g_list_prepend (new_edges, new_edge); - - /* Update the remaining windows to only those at a higher - * stacking position than this one. - */ - while (rem_win_stacking && - stack_position >= GPOINTER_TO_INT (rem_win_stacking->data)) - { - rem_windows = rem_windows->next; - rem_win_stacking = rem_win_stacking->next; - } - - /* Remove edge portions overlapped by rem_windows and rem_docks */ - new_edges = - meta_rectangle_remove_intersections_with_boxes_from_edges ( - new_edges, - rem_windows); - - /* Save the new edges */ - edges = g_list_concat (new_edges, edges); - } - - stack_position++; - cur_window_iter = cur_window_iter->next; - } - - /* - * 4th: Free the extra memory not needed and sort the list - */ - g_list_free (stacked_windows); - /* Free the memory used by the obscuring windows/docks lists */ - g_slist_free (window_stacking); - /* FIXME: Shouldn't there be a helper function to make this one line of code - * to free a list instead of four ugly ones? - */ - g_slist_foreach (obscuring_windows, - (void (*)(gpointer,gpointer))&g_free, /* ew, for ugly */ - NULL); - g_slist_free (obscuring_windows); - - /* Sort the list. FIXME: Should I bother with this sorting? I just - * sort again later in cache_edges() anyway... - */ - edges = g_list_sort (edges, meta_rectangle_edge_cmp); - - /* - * 5th: Cache the combination of these edges with the onscreen and - * xinerama edges in an array for quick access. Free the edges since - * they've been cached elsewhere. - */ - cache_edges (display, - edges, - display->grab_screen->active_workspace->xinerama_edges, - display->grab_screen->active_workspace->screen_edges); - g_list_free (edges); - - /* - * 6th: Initialize the resistance timeouts and buildups - */ - initialize_grab_edge_resistance_data (display); -} - -/* Note that old_[xy] and new_[xy] are with respect to inner positions of - * the window. - */ -void -meta_window_edge_resistance_for_move (MetaWindow *window, - int old_x, - int old_y, - int *new_x, - int *new_y, - GSourceFunc timeout_func, - gboolean snap, - gboolean is_keyboard_op) -{ - MetaRectangle old_outer, proposed_outer, new_outer; - gboolean is_resize; - - if (window == window->display->grab_window && - window->display->grab_wireframe_active) - { - meta_window_get_xor_rect (window, - &window->display->grab_wireframe_rect, - &old_outer); - } - else - { - meta_window_get_outer_rect (window, &old_outer); - } - proposed_outer = old_outer; - proposed_outer.x += (*new_x - old_x); - proposed_outer.y += (*new_y - old_y); - new_outer = proposed_outer; - - window->display->grab_last_user_action_was_snap = snap; - is_resize = FALSE; - if (apply_edge_resistance_to_each_side (window->display, - window, - &old_outer, - &new_outer, - timeout_func, - snap, - is_keyboard_op, - is_resize)) - { - /* apply_edge_resistance_to_each_side independently applies - * resistance to both the right and left edges of new_outer as both - * could meet areas of resistance. But we don't want a resize, so we - * just have both edges move according to the stricter of the - * resistances. Same thing goes for top & bottom edges. - */ - MetaRectangle *reference; - int left_change, right_change, smaller_x_change; - int top_change, bottom_change, smaller_y_change; - - if (snap && !is_keyboard_op) - reference = &proposed_outer; - else - reference = &old_outer; - - left_change = BOX_LEFT (new_outer) - BOX_LEFT (*reference); - right_change = BOX_RIGHT (new_outer) - BOX_RIGHT (*reference); - if ( snap && is_keyboard_op && left_change == 0) - smaller_x_change = right_change; - else if (snap && is_keyboard_op && right_change == 0) - smaller_x_change = left_change; - else if (ABS (left_change) < ABS (right_change)) - smaller_x_change = left_change; - else - smaller_x_change = right_change; - - top_change = BOX_TOP (new_outer) - BOX_TOP (*reference); - bottom_change = BOX_BOTTOM (new_outer) - BOX_BOTTOM (*reference); - if ( snap && is_keyboard_op && top_change == 0) - smaller_y_change = bottom_change; - else if (snap && is_keyboard_op && bottom_change == 0) - smaller_y_change = top_change; - else if (ABS (top_change) < ABS (bottom_change)) - smaller_y_change = top_change; - else - smaller_y_change = bottom_change; - - *new_x = old_x + smaller_x_change + - (BOX_LEFT (*reference) - BOX_LEFT (old_outer)); - *new_y = old_y + smaller_y_change + - (BOX_TOP (*reference) - BOX_TOP (old_outer)); - - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "outer x & y move-to coordinate changed from %d,%d to %d,%d\n", - proposed_outer.x, proposed_outer.y, - old_outer.x + (*new_x - old_x), - old_outer.y + (*new_y - old_y)); - } -} - -/* Note that old_(width|height) and new_(width|height) are with respect to - * sizes of the inner window. - */ -void -meta_window_edge_resistance_for_resize (MetaWindow *window, - int old_width, - int old_height, - int *new_width, - int *new_height, - int gravity, - GSourceFunc timeout_func, - gboolean snap, - gboolean is_keyboard_op) -{ - MetaRectangle old_outer, new_outer; - int proposed_outer_width, proposed_outer_height; - gboolean is_resize; - - if (window == window->display->grab_window && - window->display->grab_wireframe_active) - { - meta_window_get_xor_rect (window, - &window->display->grab_wireframe_rect, - &old_outer); - } - else - { - meta_window_get_outer_rect (window, &old_outer); - } - proposed_outer_width = old_outer.width + (*new_width - old_width); - proposed_outer_height = old_outer.height + (*new_height - old_height); - meta_rectangle_resize_with_gravity (&old_outer, - &new_outer, - gravity, - proposed_outer_width, - proposed_outer_height); - - window->display->grab_last_user_action_was_snap = snap; - is_resize = TRUE; - if (apply_edge_resistance_to_each_side (window->display, - window, - &old_outer, - &new_outer, - timeout_func, - snap, - is_keyboard_op, - is_resize)) - { - *new_width = old_width + (new_outer.width - old_outer.width); - *new_height = old_height + (new_outer.height - old_outer.height); - - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "outer width & height got changed from %d,%d to %d,%d\n", - proposed_outer_width, proposed_outer_height, - new_outer.width, new_outer.height); - } -} diff --git a/src/core/edge-resistance.h b/src/core/edge-resistance.h deleted file mode 100644 index 14ba17a0..00000000 --- a/src/core/edge-resistance.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Edge resistance for move/resize operations */ - -/* - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_EDGE_RESISTANCE_H -#define META_EDGE_RESISTANCE_H - -#include "window-private.h" - -void meta_window_edge_resistance_for_move (MetaWindow *window, - int old_x, - int old_y, - int *new_x, - int *new_y, - GSourceFunc timeout_func, - gboolean snap, - gboolean is_keyboard_op); -void meta_window_edge_resistance_for_resize (MetaWindow *window, - int old_width, - int old_height, - int *new_width, - int *new_height, - int gravity, - GSourceFunc timeout_func, - gboolean snap, - gboolean is_keyboard_op); - -#endif /* META_EDGE_RESISTANCE_H */ - diff --git a/src/core/effects.c b/src/core/effects.c deleted file mode 100644 index be369799..00000000 --- a/src/core/effects.c +++ /dev/null @@ -1,735 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file effects.c "Special effects" other than compositor effects. - * - * Before we had a serious compositor, we supported swooping - * rectangles for minimising and so on. These are still supported - * today, even when the compositor is enabled. The file contains two - * parts: - * - * 1) A set of functions, each of which implements a special effect. - * (Only the minimize function does anything interesting; we should - * probably get rid of the rest.) - * - * 2) A set of functions for moving a highlighted wireframe box around - * the screen, optionally with height and width shown in the middle. - * This is used for moving and resizing when reduced_resources is set. - * - * There was formerly a system which allowed callers to drop in their - * own handlers for various things; it was never used (people who want - * their own handlers can just modify this file, after all) and it added - * a good deal of extra complexity, so it has been removed. If you want it, - * it can be found in svn r3769. - * - * Once upon a time there were three different ways of drawing the box - * animation: window wireframe, window opaque, and root. People who had - * the shape extension theoretically had the choice of all three, and - * people who didn't weren't given the choice of the wireframe option. - * In practice, though, the opaque animation was never perfect, so it came - * down to the wireframe option for those who had the extension and - * the root option for those who didn't; there was actually no way of choosing - * any other option anyway. Work on the opaque animation stopped in 2002; - * anyone who wants something like that these days will be using the - * compositor anyway. - * - * In svn r3769 this was made explicit. - */ - -/* - * Copyright (C) 2001 Anders Carlsson, Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "effects.h" -#include "display-private.h" -#include "ui.h" -#include "window-private.h" -#include "prefs.h" - -#ifdef HAVE_SHAPE -#include <X11/extensions/shape.h> -#endif - -#define META_MINIMIZE_ANIMATION_LENGTH 0.25 -#define META_SHADE_ANIMATION_LENGTH 0.2 - -#include <string.h> - -typedef struct MetaEffect MetaEffect; -typedef struct MetaEffectPriv MetaEffectPriv; - -typedef struct -{ - MetaScreen *screen; - - double millisecs_duration; - GTimeVal start_time; - -#ifdef HAVE_SHAPE - /** For wireframe window */ - Window wireframe_xwindow; -#else - /** Rectangle to erase */ - MetaRectangle last_rect; - - /** First time we've plotted anything in this animation? */ - gboolean first_time; - - /** For wireframe drawn on root window */ - GC gc; -#endif - - MetaRectangle start_rect; - MetaRectangle end_rect; - -} BoxAnimationContext; - -/** - * Information we need to know during a maximise or minimise effect. - */ -typedef struct -{ - /** This is the normal-size window. */ - MetaRectangle window_rect; - /** This is the size of the window when it's an icon. */ - MetaRectangle icon_rect; -} MetaMinimizeEffect, MetaUnminimizeEffect; - -struct MetaEffectPriv -{ - MetaEffectFinished finished; - gpointer finished_data; -}; - -struct MetaEffect -{ - /** The window the effect is applied to. */ - MetaWindow *window; - /** Which effect is happening here. */ - MetaEffectType type; - /** The effect handler can hang data here. */ - gpointer info; - - union - { - MetaMinimizeEffect minimize; - /* ... and theoretically anything else */ - } u; - - MetaEffectPriv *priv; -}; - -static void run_default_effect_handler (MetaEffect *effect); -static void run_handler (MetaEffect *effect); -static void effect_free (MetaEffect *effect); - -static MetaEffect * -create_effect (MetaEffectType type, - MetaWindow *window, - MetaEffectFinished finished, - gpointer finished_data); - -static void -draw_box_animation (MetaScreen *screen, - MetaRectangle *initial_rect, - MetaRectangle *destination_rect, - double seconds_duration); - -/** - * Creates an effect. - * - */ -static MetaEffect* -create_effect (MetaEffectType type, - MetaWindow *window, - MetaEffectFinished finished, - gpointer finished_data) -{ - MetaEffect *effect = g_new (MetaEffect, 1); - - effect->type = type; - effect->window = window; - effect->priv = g_new (MetaEffectPriv, 1); - effect->priv->finished = finished; - effect->priv->finished_data = finished_data; - - return effect; -} - -/** - * Destroys an effect. If the effect has a "finished" hook, it will be - * called before cleanup. - * - * \param effect The effect. - */ -static void -effect_free (MetaEffect *effect) -{ - if (effect->priv->finished) - effect->priv->finished (effect->priv->finished_data); - - g_free (effect->priv); - g_free (effect); -} - -void -meta_effect_run_focus (MetaWindow *window, - MetaEffectFinished finished, - gpointer data) -{ - MetaEffect *effect; - - g_return_if_fail (window != NULL); - - effect = create_effect (META_EFFECT_FOCUS, window, finished, data); - - run_handler (effect); -} - -void -meta_effect_run_minimize (MetaWindow *window, - MetaRectangle *window_rect, - MetaRectangle *icon_rect, - MetaEffectFinished finished, - gpointer data) -{ - MetaEffect *effect; - - g_return_if_fail (window != NULL); - g_return_if_fail (icon_rect != NULL); - - effect = create_effect (META_EFFECT_MINIMIZE, window, finished, data); - - effect->u.minimize.window_rect = *window_rect; - effect->u.minimize.icon_rect = *icon_rect; - - run_handler (effect); -} - -void -meta_effect_run_unminimize (MetaWindow *window, - MetaRectangle *window_rect, - MetaRectangle *icon_rect, - MetaEffectFinished finished, - gpointer data) -{ - MetaEffect *effect; - - g_return_if_fail (window != NULL); - g_return_if_fail (icon_rect != NULL); - - effect = create_effect (META_EFFECT_UNMINIMIZE, window, finished, data); - - effect->u.minimize.window_rect = *window_rect; - effect->u.minimize.icon_rect = *icon_rect; - - run_handler (effect); -} - -void -meta_effect_run_close (MetaWindow *window, - MetaEffectFinished finished, - gpointer data) -{ - MetaEffect *effect; - - g_return_if_fail (window != NULL); - - effect = create_effect (META_EFFECT_CLOSE, window, - finished, data); - - run_handler (effect); -} - - -/* old ugly minimization effect */ - -#ifdef HAVE_SHAPE -static void -update_wireframe_window (MetaDisplay *display, - Window xwindow, - const MetaRectangle *rect) -{ - XMoveResizeWindow (display->xdisplay, - xwindow, - rect->x, rect->y, - rect->width, rect->height); - -#define OUTLINE_WIDTH 3 - - if (rect->width > OUTLINE_WIDTH * 2 && - rect->height > OUTLINE_WIDTH * 2) - { - XRectangle xrect; - Region inner_xregion; - Region outer_xregion; - - inner_xregion = XCreateRegion (); - outer_xregion = XCreateRegion (); - - xrect.x = 0; - xrect.y = 0; - xrect.width = rect->width; - xrect.height = rect->height; - - XUnionRectWithRegion (&xrect, outer_xregion, outer_xregion); - - xrect.x += OUTLINE_WIDTH; - xrect.y += OUTLINE_WIDTH; - xrect.width -= OUTLINE_WIDTH * 2; - xrect.height -= OUTLINE_WIDTH * 2; - - XUnionRectWithRegion (&xrect, inner_xregion, inner_xregion); - - XSubtractRegion (outer_xregion, inner_xregion, outer_xregion); - - XShapeCombineRegion (display->xdisplay, xwindow, - ShapeBounding, 0, 0, outer_xregion, ShapeSet); - - XDestroyRegion (outer_xregion); - XDestroyRegion (inner_xregion); - } - else - { - /* Unset the shape */ - XShapeCombineMask (display->xdisplay, xwindow, - ShapeBounding, 0, 0, None, ShapeSet); - } -} -#endif - -/** - * A hack to force the X server to synchronize with the - * graphics hardware. - */ -static void -graphics_sync (BoxAnimationContext *context) -{ - XImage *image; - - image = XGetImage (context->screen->display->xdisplay, - context->screen->xroot, - 0, 0, 1, 1, - AllPlanes, ZPixmap); - - XDestroyImage (image); -} - -static gboolean -effects_draw_box_animation_timeout (BoxAnimationContext *context) -{ - double elapsed; - GTimeVal current_time; - MetaRectangle draw_rect; - double fraction; - -#ifndef HAVE_SHAPE - if (!context->first_time) - { - /* Restore the previously drawn background */ - XDrawRectangle (context->screen->display->xdisplay, - context->screen->xroot, - context->gc, - context->last_rect.x, context->last_rect.y, - context->last_rect.width, context->last_rect.height); - } - else - context->first_time = FALSE; - -#endif /* !HAVE_SHAPE */ - - g_get_current_time (¤t_time); - - /* We use milliseconds for all times */ - elapsed = - ((((double)current_time.tv_sec - context->start_time.tv_sec) * G_USEC_PER_SEC + - (current_time.tv_usec - context->start_time.tv_usec))) / 1000.0; - - if (elapsed < 0) - { - /* Probably the system clock was set backwards? */ - meta_warning ("System clock seemed to go backwards?\n"); - elapsed = G_MAXDOUBLE; /* definitely done. */ - } - - if (elapsed > context->millisecs_duration) - { - /* All done */ -#ifdef HAVE_SHAPE - XDestroyWindow (context->screen->display->xdisplay, - context->wireframe_xwindow); -#else - meta_display_ungrab (context->screen->display); - meta_ui_pop_delay_exposes (context->screen->ui); - XFreeGC (context->screen->display->xdisplay, - context->gc); -#endif /* !HAVE_SHAPE */ - - graphics_sync (context); - - g_free (context); - return FALSE; - } - - g_assert (context->millisecs_duration > 0.0); - fraction = elapsed / context->millisecs_duration; - - draw_rect = context->start_rect; - - /* Now add a delta proportional to elapsed time. */ - draw_rect.x += (context->end_rect.x - context->start_rect.x) * fraction; - draw_rect.y += (context->end_rect.y - context->start_rect.y) * fraction; - draw_rect.width += (context->end_rect.width - context->start_rect.width) * fraction; - draw_rect.height += (context->end_rect.height - context->start_rect.height) * fraction; - - /* don't confuse X or gdk-pixbuf with bogus rectangles */ - if (draw_rect.width < 1) - draw_rect.width = 1; - if (draw_rect.height < 1) - draw_rect.height = 1; - -#ifdef HAVE_SHAPE - update_wireframe_window (context->screen->display, - context->wireframe_xwindow, - &draw_rect); -#else - context->last_rect = draw_rect; - - /* Draw the rectangle */ - XDrawRectangle (context->screen->display->xdisplay, - context->screen->xroot, - context->gc, - draw_rect.x, draw_rect.y, - draw_rect.width, draw_rect.height); - -#endif /* !HAVE_SHAPE */ - - /* kick changes onto the server */ - graphics_sync (context); - - return TRUE; -} - -void -draw_box_animation (MetaScreen *screen, - MetaRectangle *initial_rect, - MetaRectangle *destination_rect, - double seconds_duration) -{ - BoxAnimationContext *context; - -#ifdef HAVE_SHAPE - XSetWindowAttributes attrs; -#else - XGCValues gc_values; -#endif - - g_return_if_fail (seconds_duration > 0.0); - - if (g_getenv ("METACITY_DEBUG_EFFECTS")) - seconds_duration *= 10; /* slow things down */ - - /* Create the animation context */ - context = g_new0 (BoxAnimationContext, 1); - - context->screen = screen; - - context->millisecs_duration = seconds_duration * 1000.0; - - context->start_rect = *initial_rect; - context->end_rect = *destination_rect; - -#ifdef HAVE_SHAPE - - attrs.override_redirect = True; - attrs.background_pixel = BlackPixel (screen->display->xdisplay, - screen->number); - - context->wireframe_xwindow = XCreateWindow (screen->display->xdisplay, - screen->xroot, - initial_rect->x, - initial_rect->y, - initial_rect->width, - initial_rect->height, - 0, - CopyFromParent, - CopyFromParent, - (Visual *)CopyFromParent, - CWOverrideRedirect | CWBackPixel, - &attrs); - - update_wireframe_window (screen->display, - context->wireframe_xwindow, - initial_rect); - - XMapWindow (screen->display->xdisplay, - context->wireframe_xwindow); - -#else /* !HAVE_SHAPE */ - - context->first_time = TRUE; - gc_values.subwindow_mode = IncludeInferiors; - gc_values.function = GXinvert; - - context->gc = XCreateGC (screen->display->xdisplay, - screen->xroot, - GCSubwindowMode | GCFunction, - &gc_values); - - /* Grab the X server to avoid screen dirt */ - meta_display_grab (context->screen->display); - meta_ui_push_delay_exposes (context->screen->ui); -#endif - - /* Do this only after we get the pixbuf from the server, - * so that the animation doesn't get truncated. - */ - g_get_current_time (&context->start_time); - - /* Add the timeout - a short one, could even use an idle, - * but this is maybe more CPU-friendly. - */ - g_timeout_add (15, - (GSourceFunc)effects_draw_box_animation_timeout, - context); - - /* kick changes onto the server */ - XFlush (context->screen->display->xdisplay); -} - -void -meta_effects_begin_wireframe (MetaScreen *screen, - const MetaRectangle *rect, - int width, - int height) -{ - /* Grab the X server to avoid screen dirt */ - meta_display_grab (screen->display); - meta_ui_push_delay_exposes (screen->ui); - - meta_effects_update_wireframe (screen, - NULL, -1, -1, - rect, width, height); -} - -static void -draw_xor_rect (MetaScreen *screen, - const MetaRectangle *rect, - int width, - int height) -{ - /* The lines in the center can't overlap the rectangle or each - * other, or the XOR gets reversed. So we have to draw things - * a bit oddly. - */ - XSegment segments[8]; - MetaRectangle shrunk_rect; - int i; - -#define LINE_WIDTH META_WIREFRAME_XOR_LINE_WIDTH - - /* We don't want the wireframe going outside the window area. - * It makes it harder for the user to position windows and it exposes other - * annoying bugs. - */ - shrunk_rect = *rect; - - shrunk_rect.x += LINE_WIDTH / 2 + LINE_WIDTH % 2; - shrunk_rect.y += LINE_WIDTH / 2 + LINE_WIDTH % 2; - shrunk_rect.width -= LINE_WIDTH + 2 * (LINE_WIDTH % 2); - shrunk_rect.height -= LINE_WIDTH + 2 * (LINE_WIDTH % 2); - - XDrawRectangle (screen->display->xdisplay, - screen->xroot, - screen->root_xor_gc, - shrunk_rect.x, shrunk_rect.y, - shrunk_rect.width, shrunk_rect.height); - - /* Don't put lines inside small rectangles where they won't fit */ - if (shrunk_rect.width < (LINE_WIDTH * 4) || - shrunk_rect.height < (LINE_WIDTH * 4)) - return; - - if ((width >= 0) && (height >= 0)) - { - XGCValues gc_values = { 0 }; - - if (XGetGCValues (screen->display->xdisplay, - screen->root_xor_gc, - GCFont, &gc_values)) - { - char *text; - int text_length; - - XFontStruct *font_struct; - int text_width, text_height; - int box_x, box_y; - int box_width, box_height; - - font_struct = XQueryFont (screen->display->xdisplay, - gc_values.font); - - if (font_struct != NULL) - { - text = g_strdup_printf ("%d x %d", width, height); - text_length = strlen (text); - - text_width = text_length * font_struct->max_bounds.width; - text_height = font_struct->max_bounds.descent + - font_struct->max_bounds.ascent; - - box_width = text_width + 2 * LINE_WIDTH; - box_height = text_height + 2 * LINE_WIDTH; - - - box_x = shrunk_rect.x + (shrunk_rect.width - box_width) / 2; - box_y = shrunk_rect.y + (shrunk_rect.height - box_height) / 2; - - if ((box_width < shrunk_rect.width) && - (box_height < shrunk_rect.height)) - { - XFillRectangle (screen->display->xdisplay, - screen->xroot, - screen->root_xor_gc, - box_x, box_y, - box_width, box_height); - XDrawString (screen->display->xdisplay, - screen->xroot, - screen->root_xor_gc, - box_x + LINE_WIDTH, - box_y + LINE_WIDTH + font_struct->max_bounds.ascent, - text, text_length); - } - - g_free (text); - - XFreeFontInfo (NULL, font_struct, 1); - - if ((box_width + LINE_WIDTH) >= (shrunk_rect.width / 3)) - return; - - if ((box_height + LINE_WIDTH) >= (shrunk_rect.height / 3)) - return; - } - } - } - - /* Two vertical lines at 1/3 and 2/3 */ - segments[0].x1 = shrunk_rect.x + shrunk_rect.width / 3; - segments[0].y1 = shrunk_rect.y + LINE_WIDTH / 2 + LINE_WIDTH % 2; - segments[0].x2 = segments[0].x1; - segments[0].y2 = shrunk_rect.y + shrunk_rect.height - LINE_WIDTH / 2; - - segments[1] = segments[0]; - segments[1].x1 = shrunk_rect.x + (shrunk_rect.width / 3) * 2; - segments[1].x2 = segments[1].x1; - - /* Now make two horizontal lines at 1/3 and 2/3, but not - * overlapping the verticals - */ - - segments[2].x1 = shrunk_rect.x + LINE_WIDTH / 2 + LINE_WIDTH % 2; - segments[2].x2 = segments[0].x1 - LINE_WIDTH / 2; - segments[2].y1 = shrunk_rect.y + shrunk_rect.height / 3; - segments[2].y2 = segments[2].y1; - - segments[3] = segments[2]; - segments[3].x1 = segments[2].x2 + LINE_WIDTH; - segments[3].x2 = segments[1].x1 - LINE_WIDTH / 2; - - segments[4] = segments[3]; - segments[4].x1 = segments[3].x2 + LINE_WIDTH; - segments[4].x2 = shrunk_rect.x + shrunk_rect.width - LINE_WIDTH / 2; - - /* Second horizontal line is just like the first, but - * shifted down - */ - i = 5; - while (i < 8) - { - segments[i] = segments[i - 3]; - segments[i].y1 = shrunk_rect.y + (shrunk_rect.height / 3) * 2; - segments[i].y2 = segments[i].y1; - ++i; - } - - XDrawSegments (screen->display->xdisplay, - screen->xroot, - screen->root_xor_gc, - segments, - G_N_ELEMENTS (segments)); -} - -void -meta_effects_update_wireframe (MetaScreen *screen, - const MetaRectangle *old_rect, - int old_width, - int old_height, - const MetaRectangle *new_rect, - int new_width, - int new_height) -{ - if (old_rect) - draw_xor_rect (screen, old_rect, old_width, old_height); - - if (new_rect) - draw_xor_rect (screen, new_rect, new_width, new_height); - - XFlush (screen->display->xdisplay); -} - -void -meta_effects_end_wireframe (MetaScreen *screen, - const MetaRectangle *old_rect, - int old_width, - int old_height) -{ - meta_effects_update_wireframe (screen, - old_rect, old_width, old_height, - NULL, -1, -1); - - meta_display_ungrab (screen->display); - meta_ui_pop_delay_exposes (screen->ui); -} - -static void -run_default_effect_handler (MetaEffect *effect) -{ - switch (effect->type) - { - case META_EFFECT_MINIMIZE: - draw_box_animation (effect->window->screen, - &(effect->u.minimize.window_rect), - &(effect->u.minimize.icon_rect), - META_MINIMIZE_ANIMATION_LENGTH); - break; - - default: - break; - } -} - -static void -run_handler (MetaEffect *effect) -{ - if (meta_prefs_get_gnome_animations ()) - run_default_effect_handler (effect); - - effect_free (effect); -} diff --git a/src/core/effects.h b/src/core/effects.h deleted file mode 100644 index 91d09e15..00000000 --- a/src/core/effects.h +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file effects.h "Special effects" other than compositor effects. - * - * Before we had a serious compositor, we supported swooping - * rectangles for minimising and so on. These are still supported - * today, even when the compositor is enabled. The file contains two - * parts: - * - * 1) A set of functions, each of which implements a special effect. - * (Only the minimize function does anything interesting; we should - * probably get rid of the rest.) - * - * 2) A set of functions for moving a highlighted wireframe box around - * the screen, optionally with height and width shown in the middle. - * This is used for moving and resizing when reduced_resources is set. - * - * There was formerly a system which allowed callers to drop in their - * own handlers for various things; it was never used (people who want - * their own handlers can just modify this file, after all) and it added - * a good deal of extra complexity, so it has been removed. If you want it, - * it can be found in svn r3769. - */ - -/* - * Copyright (C) 2001 Anders Carlsson, Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_EFFECTS_H -#define META_EFFECTS_H - -#include "util.h" -#include "screen-private.h" - -typedef enum -{ - META_EFFECT_MINIMIZE, - META_EFFECT_UNMINIMIZE, - META_EFFECT_FOCUS, - META_EFFECT_CLOSE, - META_NUM_EFFECTS -} MetaEffectType; - -/** - * A callback which will be called when the effect has finished. - */ -typedef void (* MetaEffectFinished) (gpointer data); - -/** - * Performs the minimize effect. - * - * \param window The window we're moving - * \param window_rect Its current state - * \param target Where it should end up - * \param finished Callback for when it's finished - * \param data Data for callback - */ -void meta_effect_run_minimize (MetaWindow *window, - MetaRectangle *window_rect, - MetaRectangle *target, - MetaEffectFinished finished, - gpointer data); - -/** - * Performs the unminimize effect. There is no such effect. - * FIXME: delete this. - * - * \param window The window we're moving - * \param icon_rect Its current state - * \param window_rect Where it should end up - * \param finished Callback for when it's finished - * \param data Data for callback - */ -void meta_effect_run_unminimize (MetaWindow *window, - MetaRectangle *window_rect, - MetaRectangle *icon_rect, - MetaEffectFinished finished, - gpointer data); - -/** - * Performs the close effect. There is no such effect. - * FIXME: delete this. - * - * \param window The window we're moving - * \param finished Callback for when it's finished - * \param data Data for callback - */ -void meta_effect_run_close (MetaWindow *window, - MetaEffectFinished finished, - gpointer data); - -/** - * Performs the focus effect. There is no such effect. - * FIXME: delete this. - * - * \param window The window we're moving - * \param finished Callback for when it's finished - * \param data Data for callback - */ -void meta_effect_run_focus (MetaWindow *window, - MetaEffectFinished finished, - gpointer data); - -/** - * Grabs the server and paints a wireframe rectangle on the screen. - * Since this involves starting a grab, please be considerate of other - * users and don't keep the grab for long. You may move the wireframe - * around using meta_effects_update_wireframe() and remove it, and undo - * the grab, using meta_effects_end_wireframe(). - * - * \param screen The screen to draw the rectangle on. - * \param rect The size of the rectangle to draw. - * \param width The width to display in the middle (or 0 not to) - * \param height The width to display in the middle (or 0 not to) - */ -void meta_effects_begin_wireframe (MetaScreen *screen, - const MetaRectangle *rect, - int width, - int height); - -/** - * Moves a wireframe rectangle around after its creation by - * meta_effects_begin_wireframe(). (Perhaps we ought to remember the old - * positions and not require people to pass them in?) - * - * \param old_rect Where the rectangle is now - * \param old_width The width that was displayed on it (or 0 if there wasn't) - * \param old_height The height that was displayed on it (or 0 if there wasn't) - * \param new_rect Where the rectangle is going - * \param new_width The width that will be displayed on it (or 0 not to) - * \param new_height The height that will be displayed on it (or 0 not to) - */ -void meta_effects_update_wireframe (MetaScreen *screen, - const MetaRectangle *old_rect, - int old_width, - int old_height, - const MetaRectangle *new_rect, - int new_width, - int new_height); - -/** - * Removes a wireframe rectangle from the screen and ends the grab started by - * meta_effects_begin_wireframe(). - * - * \param old_rect Where the rectangle is now - * \param old_width The width that was displayed on it (or 0 if there wasn't) - * \param old_height The height that was displayed on it (or 0 if there wasn't) - */ -void meta_effects_end_wireframe (MetaScreen *screen, - const MetaRectangle *old_rect, - int width, - int height); - -#endif /* META_EFFECTS_H */ diff --git a/src/core/errors.c b/src/core/errors.c deleted file mode 100644 index 8de46080..00000000 --- a/src/core/errors.c +++ /dev/null @@ -1,288 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X error handling */ - -/* - * Copyright (C) 2001 Havoc Pennington, error trapping inspired by GDK - * code copyrighted by the GTK team. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "errors.h" -#include "display-private.h" -#include <errno.h> -#include <stdlib.h> -#include <gdk/gdk.h> - -static int x_error_handler (Display *display, - XErrorEvent *error); -static int x_io_error_handler (Display *display); - -void -meta_errors_init (void) -{ - XSetErrorHandler (x_error_handler); - XSetIOErrorHandler (x_io_error_handler); -} - -typedef struct ForeignDisplay ForeignDisplay; - -struct ForeignDisplay -{ - Display *dpy; - ErrorHandler handler; - gpointer data; - ForeignDisplay *next; -}; - -static ForeignDisplay *foreign_displays; - -void -meta_errors_register_foreign_display (Display *foreign_dpy, - ErrorHandler handler, - gpointer data) -{ - ForeignDisplay *info = g_new0 (ForeignDisplay, 1); - info->dpy = foreign_dpy; - info->handler = handler; - info->data = data; - info->next = foreign_displays; - foreign_displays = info; -} - -static void -meta_error_trap_push_internal (MetaDisplay *display, - gboolean need_sync) -{ - /* GDK resets the error handler on each push */ - int (* old_error_handler) (Display *, - XErrorEvent *); - - if (need_sync) - { - XSync (display->xdisplay, False); - } - - gdk_error_trap_push (); - - /* old_error_handler will just be equal to x_error_handler - * for nested traps - */ - old_error_handler = XSetErrorHandler (x_error_handler); - - /* Replace GDK handler, but save it so we can chain up */ - if (display->error_trap_handler == NULL) - { - g_assert (display->error_traps == 0); - display->error_trap_handler = old_error_handler; - g_assert (display->error_trap_handler != x_error_handler); - } - - display->error_traps += 1; - - meta_topic (META_DEBUG_ERRORS, "%d traps remain\n", display->error_traps); -} - -static int -meta_error_trap_pop_internal (MetaDisplay *display, - gboolean need_sync) -{ - int result; - - g_assert (display->error_traps > 0); - - if (need_sync) - { - XSync (display->xdisplay, False); - } - - result = gdk_error_trap_pop (); - - display->error_traps -= 1; - - if (display->error_traps == 0) - { - /* check that GDK put our handler back; this - * assumes that there are no pending GDK traps from GDK itself - */ - - int (* restored_error_handler) (Display *, - XErrorEvent *); - - restored_error_handler = XSetErrorHandler (x_error_handler); - - /* remove this */ - display->error_trap_handler = NULL; - } - - meta_topic (META_DEBUG_ERRORS, "%d traps\n", display->error_traps); - - return result; -} - -void -meta_error_trap_push (MetaDisplay *display) -{ - meta_error_trap_push_internal (display, FALSE); -} - -void -meta_error_trap_pop (MetaDisplay *display, - gboolean last_request_was_roundtrip) -{ - gboolean need_sync; - - /* we only have to sync when popping the outermost trap */ - need_sync = (display->error_traps == 1 && !last_request_was_roundtrip); - - if (need_sync) - meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop, traps = %d, roundtrip = %d\n", - display->error_traps, last_request_was_roundtrip); - - display->error_trap_synced_at_last_pop = need_sync || last_request_was_roundtrip; - - meta_error_trap_pop_internal (display, need_sync); -} - -void -meta_error_trap_push_with_return (MetaDisplay *display) -{ - gboolean need_sync; - - /* We don't sync on push_with_return if there are no traps - * currently, because we assume that any errors were either covered - * by a previous pop, or were fatal. - * - * More generally, we don't sync if we were synchronized last time - * we popped. This is known to be the case if there are no traps, - * but we also keep a flag so we know whether it's the case otherwise. - */ - - if (!display->error_trap_synced_at_last_pop) - need_sync = TRUE; - else - need_sync = FALSE; - - if (need_sync) - meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_push_with_return, traps = %d\n", - display->error_traps); - - meta_error_trap_push_internal (display, FALSE); -} - -int -meta_error_trap_pop_with_return (MetaDisplay *display, - gboolean last_request_was_roundtrip) -{ - if (!last_request_was_roundtrip) - meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop_with_return, traps = %d, roundtrip = %d\n", - display->error_traps, last_request_was_roundtrip); - - display->error_trap_synced_at_last_pop = TRUE; - - return meta_error_trap_pop_internal (display, - !last_request_was_roundtrip); -} - -static int -x_error_handler (Display *xdisplay, - XErrorEvent *error) -{ - int retval; - gchar buf[64]; - MetaDisplay *display; - ForeignDisplay *foreign; - - for (foreign = foreign_displays; foreign != NULL; foreign = foreign->next) - { - if (foreign->dpy == xdisplay) - { - foreign->handler (xdisplay, error, foreign->data); - - return 0; - } - } - - XGetErrorText (xdisplay, error->error_code, buf, 63); - - display = meta_display_for_x_display (xdisplay); - - /* Display can be NULL here because the compositing manager - * has its own Display, but Xlib only has one global error handler - */ - if (display->error_traps > 0) - { - /* we're in an error trap, chain to the trap handler - * saved from GDK - */ - meta_verbose ("X error: %s serial %ld error_code %d request_code %d minor_code %d)\n", - buf, - error->serial, - error->error_code, - error->request_code, - error->minor_code); - - g_assert (display->error_trap_handler != NULL); - g_assert (display->error_trap_handler != x_error_handler); - - retval = (* display->error_trap_handler) (xdisplay, error); - } - else - { - meta_bug ("Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n", - buf, - error->serial, - error->error_code, - error->request_code, - error->minor_code); - - retval = 1; /* compiler warning */ - } - - return retval; -} - -static int -x_io_error_handler (Display *xdisplay) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - - if (display == NULL) - meta_bug ("IO error received for unknown display?\n"); - - if (errno == EPIPE) - { - meta_warning (_("Lost connection to the display '%s';\n" - "most likely the X server was shut down or you killed/destroyed\n" - "the window manager.\n"), - display->name); - } - else - { - meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"), - errno, g_strerror (errno), - display->name); - } - - /* Xlib would force an exit anyhow */ - exit (1); - - return 0; -} diff --git a/src/core/eventqueue.c b/src/core/eventqueue.c deleted file mode 100644 index 4ce3e46a..00000000 --- a/src/core/eventqueue.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X event source for main loop */ - -/* - * Copyright (C) 2001 Havoc Pennington (based on GDK code (C) Owen - * Taylor, Red Hat Inc.) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. */ - -#include "eventqueue.h" -#include <X11/Xlib.h> - -static gboolean eq_prepare (GSource *source, - gint *timeout); -static gboolean eq_check (GSource *source); -static gboolean eq_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data); -static void eq_destroy (GSource *source); - -static GSourceFuncs eq_funcs = { - eq_prepare, - eq_check, - eq_dispatch, - eq_destroy -}; - -struct _MetaEventQueue -{ - GSource source; - - Display *display; - GPollFD poll_fd; - int connection_fd; - GQueue *events; -}; - -MetaEventQueue* -meta_event_queue_new (Display *display, MetaEventQueueFunc func, gpointer data) -{ - GSource *source; - MetaEventQueue *eq; - - source = g_source_new (&eq_funcs, sizeof (MetaEventQueue)); - eq = (MetaEventQueue*) source; - - eq->connection_fd = ConnectionNumber (display); - eq->poll_fd.fd = eq->connection_fd; - eq->poll_fd.events = G_IO_IN; - - eq->events = g_queue_new (); - - eq->display = display; - - g_source_set_priority (source, G_PRIORITY_DEFAULT); - g_source_add_poll (source, &eq->poll_fd); - g_source_set_can_recurse (source, TRUE); - - g_source_set_callback (source, (GSourceFunc) func, data, NULL); - - g_source_attach (source, NULL); - g_source_unref (source); - - return eq; -} - -void -meta_event_queue_free (MetaEventQueue *eq) -{ - GSource *source; - - source = (GSource*) eq; - - g_source_destroy (source); -} - -static gboolean -eq_events_pending (MetaEventQueue *eq) -{ - return eq->events->length > 0 || XPending (eq->display); -} - -static void -eq_queue_events (MetaEventQueue *eq) -{ - XEvent xevent; - - while (XPending (eq->display)) - { - XEvent *copy; - - XNextEvent (eq->display, &xevent); - - copy = g_new (XEvent, 1); - *copy = xevent; - - g_queue_push_tail (eq->events, copy); - } -} - -static gboolean -eq_prepare (GSource *source, gint *timeout) -{ - MetaEventQueue *eq; - - eq = (MetaEventQueue*) source; - - *timeout = -1; - - return eq_events_pending (eq); -} - -static gboolean -eq_check (GSource *source) -{ - MetaEventQueue *eq; - - eq = (MetaEventQueue*) source; - - if (eq->poll_fd.revents & G_IO_IN) - return eq_events_pending (eq); - else - return FALSE; -} - -static gboolean -eq_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) -{ - MetaEventQueue *eq; - - eq = (MetaEventQueue*) source; - - eq_queue_events (eq); - - if (eq->events->length > 0) - { - XEvent *event; - MetaEventQueueFunc func; - - event = g_queue_pop_head (eq->events); - func = (MetaEventQueueFunc) callback; - - (* func) (event, user_data); - - g_free (event); - } - - return TRUE; -} - -static void -eq_destroy (GSource *source) -{ - MetaEventQueue *eq; - - eq = (MetaEventQueue*) source; - - while (eq->events->length > 0) - { - XEvent *event; - - event = g_queue_pop_head (eq->events); - - g_free (event); - } - - g_queue_free (eq->events); - - /* source itself is freed by glib */ -} diff --git a/src/core/eventqueue.h b/src/core/eventqueue.h deleted file mode 100644 index cd115bdb..00000000 --- a/src/core/eventqueue.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X event source for main loop */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_EVENT_QUEUE_H -#define META_EVENT_QUEUE_H - -#include <glib.h> -#include <X11/Xlib.h> - -typedef struct _MetaEventQueue MetaEventQueue; - -typedef void (* MetaEventQueueFunc) (XEvent *event, - gpointer data); - -MetaEventQueue* meta_event_queue_new (Display *display, - MetaEventQueueFunc func, - gpointer data); -void meta_event_queue_free (MetaEventQueue *eq); - -#endif diff --git a/src/core/frame-private.h b/src/core/frame-private.h deleted file mode 100644 index cba9b52a..00000000 --- a/src/core/frame-private.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X window decorations */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_FRAME_PRIVATE_H -#define META_FRAME_PRIVATE_H - -#include "frame.h" -#include "window-private.h" - -typedef struct _MetaFrameGeometry MetaFrameGeometry; - -struct _MetaFrameGeometry -{ - /* border sizes (space between frame and child) */ - int left_width; - int right_width; - int top_height; - int bottom_height; -}; - -struct _MetaFrame -{ - /* window we frame */ - MetaWindow *window; - - /* reparent window */ - Window xwindow; - - MetaCursor current_cursor; - - /* This rect is trusted info from where we put the - * frame, not the result of ConfigureNotify - */ - MetaRectangle rect; - - /* position of client, size of frame */ - int child_x; - int child_y; - int right_width; - int bottom_height; - - guint mapped : 1; - guint need_reapply_frame_shape : 1; - guint is_flashing : 1; /* used by the visual bell flash */ -}; - -void meta_window_ensure_frame (MetaWindow *window); -void meta_window_destroy_frame (MetaWindow *window); -void meta_frame_queue_draw (MetaFrame *frame); - -MetaFrameFlags meta_frame_get_flags (MetaFrame *frame); - -/* These should ONLY be called from meta_window_move_resize_internal */ -void meta_frame_calc_geometry (MetaFrame *frame, - MetaFrameGeometry *geomp); -void meta_frame_sync_to_window (MetaFrame *frame, - int gravity, - gboolean need_move, - gboolean need_resize); - -void meta_frame_set_screen_cursor (MetaFrame *frame, - MetaCursor cursor); - -#endif - - - - diff --git a/src/core/frame.c b/src/core/frame.c deleted file mode 100644 index d2bf62fc..00000000 --- a/src/core/frame.c +++ /dev/null @@ -1,420 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X window decorations */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003, 2004 Red Hat, Inc. - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "frame-private.h" -#include "bell.h" -#include "errors.h" -#include "keybindings.h" - -#ifdef HAVE_RENDER -#include <X11/extensions/Xrender.h> -#endif - -#define EVENT_MASK (SubstructureRedirectMask | \ - StructureNotifyMask | SubstructureNotifyMask | \ - ExposureMask | \ - ButtonPressMask | ButtonReleaseMask | \ - PointerMotionMask | PointerMotionHintMask | \ - EnterWindowMask | LeaveWindowMask | \ - FocusChangeMask | \ - ColormapChangeMask) - -void -meta_window_ensure_frame (MetaWindow *window) -{ - MetaFrame *frame; - XSetWindowAttributes attrs; - Visual *visual; - - if (window->frame) - return; - - /* See comment below for why this is required. */ - meta_display_grab (window->display); - - frame = g_new (MetaFrame, 1); - - frame->window = window; - frame->xwindow = None; - - frame->rect = window->rect; - frame->child_x = 0; - frame->child_y = 0; - frame->bottom_height = 0; - frame->right_width = 0; - frame->current_cursor = 0; - - frame->mapped = FALSE; - frame->need_reapply_frame_shape = TRUE; - frame->is_flashing = FALSE; - - meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n", - window->desc, - XVisualIDFromVisual (window->xvisual) == - XVisualIDFromVisual (window->screen->default_xvisual) ? - "is" : "is not", - window->depth, window->screen->default_depth); - meta_verbose ("Frame geometry %d,%d %dx%d\n", - frame->rect.x, frame->rect.y, - frame->rect.width, frame->rect.height); - - /* Default depth/visual handles clients with weird visuals; they can - * always be children of the root depth/visual obviously, but - * e.g. DRI games can't be children of a parent that has the same - * visual as the client. NULL means default visual. - * - * We look for an ARGB visual if we can find one, otherwise use - * the default of NULL. - */ - - /* Special case for depth 32 windows (assumed to be ARGB), - * we use the window's visual. Otherwise we just use the system visual. - */ - if (window->depth == 32) - visual = window->xvisual; - else - visual = NULL; - - frame->xwindow = meta_ui_create_frame_window (window->screen->ui, - window->display->xdisplay, - visual, - frame->rect.x, - frame->rect.y, - frame->rect.width, - frame->rect.height, - frame->window->screen->number); - - meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow); - attrs.event_mask = EVENT_MASK; - XChangeWindowAttributes (window->display->xdisplay, - frame->xwindow, CWEventMask, &attrs); - - meta_display_register_x_window (window->display, &frame->xwindow, window); - - /* Now that frame->xwindow is registered with window, we can set its - * background. - */ - meta_ui_reset_frame_bg (window->screen->ui, frame->xwindow); - - /* Reparent the client window; it may be destroyed, - * thus the error trap. We'll get a destroy notify later - * and free everything. Comment in FVWM source code says - * we need a server grab or the child can get its MapNotify - * before we've finished reparenting and getting the decoration - * window onscreen, so ensure_frame must be called with - * a grab. - */ - meta_error_trap_push (window->display); - if (window->mapped) - { - window->mapped = FALSE; /* the reparent will unmap the window, - * we don't want to take that as a withdraw - */ - meta_topic (META_DEBUG_WINDOW_STATE, - "Incrementing unmaps_pending on %s for reparent\n", window->desc); - window->unmaps_pending += 1; - } - /* window was reparented to this position */ - window->rect.x = 0; - window->rect.y = 0; - - XReparentWindow (window->display->xdisplay, - window->xwindow, - frame->xwindow, - window->rect.x, - window->rect.y); - /* FIXME handle this error */ - meta_error_trap_pop (window->display, FALSE); - - /* stick frame to the window */ - window->frame = frame; - - if (window->title) - meta_ui_set_frame_title (window->screen->ui, - window->frame->xwindow, - window->title); - - /* Move keybindings to frame instead of window */ - meta_window_grab_keys (window); - - /* Shape mask */ - meta_ui_apply_frame_shape (frame->window->screen->ui, - frame->xwindow, - frame->rect.width, - frame->rect.height, - frame->window->has_shape); - frame->need_reapply_frame_shape = FALSE; - - meta_display_ungrab (window->display); -} - -void -meta_window_destroy_frame (MetaWindow *window) -{ - MetaFrame *frame; - - if (window->frame == NULL) - return; - - meta_verbose ("Unframing window %s\n", window->desc); - - frame = window->frame; - - meta_bell_notify_frame_destroy (frame); - - /* Unparent the client window; it may be destroyed, - * thus the error trap. - */ - meta_error_trap_push (window->display); - if (window->mapped) - { - window->mapped = FALSE; /* Keep track of unmapping it, so we - * can identify a withdraw initiated - * by the client. - */ - meta_topic (META_DEBUG_WINDOW_STATE, - "Incrementing unmaps_pending on %s for reparent back to root\n", window->desc); - window->unmaps_pending += 1; - } - XReparentWindow (window->display->xdisplay, - window->xwindow, - window->screen->xroot, - /* Using anything other than meta_window_get_position() - * coordinates here means we'll need to ensure a configure - * notify event is sent; see bug 399552. - */ - window->frame->rect.x, - window->frame->rect.y); - meta_error_trap_pop (window->display, FALSE); - - meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow); - - meta_display_unregister_x_window (window->display, - frame->xwindow); - - window->frame = NULL; - - /* Move keybindings to window instead of frame */ - meta_window_grab_keys (window); - - g_free (frame); - - /* Put our state back where it should be */ - meta_window_queue (window, META_QUEUE_CALC_SHOWING); -} - - -MetaFrameFlags -meta_frame_get_flags (MetaFrame *frame) -{ - MetaFrameFlags flags; - - flags = 0; - - if (frame->window->border_only) - { - ; /* FIXME this may disable the _function_ as well as decor - * in some cases, which is sort of wrong. - */ - } - else - { - flags |= META_FRAME_ALLOWS_MENU; - - if (frame->window->has_close_func) - flags |= META_FRAME_ALLOWS_DELETE; - - if (frame->window->has_maximize_func) - flags |= META_FRAME_ALLOWS_MAXIMIZE; - - if (frame->window->has_minimize_func) - flags |= META_FRAME_ALLOWS_MINIMIZE; - - if (frame->window->has_shade_func) - flags |= META_FRAME_ALLOWS_SHADE; - } - - if (META_WINDOW_ALLOWS_MOVE (frame->window)) - flags |= META_FRAME_ALLOWS_MOVE; - - if (META_WINDOW_ALLOWS_HORIZONTAL_RESIZE (frame->window)) - flags |= META_FRAME_ALLOWS_HORIZONTAL_RESIZE; - - if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window)) - flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE; - - if (frame->window->has_focus) - flags |= META_FRAME_HAS_FOCUS; - - if (frame->window->shaded) - flags |= META_FRAME_SHADED; - - if (frame->window->on_all_workspaces) - flags |= META_FRAME_STUCK; - - /* FIXME: Should we have some kind of UI for windows that are just vertically - * maximized or just horizontally maximized? - */ - if (META_WINDOW_MAXIMIZED (frame->window)) - flags |= META_FRAME_MAXIMIZED; - - if (frame->window->fullscreen) - flags |= META_FRAME_FULLSCREEN; - - if (frame->is_flashing) - flags |= META_FRAME_IS_FLASHING; - - if (frame->window->wm_state_above) - flags |= META_FRAME_ABOVE; - - return flags; -} - -void -meta_frame_calc_geometry (MetaFrame *frame, - MetaFrameGeometry *geomp) -{ - MetaFrameGeometry geom; - MetaWindow *window; - - window = frame->window; - - meta_ui_get_frame_geometry (window->screen->ui, - frame->xwindow, - &geom.top_height, - &geom.bottom_height, - &geom.left_width, - &geom.right_width); - - *geomp = geom; -} - -static void -update_shape (MetaFrame *frame) -{ - if (frame->need_reapply_frame_shape) - { - meta_ui_apply_frame_shape (frame->window->screen->ui, - frame->xwindow, - frame->rect.width, - frame->rect.height, - frame->window->has_shape); - frame->need_reapply_frame_shape = FALSE; - } -} - -void -meta_frame_sync_to_window (MetaFrame *frame, - int resize_gravity, - gboolean need_move, - gboolean need_resize) -{ - if (!(need_move || need_resize)) - { - update_shape (frame); - return; - } - - meta_topic (META_DEBUG_GEOMETRY, - "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)\n", - frame->rect.x, frame->rect.y, - frame->rect.width, frame->rect.height, - frame->rect.x + frame->rect.width, - frame->rect.y + frame->rect.height); - - /* set bg to none to avoid flicker */ - if (need_resize) - { - meta_ui_unflicker_frame_bg (frame->window->screen->ui, - frame->xwindow, - frame->rect.width, - frame->rect.height); - - /* we need new shape if we're resized */ - frame->need_reapply_frame_shape = TRUE; - } - - /* Done before the window resize, because doing it before means - * part of the window being resized becomes unshaped, which may - * be sort of hard to see with bg = None. If we did it after - * window resize, part of the window being resized would become - * shaped, which might be more visible. - */ - update_shape (frame); - - meta_ui_move_resize_frame (frame->window->screen->ui, - frame->xwindow, - frame->rect.x, - frame->rect.y, - frame->rect.width, - frame->rect.height); - - if (need_resize) - { - meta_ui_reset_frame_bg (frame->window->screen->ui, - frame->xwindow); - - /* If we're interactively resizing the frame, repaint - * it immediately so we don't start to lag. - */ - if (frame->window->display->grab_window == - frame->window) - meta_ui_repaint_frame (frame->window->screen->ui, - frame->xwindow); - } -} - -void -meta_frame_queue_draw (MetaFrame *frame) -{ - meta_ui_queue_frame_draw (frame->window->screen->ui, - frame->xwindow); -} - -void -meta_frame_set_screen_cursor (MetaFrame *frame, - MetaCursor cursor) -{ - Cursor xcursor; - if (cursor == frame->current_cursor) - return; - frame->current_cursor = cursor; - if (cursor == META_CURSOR_DEFAULT) - XUndefineCursor (frame->window->display->xdisplay, frame->xwindow); - else - { - xcursor = meta_display_create_x_cursor (frame->window->display, cursor); - XDefineCursor (frame->window->display->xdisplay, frame->xwindow, xcursor); - XFlush (frame->window->display->xdisplay); - XFreeCursor (frame->window->display->xdisplay, xcursor); - } -} - -Window -meta_frame_get_xwindow (MetaFrame *frame) -{ - return frame->xwindow; -} diff --git a/src/core/group-private.h b/src/core/group-private.h deleted file mode 100644 index 25b05c77..00000000 --- a/src/core/group-private.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window group private header */ - -/* - * Copyright (C) 2002 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_GROUP_PRIVATE_H -#define META_GROUP_PRIVATE_H - -#include "group.h" - -struct _MetaGroup -{ - int refcount; - MetaDisplay *display; - GSList *windows; - Window group_leader; - char *startup_id; - char *wm_client_machine; -}; - -#endif - - - - diff --git a/src/core/group-props.c b/src/core/group-props.c deleted file mode 100644 index 05e82900..00000000 --- a/src/core/group-props.c +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* MetaGroup property handling */ - -/* - * Copyright (C) 2002 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "group-props.h" -#include "group-private.h" -#include "xprops.h" -#include <X11/Xatom.h> - -typedef void (* InitValueFunc) (MetaDisplay *display, - Atom property, - MetaPropValue *value); -typedef void (* ReloadValueFunc) (MetaGroup *group, - MetaPropValue *value); - -struct _MetaGroupPropHooks -{ - Atom property; - InitValueFunc init_func; - ReloadValueFunc reload_func; -}; - -static void init_prop_value (MetaDisplay *display, - Atom property, - MetaPropValue *value); -static void reload_prop_value (MetaGroup *group, - MetaPropValue *value); -static MetaGroupPropHooks* find_hooks (MetaDisplay *display, - Atom property); - - - -void -meta_group_reload_property (MetaGroup *group, - Atom property) -{ - meta_group_reload_properties (group, &property, 1); -} - -void -meta_group_reload_properties (MetaGroup *group, - const Atom *properties, - int n_properties) -{ - int i; - MetaPropValue *values; - - g_return_if_fail (properties != NULL); - g_return_if_fail (n_properties > 0); - - values = g_new0 (MetaPropValue, n_properties); - - i = 0; - while (i < n_properties) - { - init_prop_value (group->display, properties[i], &values[i]); - ++i; - } - - meta_prop_get_values (group->display, group->group_leader, - values, n_properties); - - i = 0; - while (i < n_properties) - { - reload_prop_value (group, &values[i]); - - ++i; - } - - meta_prop_free_values (values, n_properties); - - g_free (values); -} - -/* Fill in the MetaPropValue used to get the value of "property" */ -static void -init_prop_value (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - MetaGroupPropHooks *hooks; - - value->type = META_PROP_VALUE_INVALID; - value->atom = None; - - hooks = find_hooks (display, property); - if (hooks && hooks->init_func != NULL) - (* hooks->init_func) (display, property, value); -} - -static void -reload_prop_value (MetaGroup *group, - MetaPropValue *value) -{ - MetaGroupPropHooks *hooks; - - hooks = find_hooks (group->display, value->atom); - if (hooks && hooks->reload_func != NULL) - (* hooks->reload_func) (group, value); -} - -static void -init_wm_client_machine (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_STRING; - value->atom = display->atom_WM_CLIENT_MACHINE; -} - -static void -reload_wm_client_machine (MetaGroup *group, - MetaPropValue *value) -{ - g_free (group->wm_client_machine); - group->wm_client_machine = NULL; - - if (value->type != META_PROP_VALUE_INVALID) - group->wm_client_machine = g_strdup (value->v.str); - - meta_verbose ("Group has client machine \"%s\"\n", - group->wm_client_machine ? group->wm_client_machine : "unset"); -} - -static void -init_net_startup_id (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_UTF8; - value->atom = display->atom__NET_STARTUP_ID; -} - -static void -reload_net_startup_id (MetaGroup *group, - MetaPropValue *value) -{ - g_free (group->startup_id); - group->startup_id = NULL; - - if (value->type != META_PROP_VALUE_INVALID) - group->startup_id = g_strdup (value->v.str); - - meta_verbose ("Group has startup id \"%s\"\n", - group->startup_id ? group->startup_id : "unset"); -} - -#define N_HOOKS 3 - -void -meta_display_init_group_prop_hooks (MetaDisplay *display) -{ - int i; - MetaGroupPropHooks *hooks; - - g_assert (display->group_prop_hooks == NULL); - - display->group_prop_hooks = g_new0 (MetaGroupPropHooks, N_HOOKS); - hooks = display->group_prop_hooks; - - i = 0; - - hooks[i].property = display->atom_WM_CLIENT_MACHINE; - hooks[i].init_func = init_wm_client_machine; - hooks[i].reload_func = reload_wm_client_machine; - ++i; - - hooks[i].property = display->atom__NET_WM_PID; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = display->atom__NET_STARTUP_ID; - hooks[i].init_func = init_net_startup_id; - hooks[i].reload_func = reload_net_startup_id; - ++i; - - if (i != N_HOOKS) - { - g_error ("Initialized %d group hooks should have been %d\n", i, N_HOOKS); - } -} - -void -meta_display_free_group_prop_hooks (MetaDisplay *display) -{ - g_assert (display->group_prop_hooks != NULL); - - g_free (display->group_prop_hooks); - display->group_prop_hooks = NULL; -} - -static MetaGroupPropHooks* -find_hooks (MetaDisplay *display, - Atom property) -{ - int i; - - /* FIXME we could sort the array and do binary search or - * something - */ - - i = 0; - while (i < N_HOOKS) - { - if (display->group_prop_hooks[i].property == property) - return &display->group_prop_hooks[i]; - - ++i; - } - - return NULL; -} diff --git a/src/core/group-props.h b/src/core/group-props.h deleted file mode 100644 index ffde0901..00000000 --- a/src/core/group-props.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* MetaGroup property handling */ - -/* - * Copyright (C) 2002 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_GROUP_PROPS_H -#define META_GROUP_PROPS_H - -#include "group.h" - -void meta_group_reload_property (MetaGroup *group, - Atom property); -void meta_group_reload_properties (MetaGroup *group, - const Atom *properties, - int n_properties); -void meta_display_init_group_prop_hooks (MetaDisplay *display); -void meta_display_free_group_prop_hooks (MetaDisplay *display); - -#endif /* META_GROUP_PROPS_H */ diff --git a/src/core/group.c b/src/core/group.c deleted file mode 100644 index 69c879ee..00000000 --- a/src/core/group.c +++ /dev/null @@ -1,274 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window groups */ - -/* - * Copyright (C) 2002 Red Hat Inc. - * Copyright (C) 2003 Rob Adams - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "util.h" -#include "group-private.h" -#include "group-props.h" -#include "window.h" - -static MetaGroup* -meta_group_new (MetaDisplay *display, - Window group_leader) -{ - MetaGroup *group; -#define N_INITIAL_PROPS 3 - Atom initial_props[N_INITIAL_PROPS]; - int i; - - g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props)); - - group = g_new0 (MetaGroup, 1); - - group->display = display; - group->windows = NULL; - group->group_leader = group_leader; - group->refcount = 1; /* owned by caller, hash table has only weak ref */ - - if (display->groups_by_leader == NULL) - display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash, - meta_unsigned_long_equal); - - g_assert (g_hash_table_lookup (display->groups_by_leader, &group_leader) == NULL); - - g_hash_table_insert (display->groups_by_leader, - &group->group_leader, - group); - - /* Fill these in the order we want them to be gotten */ - i = 0; - initial_props[i++] = display->atom_WM_CLIENT_MACHINE; - initial_props[i++] = display->atom__NET_WM_PID; - initial_props[i++] = display->atom__NET_STARTUP_ID; - g_assert (N_INITIAL_PROPS == i); - - meta_group_reload_properties (group, initial_props, N_INITIAL_PROPS); - - meta_topic (META_DEBUG_GROUPS, - "Created new group with leader 0x%lx\n", - group->group_leader); - - return group; -} - -static void -meta_group_unref (MetaGroup *group) -{ - g_return_if_fail (group->refcount > 0); - - group->refcount -= 1; - if (group->refcount == 0) - { - meta_topic (META_DEBUG_GROUPS, - "Destroying group with leader 0x%lx\n", - group->group_leader); - - g_assert (group->display->groups_by_leader != NULL); - - g_hash_table_remove (group->display->groups_by_leader, - &group->group_leader); - - /* mop up hash table, this is how it gets freed on display close */ - if (g_hash_table_size (group->display->groups_by_leader) == 0) - { - g_hash_table_destroy (group->display->groups_by_leader); - group->display->groups_by_leader = NULL; - } - - g_free (group->wm_client_machine); - g_free (group->startup_id); - - g_free (group); - } -} - -MetaGroup* -meta_window_get_group (MetaWindow *window) -{ - if (window->unmanaging) - return NULL; - - return window->group; -} - -void -meta_window_compute_group (MetaWindow* window) -{ - MetaGroup *group; - MetaWindow *ancestor; - - /* use window->xwindow if no window->xgroup_leader */ - - group = NULL; - - /* Determine the ancestor of the window; its group setting will override the - * normal grouping rules; see bug 328211. - */ - ancestor = meta_window_find_root_ancestor (window); - - if (window->display->groups_by_leader) - { - if (ancestor != window) - group = ancestor->group; - else if (window->xgroup_leader != None) - group = g_hash_table_lookup (window->display->groups_by_leader, - &window->xgroup_leader); - else - group = g_hash_table_lookup (window->display->groups_by_leader, - &window->xwindow); - } - - if (group != NULL) - { - window->group = group; - group->refcount += 1; - } - else - { - if (ancestor != window && ancestor->xgroup_leader != None) - group = meta_group_new (window->display, - ancestor->xgroup_leader); - else if (window->xgroup_leader != None) - group = meta_group_new (window->display, - window->xgroup_leader); - else - group = meta_group_new (window->display, - window->xwindow); - - window->group = group; - } - - window->group->windows = g_slist_prepend (window->group->windows, window); - - meta_topic (META_DEBUG_GROUPS, - "Adding %s to group with leader 0x%lx\n", - window->desc, group->group_leader); - -} - -static void -remove_window_from_group (MetaWindow *window) -{ - if (window->group != NULL) - { - meta_topic (META_DEBUG_GROUPS, - "Removing %s from group with leader 0x%lx\n", - window->desc, window->group->group_leader); - - window->group->windows = - g_slist_remove (window->group->windows, - window); - meta_group_unref (window->group); - window->group = NULL; - } -} - -void -meta_window_group_leader_changed (MetaWindow *window) -{ - remove_window_from_group (window); - meta_window_compute_group (window); -} - -void -meta_window_shutdown_group (MetaWindow *window) -{ - remove_window_from_group (window); -} - -MetaGroup* -meta_display_lookup_group (MetaDisplay *display, - Window group_leader) -{ - MetaGroup *group; - - group = NULL; - - if (display->groups_by_leader) - group = g_hash_table_lookup (display->groups_by_leader, - &group_leader); - - return group; -} - -GSList* -meta_group_list_windows (MetaGroup *group) -{ - return g_slist_copy (group->windows); -} - -void -meta_group_update_layers (MetaGroup *group) -{ - GSList *tmp; - GSList *frozen_stacks; - - if (group->windows == NULL) - return; - - frozen_stacks = NULL; - tmp = group->windows; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - /* we end up freezing the same stack a lot of times, - * but doesn't hurt anything. have to handle - * groups that span 2 screens. - */ - meta_stack_freeze (window->screen->stack); - frozen_stacks = g_slist_prepend (frozen_stacks, window->screen->stack); - - meta_stack_update_layer (window->screen->stack, - window); - - tmp = tmp->next; - } - - tmp = frozen_stacks; - while (tmp != NULL) - { - meta_stack_thaw (tmp->data); - tmp = tmp->next; - } - - g_slist_free (frozen_stacks); -} - -const char* -meta_group_get_startup_id (MetaGroup *group) -{ - return group->startup_id; -} - -gboolean -meta_group_property_notify (MetaGroup *group, - XEvent *event) -{ - meta_group_reload_property (group, - event->xproperty.atom); - - return TRUE; - -} diff --git a/src/core/group.h b/src/core/group.h deleted file mode 100644 index 562ac59b..00000000 --- a/src/core/group.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window groups */ - -/* - * Copyright (C) 2002 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_GROUP_H -#define META_GROUP_H - -#include "window-private.h" - -/* note, can return NULL */ -MetaGroup* meta_window_get_group (MetaWindow *window); -void meta_window_compute_group (MetaWindow* window); -void meta_window_shutdown_group (MetaWindow *window); - -void meta_window_group_leader_changed (MetaWindow *window); - -/* note, can return NULL */ -MetaGroup* meta_display_lookup_group (MetaDisplay *display, - Window group_leader); - -GSList* meta_group_list_windows (MetaGroup *group); - -void meta_group_update_layers (MetaGroup *group); - -const char* meta_group_get_startup_id (MetaGroup *group); - -gboolean meta_group_property_notify (MetaGroup *group, - XEvent *event); - -#endif - - - - diff --git a/src/core/iconcache.c b/src/core/iconcache.c deleted file mode 100644 index 7fa21840..00000000 --- a/src/core/iconcache.c +++ /dev/null @@ -1,849 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window icons */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "iconcache.h" -#include "ui.h" -#include "errors.h" - -#include <X11/Xatom.h> - -/* The icon-reading code is also in libwnck, please sync bugfixes */ - -static void -get_fallback_icons (MetaScreen *screen, - GdkPixbuf **iconp, - int ideal_width, - int ideal_height, - GdkPixbuf **mini_iconp, - int ideal_mini_width, - int ideal_mini_height) -{ - /* we don't scale, should be fixed if we ever un-hardcode the icon - * size - */ - *iconp = meta_ui_get_default_window_icon (screen->ui); - *mini_iconp = meta_ui_get_default_mini_icon (screen->ui); -} - -static gboolean -find_largest_sizes (gulong *data, - gulong nitems, - int *width, - int *height) -{ - *width = 0; - *height = 0; - - while (nitems > 0) - { - int w, h; - - if (nitems < 3) - return FALSE; /* no space for w, h */ - - w = data[0]; - h = data[1]; - - if (nitems < ((gulong)(w * h) + 2)) - return FALSE; /* not enough data */ - - *width = MAX (w, *width); - *height = MAX (h, *height); - - data += (w * h) + 2; - nitems -= (w * h) + 2; - } - - return TRUE; -} - -static gboolean -find_best_size (gulong *data, - gulong nitems, - int ideal_width, - int ideal_height, - int *width, - int *height, - gulong **start) -{ - int best_w; - int best_h; - gulong *best_start; - int max_width, max_height; - - *width = 0; - *height = 0; - *start = NULL; - - if (!find_largest_sizes (data, nitems, &max_width, &max_height)) - return FALSE; - - if (ideal_width < 0) - ideal_width = max_width; - if (ideal_height < 0) - ideal_height = max_height; - - best_w = 0; - best_h = 0; - best_start = NULL; - - while (nitems > 0) - { - int w, h; - gboolean replace; - - replace = FALSE; - - if (nitems < 3) - return FALSE; /* no space for w, h */ - - w = data[0]; - h = data[1]; - - if (nitems < ((gulong)(w * h) + 2)) - break; /* not enough data */ - - if (best_start == NULL) - { - replace = TRUE; - } - else - { - /* work with averages */ - const int ideal_size = (ideal_width + ideal_height) / 2; - int best_size = (best_w + best_h) / 2; - int this_size = (w + h) / 2; - - /* larger than desired is always better than smaller */ - if (best_size < ideal_size && - this_size >= ideal_size) - replace = TRUE; - /* if we have too small, pick anything bigger */ - else if (best_size < ideal_size && - this_size > best_size) - replace = TRUE; - /* if we have too large, pick anything smaller - * but still >= the ideal - */ - else if (best_size > ideal_size && - this_size >= ideal_size && - this_size < best_size) - replace = TRUE; - } - - if (replace) - { - best_start = data + 2; - best_w = w; - best_h = h; - } - - data += (w * h) + 2; - nitems -= (w * h) + 2; - } - - if (best_start) - { - *start = best_start; - *width = best_w; - *height = best_h; - return TRUE; - } - else - return FALSE; -} - -static void -argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata) -{ - guchar *p; - int i; - - *pixdata = g_new (guchar, len * 4); - p = *pixdata; - - /* One could speed this up a lot. */ - i = 0; - while (i < len) - { - guint argb; - guint rgba; - - argb = argb_data[i]; - rgba = (argb << 8) | (argb >> 24); - - *p = rgba >> 24; - ++p; - *p = (rgba >> 16) & 0xff; - ++p; - *p = (rgba >> 8) & 0xff; - ++p; - *p = rgba & 0xff; - ++p; - - ++i; - } -} - -static gboolean -read_rgb_icon (MetaDisplay *display, - Window xwindow, - int ideal_width, - int ideal_height, - int ideal_mini_width, - int ideal_mini_height, - int *width, - int *height, - guchar **pixdata, - int *mini_width, - int *mini_height, - guchar **mini_pixdata) -{ - Atom type; - int format; - gulong nitems; - gulong bytes_after; - int result, err; - guchar *data; - gulong *best; - int w, h; - gulong *best_mini; - int mini_w, mini_h; - gulong *data_as_long; - - meta_error_trap_push_with_return (display); - type = None; - data = NULL; - result = XGetWindowProperty (display->xdisplay, - xwindow, - display->atom__NET_WM_ICON, - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, &data); - err = meta_error_trap_pop_with_return (display, TRUE); - - if (err != Success || - result != Success) - return FALSE; - - if (type != XA_CARDINAL) - { - XFree (data); - return FALSE; - } - - data_as_long = (gulong *)data; - - if (!find_best_size (data_as_long, nitems, - ideal_width, ideal_height, - &w, &h, &best)) - { - XFree (data); - return FALSE; - } - - if (!find_best_size (data_as_long, nitems, - ideal_mini_width, ideal_mini_height, - &mini_w, &mini_h, &best_mini)) - { - XFree (data); - return FALSE; - } - - *width = w; - *height = h; - - *mini_width = mini_w; - *mini_height = mini_h; - - argbdata_to_pixdata (best, w * h, pixdata); - argbdata_to_pixdata (best_mini, mini_w * mini_h, mini_pixdata); - - XFree (data); - - return TRUE; -} - -static void -free_pixels (guchar *pixels, gpointer data) -{ - g_free (pixels); -} - -static void -get_pixmap_geometry (MetaDisplay *display, - Pixmap pixmap, - int *w, - int *h, - int *d) -{ - Window root_ignored; - int x_ignored, y_ignored; - guint width, height; - guint border_width_ignored; - guint depth; - - if (w) - *w = 1; - if (h) - *h = 1; - if (d) - *d = 1; - - XGetGeometry (display->xdisplay, - pixmap, &root_ignored, &x_ignored, &y_ignored, - &width, &height, &border_width_ignored, &depth); - - if (w) - *w = width; - if (h) - *h = height; - if (d) - *d = depth; -} - -static GdkPixbuf* -apply_mask (GdkPixbuf *pixbuf, - GdkPixbuf *mask) -{ - int w, h; - int i, j; - GdkPixbuf *with_alpha; - guchar *src; - guchar *dest; - int src_stride; - int dest_stride; - - w = MIN (gdk_pixbuf_get_width (mask), gdk_pixbuf_get_width (pixbuf)); - h = MIN (gdk_pixbuf_get_height (mask), gdk_pixbuf_get_height (pixbuf)); - - with_alpha = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); - - dest = gdk_pixbuf_get_pixels (with_alpha); - src = gdk_pixbuf_get_pixels (mask); - - dest_stride = gdk_pixbuf_get_rowstride (with_alpha); - src_stride = gdk_pixbuf_get_rowstride (mask); - - i = 0; - while (i < h) - { - j = 0; - while (j < w) - { - guchar *s = src + i * src_stride + j * 3; - guchar *d = dest + i * dest_stride + j * 4; - - /* s[0] == s[1] == s[2], they are 255 if the bit was set, 0 - * otherwise - */ - if (s[0] == 0) - d[3] = 0; /* transparent */ - else - d[3] = 255; /* opaque */ - - ++j; - } - - ++i; - } - - return with_alpha; -} - -static gboolean -try_pixmap_and_mask (MetaDisplay *display, - Pixmap src_pixmap, - Pixmap src_mask, - GdkPixbuf **iconp, - int ideal_width, - int ideal_height, - GdkPixbuf **mini_iconp, - int ideal_mini_width, - int ideal_mini_height) -{ - GdkPixbuf *unscaled = NULL; - GdkPixbuf *mask = NULL; - int w, h; - - if (src_pixmap == None) - return FALSE; - - meta_error_trap_push (display); - - get_pixmap_geometry (display, src_pixmap, &w, &h, NULL); - - unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL, - src_pixmap, - 0, 0, 0, 0, - w, h); - - if (unscaled && src_mask != None) - { - get_pixmap_geometry (display, src_mask, &w, &h, NULL); - mask = meta_gdk_pixbuf_get_from_pixmap (NULL, - src_mask, - 0, 0, 0, 0, - w, h); - } - - meta_error_trap_pop (display, FALSE); - - if (mask) - { - GdkPixbuf *masked; - - masked = apply_mask (unscaled, mask); - g_object_unref (G_OBJECT (unscaled)); - unscaled = masked; - - g_object_unref (G_OBJECT (mask)); - mask = NULL; - } - - if (unscaled) - { - *iconp = - gdk_pixbuf_scale_simple (unscaled, - ideal_width > 0 ? ideal_width : - gdk_pixbuf_get_width (unscaled), - ideal_height > 0 ? ideal_height : - gdk_pixbuf_get_height (unscaled), - GDK_INTERP_BILINEAR); - *mini_iconp = - gdk_pixbuf_scale_simple (unscaled, - ideal_mini_width > 0 ? ideal_mini_width : - gdk_pixbuf_get_width (unscaled), - ideal_mini_height > 0 ? ideal_mini_height : - gdk_pixbuf_get_height (unscaled), - GDK_INTERP_BILINEAR); - - g_object_unref (G_OBJECT (unscaled)); - - if (*iconp && *mini_iconp) - return TRUE; - else - { - if (*iconp) - g_object_unref (G_OBJECT (*iconp)); - if (*mini_iconp) - g_object_unref (G_OBJECT (*mini_iconp)); - return FALSE; - } - } - else - return FALSE; -} - -static void -get_kwm_win_icon (MetaDisplay *display, - Window xwindow, - Pixmap *pixmap, - Pixmap *mask) -{ - Atom type; - int format; - gulong nitems; - gulong bytes_after; - guchar *data; - Pixmap *icons; - int err, result; - - *pixmap = None; - *mask = None; - - meta_error_trap_push_with_return (display); - icons = NULL; - result = XGetWindowProperty (display->xdisplay, xwindow, - display->atom__KWM_WIN_ICON, - 0, G_MAXLONG, - False, - display->atom__KWM_WIN_ICON, - &type, &format, &nitems, - &bytes_after, &data); - icons = (Pixmap *)data; - - err = meta_error_trap_pop_with_return (display, TRUE); - if (err != Success || - result != Success) - return; - - if (type != display->atom__KWM_WIN_ICON) - { - XFree (icons); - return; - } - - *pixmap = icons[0]; - *mask = icons[1]; - - XFree (icons); - - return; -} - -void -meta_icon_cache_init (MetaIconCache *icon_cache) -{ - g_return_if_fail (icon_cache != NULL); - - icon_cache->origin = USING_NO_ICON; - icon_cache->prev_pixmap = None; - icon_cache->prev_mask = None; -#if 0 - icon_cache->icon = NULL; - icon_cache->mini_icon = NULL; - icon_cache->ideal_width = -1; /* won't be a legit width */ - icon_cache->ideal_height = -1; - icon_cache->ideal_mini_width = -1; - icon_cache->ideal_mini_height = -1; -#endif - icon_cache->want_fallback = TRUE; - icon_cache->wm_hints_dirty = TRUE; - icon_cache->kwm_win_icon_dirty = TRUE; - icon_cache->net_wm_icon_dirty = TRUE; -} - -static void -clear_icon_cache (MetaIconCache *icon_cache, - gboolean dirty_all) -{ -#if 0 - if (icon_cache->icon) - g_object_unref (G_OBJECT (icon_cache->icon)); - icon_cache->icon = NULL; - - if (icon_cache->mini_icon) - g_object_unref (G_OBJECT (icon_cache->mini_icon)); - icon_cache->mini_icon = NULL; -#endif - - icon_cache->origin = USING_NO_ICON; - - if (dirty_all) - { - icon_cache->wm_hints_dirty = TRUE; - icon_cache->kwm_win_icon_dirty = TRUE; - icon_cache->net_wm_icon_dirty = TRUE; - } -} - -void -meta_icon_cache_free (MetaIconCache *icon_cache) -{ - clear_icon_cache (icon_cache, FALSE); -} - -void -meta_icon_cache_property_changed (MetaIconCache *icon_cache, - MetaDisplay *display, - Atom atom) -{ - if (atom == display->atom__NET_WM_ICON) - icon_cache->net_wm_icon_dirty = TRUE; - else if (atom == display->atom__KWM_WIN_ICON) - icon_cache->kwm_win_icon_dirty = TRUE; - else if (atom == XA_WM_HINTS) - icon_cache->wm_hints_dirty = TRUE; -} - -gboolean -meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache) -{ - if (icon_cache->origin <= USING_KWM_WIN_ICON && - icon_cache->kwm_win_icon_dirty) - return TRUE; - else if (icon_cache->origin <= USING_WM_HINTS && - icon_cache->wm_hints_dirty) - return TRUE; - else if (icon_cache->origin <= USING_NET_WM_ICON && - icon_cache->net_wm_icon_dirty) - return TRUE; - else if (icon_cache->origin < USING_FALLBACK_ICON && - icon_cache->want_fallback) - return TRUE; - else if (icon_cache->origin == USING_NO_ICON) - return TRUE; - else if (icon_cache->origin == USING_FALLBACK_ICON && - !icon_cache->want_fallback) - return TRUE; - else - return FALSE; -} - -static void -replace_cache (MetaIconCache *icon_cache, - IconOrigin origin, - GdkPixbuf *new_icon, - GdkPixbuf *new_mini_icon) -{ - clear_icon_cache (icon_cache, FALSE); - - icon_cache->origin = origin; - -#if 0 - if (new_icon) - g_object_ref (G_OBJECT (new_icon)); - - icon_cache->icon = new_icon; - - if (new_mini_icon) - g_object_ref (G_OBJECT (new_mini_icon)); - - icon_cache->mini_icon = new_mini_icon; -#endif -} - -static GdkPixbuf* -scaled_from_pixdata (guchar *pixdata, - int w, - int h, - int new_w, - int new_h) -{ - GdkPixbuf *src; - GdkPixbuf *dest; - - src = gdk_pixbuf_new_from_data (pixdata, - GDK_COLORSPACE_RGB, - TRUE, - 8, - w, h, w * 4, - free_pixels, - NULL); - - if (src == NULL) - return NULL; - - if (w != h) - { - GdkPixbuf *tmp; - int size; - - size = MAX (w, h); - - tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size); - - if (tmp) - { - gdk_pixbuf_fill (tmp, 0); - gdk_pixbuf_copy_area (src, 0, 0, w, h, - tmp, - (size - w) / 2, (size - h) / 2); - - g_object_unref (src); - src = tmp; - } - } - - if (w != new_w || h != new_h) - { - dest = gdk_pixbuf_scale_simple (src, new_w, new_h, GDK_INTERP_BILINEAR); - - g_object_unref (G_OBJECT (src)); - } - else - { - dest = src; - } - - return dest; -} - -gboolean -meta_read_icons (MetaScreen *screen, - Window xwindow, - MetaIconCache *icon_cache, - Pixmap wm_hints_pixmap, - Pixmap wm_hints_mask, - GdkPixbuf **iconp, - int ideal_width, - int ideal_height, - GdkPixbuf **mini_iconp, - int ideal_mini_width, - int ideal_mini_height) -{ - guchar *pixdata; - int w, h; - guchar *mini_pixdata; - int mini_w, mini_h; - Pixmap pixmap; - Pixmap mask; - - /* Return value is whether the icon changed */ - - g_return_val_if_fail (icon_cache != NULL, FALSE); - - *iconp = NULL; - *mini_iconp = NULL; - -#if 0 - if (ideal_width != icon_cache->ideal_width || - ideal_height != icon_cache->ideal_height || - ideal_mini_width != icon_cache->ideal_mini_width || - ideal_mini_height != icon_cache->ideal_mini_height) - clear_icon_cache (icon_cache, TRUE); - - icon_cache->ideal_width = ideal_width; - icon_cache->ideal_height = ideal_height; - icon_cache->ideal_mini_width = ideal_mini_width; - icon_cache->ideal_mini_height = ideal_mini_height; -#endif - - if (!meta_icon_cache_get_icon_invalidated (icon_cache)) - return FALSE; /* we have no new info to use */ - - pixdata = NULL; - - /* Our algorithm here assumes that we can't have for example origin - * < USING_NET_WM_ICON and icon_cache->net_wm_icon_dirty == FALSE - * unless we have tried to read NET_WM_ICON. - * - * Put another way, if an icon origin is not dirty, then we have - * tried to read it at the current size. If it is dirty, then - * we haven't done that since the last change. - */ - - if (icon_cache->origin <= USING_NET_WM_ICON && - icon_cache->net_wm_icon_dirty) - - { - icon_cache->net_wm_icon_dirty = FALSE; - - if (read_rgb_icon (screen->display, xwindow, - ideal_width, ideal_height, - ideal_mini_width, ideal_mini_height, - &w, &h, &pixdata, - &mini_w, &mini_h, &mini_pixdata)) - { - *iconp = scaled_from_pixdata (pixdata, w, h, - ideal_width, ideal_height); - - *mini_iconp = scaled_from_pixdata (mini_pixdata, mini_w, mini_h, - ideal_mini_width, ideal_mini_height); - - if (*iconp && *mini_iconp) - { - replace_cache (icon_cache, USING_NET_WM_ICON, - *iconp, *mini_iconp); - - return TRUE; - } - else - { - if (*iconp) - g_object_unref (G_OBJECT (*iconp)); - if (*mini_iconp) - g_object_unref (G_OBJECT (*mini_iconp)); - } - } - } - - if (icon_cache->origin <= USING_WM_HINTS && - icon_cache->wm_hints_dirty) - { - icon_cache->wm_hints_dirty = FALSE; - - pixmap = wm_hints_pixmap; - mask = wm_hints_mask; - - /* We won't update if pixmap is unchanged; - * avoids a get_from_drawable() on every geometry - * hints change - */ - if ((pixmap != icon_cache->prev_pixmap || - mask != icon_cache->prev_mask) && - pixmap != None) - { - if (try_pixmap_and_mask (screen->display, - pixmap, mask, - iconp, ideal_width, ideal_height, - mini_iconp, ideal_mini_width, ideal_mini_height)) - { - icon_cache->prev_pixmap = pixmap; - icon_cache->prev_mask = mask; - - replace_cache (icon_cache, USING_WM_HINTS, - *iconp, *mini_iconp); - - return TRUE; - } - } - } - - if (icon_cache->origin <= USING_KWM_WIN_ICON && - icon_cache->kwm_win_icon_dirty) - { - icon_cache->kwm_win_icon_dirty = FALSE; - - get_kwm_win_icon (screen->display, xwindow, &pixmap, &mask); - - if ((pixmap != icon_cache->prev_pixmap || - mask != icon_cache->prev_mask) && - pixmap != None) - { - if (try_pixmap_and_mask (screen->display, pixmap, mask, - iconp, ideal_width, ideal_height, - mini_iconp, ideal_mini_width, ideal_mini_height)) - { - icon_cache->prev_pixmap = pixmap; - icon_cache->prev_mask = mask; - - replace_cache (icon_cache, USING_KWM_WIN_ICON, - *iconp, *mini_iconp); - - return TRUE; - } - } - } - - if (icon_cache->want_fallback && - icon_cache->origin < USING_FALLBACK_ICON) - { - get_fallback_icons (screen, - iconp, - ideal_width, - ideal_height, - mini_iconp, - ideal_mini_width, - ideal_mini_height); - - replace_cache (icon_cache, USING_FALLBACK_ICON, - *iconp, *mini_iconp); - - return TRUE; - } - - if (!icon_cache->want_fallback && - icon_cache->origin == USING_FALLBACK_ICON) - { - /* Get rid of current icon */ - clear_icon_cache (icon_cache, FALSE); - - return TRUE; - } - - /* found nothing new */ - return FALSE; -} diff --git a/src/core/iconcache.h b/src/core/iconcache.h deleted file mode 100644 index ac3e40ca..00000000 --- a/src/core/iconcache.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window icons */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_ICON_CACHE_H -#define META_ICON_CACHE_H - -#include "screen-private.h" - -typedef struct _MetaIconCache MetaIconCache; - -typedef enum -{ - /* These MUST be in ascending order of preference; - * i.e. if we get _NET_WM_ICON and already have - * WM_HINTS, we prefer _NET_WM_ICON - */ - USING_NO_ICON, - USING_FALLBACK_ICON, - USING_KWM_WIN_ICON, - USING_WM_HINTS, - USING_NET_WM_ICON -} IconOrigin; - -struct _MetaIconCache -{ - int origin; - Pixmap prev_pixmap; - Pixmap prev_mask; - guint want_fallback : 1; - /* TRUE if these props have changed */ - guint wm_hints_dirty : 1; - guint kwm_win_icon_dirty : 1; - guint net_wm_icon_dirty : 1; -}; - -void meta_icon_cache_init (MetaIconCache *icon_cache); -void meta_icon_cache_free (MetaIconCache *icon_cache); -void meta_icon_cache_property_changed (MetaIconCache *icon_cache, - MetaDisplay *display, - Atom atom); -gboolean meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache); - -gboolean meta_read_icons (MetaScreen *screen, - Window xwindow, - MetaIconCache *icon_cache, - Pixmap wm_hints_pixmap, - Pixmap wm_hints_mask, - GdkPixbuf **iconp, - int ideal_width, - int ideal_height, - GdkPixbuf **mini_iconp, - int ideal_mini_width, - int ideal_mini_height); - -#endif - - - - diff --git a/src/core/keybindings.c b/src/core/keybindings.c deleted file mode 100644 index 66b8294f..00000000 --- a/src/core/keybindings.c +++ /dev/null @@ -1,3350 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity Keybindings */ -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#define _GNU_SOURCE -#define _SVID_SOURCE /* for putenv() */ - -#include <config.h> -#include "keybindings.h" -#include "workspace.h" -#include "errors.h" -#include "edge-resistance.h" -#include "ui.h" -#include "frame-private.h" -#include "place.h" -#include "prefs.h" -#include "effects.h" -#include "util.h" - -#include <X11/keysym.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#ifdef HAVE_XKB -#include <X11/XKBlib.h> -#endif - -static gboolean all_bindings_disabled = FALSE; - -typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding); - -/* Prototypes for handlers */ -#define keybind(name, handler, param, flags, stroke, description) \ -static void \ -handler (MetaDisplay *display,\ - MetaScreen *screen,\ - MetaWindow *window,\ - XEvent *event,\ - MetaKeyBinding *binding); -#include "all-keybindings.h" -#undef keybind - -/* These can't be bound to anything, but they are used to handle - * various other events. TODO: Possibly we should include them as event - * handler functions and have some kind of flag to say they're unbindable. - */ - -static void handle_workspace_switch (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding); - -static gboolean process_mouse_move_resize_grab (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - KeySym keysym); - -static gboolean process_keyboard_move_grab (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - KeySym keysym); - -static gboolean process_keyboard_resize_grab (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - KeySym keysym); - -static gboolean process_tab_grab (MetaDisplay *display, - MetaScreen *screen, - XEvent *event, - KeySym keysym); - -static gboolean process_workspace_switch_grab (MetaDisplay *display, - MetaScreen *screen, - XEvent *event, - KeySym keysym); - -static void regrab_key_bindings (MetaDisplay *display); - -typedef struct -{ - const char *name; - MetaKeyHandlerFunc func; - gint data, flags; -} MetaKeyHandler; - -struct _MetaKeyBinding -{ - const char *name; - KeySym keysym; - KeyCode keycode; - unsigned int mask; - MetaVirtualModifier modifiers; - const MetaKeyHandler *handler; -}; - -#define keybind(name, handler, param, flags, stroke, description) \ - { #name, handler, param, flags }, -static const MetaKeyHandler key_handlers[] = { -#include "all-keybindings.h" - { NULL, NULL, 0, 0 } -}; -#undef keybind - -static void -reload_keymap (MetaDisplay *display) -{ - if (display->keymap) - meta_XFree (display->keymap); - - display->keymap = XGetKeyboardMapping (display->xdisplay, - display->min_keycode, - display->max_keycode - - display->min_keycode + 1, - &display->keysyms_per_keycode); -} - -static void -reload_modmap (MetaDisplay *display) -{ - XModifierKeymap *modmap; - int map_size; - int i; - - if (display->modmap) - XFreeModifiermap (display->modmap); - - modmap = XGetModifierMapping (display->xdisplay); - display->modmap = modmap; - - display->ignored_modifier_mask = 0; - - /* Multiple bits may get set in each of these */ - display->num_lock_mask = 0; - display->scroll_lock_mask = 0; - display->meta_mask = 0; - display->hyper_mask = 0; - display->super_mask = 0; - - /* there are 8 modifiers, and the first 3 are shift, shift lock, - * and control - */ - map_size = 8 * modmap->max_keypermod; - i = 3 * modmap->max_keypermod; - while (i < map_size) - { - /* get the key code at this point in the map, - * see if its keysym is one we're interested in - */ - int keycode = modmap->modifiermap[i]; - - if (keycode >= display->min_keycode && - keycode <= display->max_keycode) - { - int j = 0; - KeySym *syms = display->keymap + - (keycode - display->min_keycode) * display->keysyms_per_keycode; - - while (j < display->keysyms_per_keycode) - { - if (syms[j] != 0) - { - const char *str; - - str = XKeysymToString (syms[j]); - meta_topic (META_DEBUG_KEYBINDINGS, - "Keysym %s bound to modifier 0x%x\n", - str ? str : "none", - (1 << ( i / modmap->max_keypermod))); - } - - if (syms[j] == XK_Num_Lock) - { - /* Mod1Mask is 1 << 3 for example, i.e. the - * fourth modifier, i / keyspermod is the modifier - * index - */ - - display->num_lock_mask |= (1 << ( i / modmap->max_keypermod)); - } - else if (syms[j] == XK_Scroll_Lock) - { - display->scroll_lock_mask |= (1 << ( i / modmap->max_keypermod)); - } - else if (syms[j] == XK_Super_L || - syms[j] == XK_Super_R) - { - display->super_mask |= (1 << ( i / modmap->max_keypermod)); - } - else if (syms[j] == XK_Hyper_L || - syms[j] == XK_Hyper_R) - { - display->hyper_mask |= (1 << ( i / modmap->max_keypermod)); - } - else if (syms[j] == XK_Meta_L || - syms[j] == XK_Meta_R) - { - display->meta_mask |= (1 << ( i / modmap->max_keypermod)); - } - - ++j; - } - } - - ++i; - } - - display->ignored_modifier_mask = (display->num_lock_mask | - display->scroll_lock_mask | - LockMask); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Ignoring modmask 0x%x num lock 0x%x scroll lock 0x%x hyper 0x%x super 0x%x meta 0x%x\n", - display->ignored_modifier_mask, - display->num_lock_mask, - display->scroll_lock_mask, - display->hyper_mask, - display->super_mask, - display->meta_mask); -} - -static void -reload_keycodes (MetaDisplay *display) -{ - meta_topic (META_DEBUG_KEYBINDINGS, - "Reloading keycodes for binding tables\n"); - - if (display->key_bindings) - { - int i; - - i = 0; - while (i < display->n_key_bindings) - { - if (display->key_bindings[i].keycode == 0) - display->key_bindings[i].keycode = XKeysymToKeycode ( - display->xdisplay, display->key_bindings[i].keysym); - - ++i; - } - } -} - -static void -reload_modifiers (MetaDisplay *display) -{ - meta_topic (META_DEBUG_KEYBINDINGS, - "Reloading keycodes for binding tables\n"); - - if (display->key_bindings) - { - int i; - - i = 0; - while (i < display->n_key_bindings) - { - meta_display_devirtualize_modifiers (display, - display->key_bindings[i].modifiers, - &display->key_bindings[i].mask); - - meta_topic (META_DEBUG_KEYBINDINGS, - " Devirtualized mods 0x%x -> 0x%x (%s)\n", - display->key_bindings[i].modifiers, - display->key_bindings[i].mask, - display->key_bindings[i].name); - - ++i; - } - } -} - - -static int -count_bindings (const MetaKeyPref *prefs, - int n_prefs) -{ - int i; - int count; - - count = 0; - i = 0; - while (i < n_prefs) - { - GSList *tmp = prefs[i].bindings; - - while (tmp) - { - MetaKeyCombo *combo = tmp->data; - - if (combo && (combo->keysym != None || combo->keycode != 0)) - { - count += 1; - - if (prefs[i].add_shift && - (combo->modifiers & META_VIRTUAL_SHIFT_MASK) == 0) - count += 1; - } - - tmp = tmp->next; - } - - ++i; - } - - return count; -} - -/* FIXME: replace this with a temporary hash */ -static const MetaKeyHandler* -find_handler (const MetaKeyHandler *handlers, - const char *name) -{ - const MetaKeyHandler *iter; - - iter = handlers; - while (iter->name) - { - if (strcmp (iter->name, name) == 0) - return iter; - - ++iter; - } - - return NULL; -} - -static void -rebuild_binding_table (MetaDisplay *display, - MetaKeyBinding **bindings_p, - int *n_bindings_p, - const MetaKeyPref *prefs, - int n_prefs) -{ - int n_bindings; - int src, dest; - - n_bindings = count_bindings (prefs, n_prefs); - g_free (*bindings_p); - *bindings_p = g_new0 (MetaKeyBinding, n_bindings); - - src = 0; - dest = 0; - while (src < n_prefs) - { - GSList *tmp = prefs[src].bindings; - - while (tmp) - { - MetaKeyCombo *combo = tmp->data; - - if (combo && (combo->keysym != None || combo->keycode != 0)) - { - const MetaKeyHandler *handler = find_handler (key_handlers, prefs[src].name); - - (*bindings_p)[dest].name = prefs[src].name; - (*bindings_p)[dest].handler = handler; - (*bindings_p)[dest].keysym = combo->keysym; - (*bindings_p)[dest].keycode = combo->keycode; - (*bindings_p)[dest].modifiers = combo->modifiers; - (*bindings_p)[dest].mask = 0; - - ++dest; - - if (prefs[src].add_shift && - (combo->modifiers & META_VIRTUAL_SHIFT_MASK) == 0) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Binding %s also needs Shift grabbed\n", - prefs[src].name); - - (*bindings_p)[dest].name = prefs[src].name; - (*bindings_p)[dest].handler = handler; - (*bindings_p)[dest].keysym = combo->keysym; - (*bindings_p)[dest].keycode = combo->keycode; - (*bindings_p)[dest].modifiers = combo->modifiers | - META_VIRTUAL_SHIFT_MASK; - (*bindings_p)[dest].mask = 0; - - ++dest; - } - } - - tmp = tmp->next; - } - - ++src; - } - - g_assert (dest == n_bindings); - - *n_bindings_p = dest; - - meta_topic (META_DEBUG_KEYBINDINGS, - " %d bindings in table\n", - *n_bindings_p); -} - -static void -rebuild_key_binding_table (MetaDisplay *display) -{ - const MetaKeyPref *prefs; - int n_prefs; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Rebuilding key binding table from preferences\n"); - - meta_prefs_get_key_bindings (&prefs, &n_prefs); - rebuild_binding_table (display, - &display->key_bindings, - &display->n_key_bindings, - prefs, n_prefs); -} - -static void -regrab_key_bindings (MetaDisplay *display) -{ - GSList *tmp; - GSList *windows; - - meta_error_trap_push (display); /* for efficiency push outer trap */ - - tmp = display->screens; - while (tmp != NULL) - { - MetaScreen *screen = tmp->data; - - meta_screen_ungrab_keys (screen); - meta_screen_grab_keys (screen); - - tmp = tmp->next; - } - - windows = meta_display_list_windows (display); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - meta_window_ungrab_keys (w); - meta_window_grab_keys (w); - - tmp = tmp->next; - } - meta_error_trap_pop (display, FALSE); - - g_slist_free (windows); -} - -static MetaKeyBindingAction -display_get_keybinding_action (MetaDisplay *display, - unsigned int keysym, - unsigned int keycode, - unsigned long mask) -{ - int i; - - i = display->n_key_bindings - 1; - while (i >= 0) - { - if (display->key_bindings[i].keysym == keysym && - display->key_bindings[i].keycode == keycode && - display->key_bindings[i].mask == mask) - { - return meta_prefs_get_keybinding_action (display->key_bindings[i].name); - } - - --i; - } - - return META_KEYBINDING_ACTION_NONE; -} - -void -meta_display_process_mapping_event (MetaDisplay *display, - XEvent *event) -{ - if (event->xmapping.request == MappingModifier) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Received MappingModifier event, will reload modmap and redo keybindings\n"); - - reload_modmap (display); - - reload_modifiers (display); - - regrab_key_bindings (display); - } - else if (event->xmapping.request == MappingKeyboard) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Received MappingKeyboard event, will reload keycodes and redo keybindings\n"); - - reload_keymap (display); - reload_modmap (display); - - reload_keycodes (display); - - regrab_key_bindings (display); - } -} - -static void -bindings_changed_callback (MetaPreference pref, - void *data) -{ - MetaDisplay *display; - - display = data; - - switch (pref) - { - case META_PREF_KEYBINDINGS: - rebuild_key_binding_table (display); - reload_keycodes (display); - reload_modifiers (display); - regrab_key_bindings (display); - break; - default: - break; - } -} - - -void -meta_display_init_keys (MetaDisplay *display) -{ - /* Keybindings */ - display->keymap = NULL; - display->keysyms_per_keycode = 0; - display->modmap = NULL; - display->min_keycode = 0; - display->max_keycode = 0; - display->ignored_modifier_mask = 0; - display->num_lock_mask = 0; - display->scroll_lock_mask = 0; - display->hyper_mask = 0; - display->super_mask = 0; - display->meta_mask = 0; - display->key_bindings = NULL; - display->n_key_bindings = 0; - - XDisplayKeycodes (display->xdisplay, - &display->min_keycode, - &display->max_keycode); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Display has keycode range %d to %d\n", - display->min_keycode, - display->max_keycode); - - reload_keymap (display); - reload_modmap (display); - - rebuild_key_binding_table (display); - - reload_keycodes (display); - reload_modifiers (display); - - /* Keys are actually grabbed in meta_screen_grab_keys() */ - - meta_prefs_add_listener (bindings_changed_callback, display); -} - -void -meta_display_shutdown_keys (MetaDisplay *display) -{ - /* Note that display->xdisplay is invalid in this function */ - - meta_prefs_remove_listener (bindings_changed_callback, display); - - if (display->keymap) - meta_XFree (display->keymap); - - if (display->modmap) - XFreeModifiermap (display->modmap); - g_free (display->key_bindings); -} - -static const char* -keysym_name (int keysym) -{ - const char *name; - - name = XKeysymToString (keysym); - if (name == NULL) - name = "(unknown)"; - - return name; -} - -/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */ -static void -meta_change_keygrab (MetaDisplay *display, - Window xwindow, - gboolean grab, - int keysym, - unsigned int keycode, - int modmask) -{ - unsigned int ignored_mask; - - /* Grab keycode/modmask, together with - * all combinations of ignored modifiers. - * X provides no better way to do this. - */ - - meta_topic (META_DEBUG_KEYBINDINGS, - "%s keybinding %s keycode %d mask 0x%x on 0x%lx\n", - grab ? "Grabbing" : "Ungrabbing", - keysym_name (keysym), keycode, - modmask, xwindow); - - /* efficiency, avoid so many XSync() */ - meta_error_trap_push (display); - - ignored_mask = 0; - while (ignored_mask <= display->ignored_modifier_mask) - { - if (ignored_mask & ~(display->ignored_modifier_mask)) - { - /* Not a combination of ignored modifiers - * (it contains some non-ignored modifiers) - */ - ++ignored_mask; - continue; - } - - if (meta_is_debugging ()) - meta_error_trap_push_with_return (display); - if (grab) - XGrabKey (display->xdisplay, keycode, - modmask | ignored_mask, - xwindow, - True, - GrabModeAsync, GrabModeSync); - else - XUngrabKey (display->xdisplay, keycode, - modmask | ignored_mask, - xwindow); - - if (meta_is_debugging ()) - { - int result; - - result = meta_error_trap_pop_with_return (display, FALSE); - - if (grab && result != Success) - { - if (result == BadAccess) - meta_warning (_("Some other program is already using the key %s with modifiers %x as a binding\n"), keysym_name (keysym), modmask | ignored_mask); - else - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to grab key %s with modifiers %x\n", - keysym_name (keysym), modmask | ignored_mask); - } - } - - ++ignored_mask; - } - - meta_error_trap_pop (display, FALSE); -} - -static void -meta_grab_key (MetaDisplay *display, - Window xwindow, - int keysym, - unsigned int keycode, - int modmask) -{ - meta_change_keygrab (display, xwindow, TRUE, keysym, keycode, modmask); -} - -static void -grab_keys (MetaKeyBinding *bindings, - int n_bindings, - MetaDisplay *display, - Window xwindow, - gboolean binding_per_window) -{ - int i; - - g_assert (n_bindings == 0 || bindings != NULL); - - meta_error_trap_push (display); - - i = 0; - while (i < n_bindings) - { - if (!!binding_per_window == - !!(bindings[i].handler->flags & BINDING_PER_WINDOW) && - bindings[i].keycode != 0) - { - meta_grab_key (display, xwindow, - bindings[i].keysym, - bindings[i].keycode, - bindings[i].mask); - } - - ++i; - } - - meta_error_trap_pop (display, FALSE); -} - -static void -ungrab_all_keys (MetaDisplay *display, - Window xwindow) -{ - if (meta_is_debugging ()) - meta_error_trap_push_with_return (display); - else - meta_error_trap_push (display); - - XUngrabKey (display->xdisplay, AnyKey, AnyModifier, - xwindow); - - if (meta_is_debugging ()) - { - int result; - - result = meta_error_trap_pop_with_return (display, FALSE); - - if (result != Success) - meta_topic (META_DEBUG_KEYBINDINGS, - "Ungrabbing all keys on 0x%lx failed\n", xwindow); - } - else - meta_error_trap_pop (display, FALSE); -} - -void -meta_screen_grab_keys (MetaScreen *screen) -{ - if (screen->all_keys_grabbed) - return; - - if (screen->keys_grabbed) - return; - - grab_keys (screen->display->key_bindings, - screen->display->n_key_bindings, - screen->display, screen->xroot, - FALSE); - - screen->keys_grabbed = TRUE; -} - -void -meta_screen_ungrab_keys (MetaScreen *screen) -{ - if (screen->keys_grabbed) - { - ungrab_all_keys (screen->display, screen->xroot); - screen->keys_grabbed = FALSE; - } -} - -void -meta_window_grab_keys (MetaWindow *window) -{ - if (window->all_keys_grabbed) - return; - - if (window->type == META_WINDOW_DOCK) - { - if (window->keys_grabbed) - ungrab_all_keys (window->display, window->xwindow); - window->keys_grabbed = FALSE; - return; - } - - if (window->keys_grabbed) - { - if (window->frame && !window->grab_on_frame) - ungrab_all_keys (window->display, window->xwindow); - else if (window->frame == NULL && - window->grab_on_frame) - ; /* continue to regrab on client window */ - else - return; /* already all good */ - } - - grab_keys (window->display->key_bindings, - window->display->n_key_bindings, - window->display, - window->frame ? window->frame->xwindow : window->xwindow, - TRUE); - - window->keys_grabbed = TRUE; - window->grab_on_frame = window->frame != NULL; -} - -void -meta_window_ungrab_keys (MetaWindow *window) -{ - if (window->keys_grabbed) - { - if (window->grab_on_frame && - window->frame != NULL) - ungrab_all_keys (window->display, - window->frame->xwindow); - else if (!window->grab_on_frame) - ungrab_all_keys (window->display, - window->xwindow); - - window->keys_grabbed = FALSE; - } -} - -#ifdef WITH_VERBOSE_MODE -static const char* -grab_status_to_string (int status) -{ - switch (status) - { - case AlreadyGrabbed: - return "AlreadyGrabbed"; - case GrabSuccess: - return "GrabSuccess"; - case GrabNotViewable: - return "GrabNotViewable"; - case GrabFrozen: - return "GrabFrozen"; - case GrabInvalidTime: - return "GrabInvalidTime"; - default: - return "(unknown)"; - } -} -#endif /* WITH_VERBOSE_MODE */ - -static gboolean -grab_keyboard (MetaDisplay *display, - Window xwindow, - guint32 timestamp) -{ - int result; - int grab_status; - - /* Grab the keyboard, so we get key releases and all key - * presses - */ - meta_error_trap_push_with_return (display); - - grab_status = XGrabKeyboard (display->xdisplay, - xwindow, True, - GrabModeAsync, GrabModeAsync, - timestamp); - - if (grab_status != GrabSuccess) - { - meta_error_trap_pop_with_return (display, TRUE); - meta_topic (META_DEBUG_KEYBINDINGS, - "XGrabKeyboard() returned failure status %s time %u\n", - grab_status_to_string (grab_status), - timestamp); - return FALSE; - } - else - { - result = meta_error_trap_pop_with_return (display, TRUE); - if (result != Success) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "XGrabKeyboard() resulted in an error\n"); - return FALSE; - } - } - - meta_topic (META_DEBUG_KEYBINDINGS, "Grabbed all keys\n"); - - return TRUE; -} - -static void -ungrab_keyboard (MetaDisplay *display, guint32 timestamp) -{ - meta_error_trap_push (display); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Ungrabbing keyboard with timestamp %u\n", - timestamp); - XUngrabKeyboard (display->xdisplay, timestamp); - meta_error_trap_pop (display, FALSE); -} - -gboolean -meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp) -{ - gboolean retval; - - if (screen->all_keys_grabbed) - return FALSE; - - if (screen->keys_grabbed) - meta_screen_ungrab_keys (screen); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Grabbing all keys on RootWindow\n"); - retval = grab_keyboard (screen->display, screen->xroot, timestamp); - if (retval) - screen->all_keys_grabbed = TRUE; - else - meta_screen_grab_keys (screen); - - return retval; -} - -void -meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp) -{ - if (screen->all_keys_grabbed) - { - ungrab_keyboard (screen->display, timestamp); - - screen->all_keys_grabbed = FALSE; - screen->keys_grabbed = FALSE; - - /* Re-establish our standard bindings */ - meta_screen_grab_keys (screen); - } -} - -gboolean -meta_window_grab_all_keys (MetaWindow *window, - guint32 timestamp) -{ - Window grabwindow; - gboolean retval; - - if (window->all_keys_grabbed) - return FALSE; - - if (window->keys_grabbed) - meta_window_ungrab_keys (window); - - /* Make sure the window is focused, otherwise the grab - * won't do a lot of good. - */ - meta_topic (META_DEBUG_FOCUS, - "Focusing %s because we're grabbing all its keys\n", - window->desc); - meta_window_focus (window, timestamp); - - grabwindow = window->frame ? window->frame->xwindow : window->xwindow; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Grabbing all keys on window %s\n", window->desc); - retval = grab_keyboard (window->display, grabwindow, timestamp); - if (retval) - { - window->keys_grabbed = FALSE; - window->all_keys_grabbed = TRUE; - window->grab_on_frame = window->frame != NULL; - } - - return retval; -} - -void -meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp) -{ - if (window->all_keys_grabbed) - { - ungrab_keyboard (window->display, timestamp); - - window->grab_on_frame = FALSE; - window->all_keys_grabbed = FALSE; - window->keys_grabbed = FALSE; - - /* Re-establish our standard bindings */ - meta_window_grab_keys (window); - } -} - -static gboolean -is_modifier (MetaDisplay *display, - unsigned int keycode) -{ - int i; - int map_size; - gboolean retval = FALSE; - - g_assert (display->modmap); - - map_size = 8 * display->modmap->max_keypermod; - i = 0; - while (i < map_size) - { - if (keycode == display->modmap->modifiermap[i]) - { - retval = TRUE; - break; - } - ++i; - } - - return retval; -} - -/* Indexes: - * shift = 0 - * lock = 1 - * control = 2 - * mod1 = 3 - * mod2 = 4 - * mod3 = 5 - * mod4 = 6 - * mod5 = 7 - */ - -static gboolean -is_specific_modifier (MetaDisplay *display, - unsigned int keycode, - unsigned int mask) -{ - int i; - int end; - gboolean retval = FALSE; - int mod_index; - - g_assert (display->modmap); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Checking whether code 0x%x is bound to modifier 0x%x\n", - keycode, mask); - - mod_index = 0; - mask = mask >> 1; - while (mask != 0) - { - mod_index += 1; - mask = mask >> 1; - } - - meta_topic (META_DEBUG_KEYBINDINGS, - "Modifier has index %d\n", mod_index); - - end = (mod_index + 1) * display->modmap->max_keypermod; - i = mod_index * display->modmap->max_keypermod; - while (i < end) - { - if (keycode == display->modmap->modifiermap[i]) - { - retval = TRUE; - break; - } - ++i; - } - - return retval; -} - -static unsigned int -get_primary_modifier (MetaDisplay *display, - unsigned int entire_binding_mask) -{ - /* The idea here is to see if the "main" modifier - * for Alt+Tab has been pressed/released. So if the binding - * is Alt+Shift+Tab then releasing Alt is the thing that - * ends the operation. It's pretty random how we order - * these. - */ - unsigned int masks[] = { Mod5Mask, Mod4Mask, Mod3Mask, - Mod2Mask, Mod1Mask, ControlMask, - ShiftMask, LockMask }; - - int i; - - i = 0; - while (i < (int) G_N_ELEMENTS (masks)) - { - if (entire_binding_mask & masks[i]) - return masks[i]; - ++i; - } - - return 0; -} - -static gboolean -keycode_is_primary_modifier (MetaDisplay *display, - unsigned int keycode, - unsigned int entire_binding_mask) -{ - unsigned int primary_modifier; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Checking whether code 0x%x is the primary modifier of mask 0x%x\n", - keycode, entire_binding_mask); - - primary_modifier = get_primary_modifier (display, entire_binding_mask); - if (primary_modifier != 0) - return is_specific_modifier (display, keycode, primary_modifier); - else - return FALSE; -} - -static gboolean -primary_modifier_still_pressed (MetaDisplay *display, - unsigned int entire_binding_mask) -{ - unsigned int primary_modifier; - int x, y, root_x, root_y; - Window root, child; - guint mask; - MetaScreen *random_screen; - Window random_xwindow; - - primary_modifier = get_primary_modifier (display, entire_binding_mask); - - random_screen = display->screens->data; - random_xwindow = random_screen->no_focus_window; - XQueryPointer (display->xdisplay, - random_xwindow, /* some random window */ - &root, &child, - &root_x, &root_y, - &x, &y, - &mask); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Primary modifier 0x%x full grab mask 0x%x current state 0x%x\n", - primary_modifier, entire_binding_mask, mask); - - if ((mask & primary_modifier) == 0) - return FALSE; - else - return TRUE; -} - -/* now called from only one place, may be worth merging */ -static gboolean -process_event (MetaKeyBinding *bindings, - int n_bindings, - MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - KeySym keysym, - gboolean on_window) -{ - int i; - - /* we used to have release-based bindings but no longer. */ - if (event->type == KeyRelease) - return FALSE; - - /* - * TODO: This would be better done with a hash table; - * it doesn't suit to use O(n) for such a common operation. - */ - for (i=0; i<n_bindings; i++) - { - const MetaKeyHandler *handler = bindings[i].handler; - - if ((!on_window && handler->flags & BINDING_PER_WINDOW) || - event->type != KeyPress || - bindings[i].keycode != event->xkey.keycode || - ((event->xkey.state & 0xff & ~(display->ignored_modifier_mask)) != - bindings[i].mask)) - continue; - - /* - * window must be non-NULL for on_window to be true, - * and so also window must be non-NULL if we get here and - * this is a BINDING_PER_WINDOW binding. - */ - - meta_topic (META_DEBUG_KEYBINDINGS, - "Binding keycode 0x%x mask 0x%x matches event 0x%x state 0x%x\n", - bindings[i].keycode, bindings[i].mask, - event->xkey.keycode, event->xkey.state); - - if (handler == NULL) - meta_bug ("Binding %s has no handler\n", bindings[i].name); - else - meta_topic (META_DEBUG_KEYBINDINGS, - "Running handler for %s\n", - bindings[i].name); - - /* Global keybindings count as a let-the-terminal-lose-focus - * due to new window mapping until the user starts - * interacting with the terminal again. - */ - display->allow_terminal_deactivation = TRUE; - - (* handler->func) (display, screen, - bindings[i].handler->flags & BINDING_PER_WINDOW? window: NULL, - event, - &bindings[i]); - return TRUE; - } - - meta_topic (META_DEBUG_KEYBINDINGS, - "No handler found for this event in this binding table\n"); - return FALSE; -} - -/* Handle a key event. May be called recursively: some key events cause - * grabs to be ended and then need to be processed again in their own - * right. This cannot cause infinite recursion because we never call - * ourselves when there wasn't a grab, and we always clear the grab - * first; the invariant is enforced using an assertion. See #112560. - * FIXME: We need to prove there are no race conditions here. - * FIXME: Does it correctly handle alt-Tab being followed by another - * grabbing keypress without letting go of alt? - * FIXME: An iterative solution would probably be simpler to understand - * (and help us solve the other fixmes). - */ -void -meta_display_process_key_event (MetaDisplay *display, - MetaWindow *window, - XEvent *event) -{ - KeySym keysym; - gboolean keep_grab; - gboolean all_keys_grabbed; - const char *str; - MetaScreen *screen; - - XAllowEvents (display->xdisplay, - all_bindings_disabled ? ReplayKeyboard : AsyncKeyboard, - event->xkey.time); - if (all_bindings_disabled) - return; - - /* if key event was on root window, we have a shortcut */ - screen = meta_display_screen_for_root (display, event->xkey.window); - - /* else round-trip to server */ - if (screen == NULL) - screen = meta_display_screen_for_xwindow (display, - event->xany.window); - - if (screen == NULL) - return; /* event window is destroyed */ - - /* ignore key events on popup menus and such. */ - if (window == NULL && - meta_ui_window_is_widget (screen->ui, event->xany.window)) - return; - - /* window may be NULL */ - - keysym = XKeycodeToKeysym (display->xdisplay, event->xkey.keycode, 0); - - str = XKeysymToString (keysym); - - /* was topic */ - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing key %s event, keysym: %s state: 0x%x window: %s\n", - event->type == KeyPress ? "press" : "release", - str ? str : "none", event->xkey.state, - window ? window->desc : "(no window)"); - - keep_grab = TRUE; - all_keys_grabbed = window ? window->all_keys_grabbed : screen->all_keys_grabbed; - if (all_keys_grabbed) - { - if (display->grab_op == META_GRAB_OP_NONE) - return; - /* If we get here we have a global grab, because - * we're in some special keyboard mode such as window move - * mode. - */ - if (window ? (window == display->grab_window) : - (screen == display->grab_screen)) - { - switch (display->grab_op) - { - case META_GRAB_OP_MOVING: - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_E: - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing event for mouse-only move/resize\n"); - g_assert (window != NULL); - keep_grab = process_mouse_move_resize_grab (display, screen, - window, event, keysym); - break; - - case META_GRAB_OP_KEYBOARD_MOVING: - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing event for keyboard move\n"); - g_assert (window != NULL); - keep_grab = process_keyboard_move_grab (display, screen, - window, event, keysym); - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing event for keyboard resize\n"); - g_assert (window != NULL); - keep_grab = process_keyboard_resize_grab (display, screen, - window, event, keysym); - break; - - case META_GRAB_OP_KEYBOARD_TABBING_NORMAL: - case META_GRAB_OP_KEYBOARD_TABBING_DOCK: - case META_GRAB_OP_KEYBOARD_TABBING_GROUP: - case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: - case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: - case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing event for keyboard tabbing/cycling\n"); - keep_grab = process_tab_grab (display, screen, event, keysym); - break; - - case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing event for keyboard workspace switching\n"); - keep_grab = process_workspace_switch_grab (display, screen, event, keysym); - break; - - default: - break; - } - } - if (!keep_grab) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Ending grab op %u on key event sym %s\n", - display->grab_op, XKeysymToString (keysym)); - meta_display_end_grab_op (display, event->xkey.time); - return; - } - } - /* Do the normal keybindings */ - process_event (display->key_bindings, - display->n_key_bindings, - display, screen, window, event, keysym, - !all_keys_grabbed && window); -} - -static gboolean -process_mouse_move_resize_grab (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - KeySym keysym) -{ - /* don't care about releases, but eat them, don't end grab */ - if (event->type == KeyRelease) - return TRUE; - - if (keysym == XK_Escape) - { - /* End move or resize and restore to original state. If the - * window was a maximized window that had been "shaken loose" we - * need to remaximize it. In normal cases, we need to do a - * moveresize now to get the position back to the original. In - * wireframe mode, we just need to set grab_was_cancelled to tru - * to avoid avoid moveresizing to the position of the wireframe. - */ - if (window->shaken_loose) - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - else if (!display->grab_wireframe_active) - meta_window_move_resize (display->grab_window, - TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); - else - display->grab_was_cancelled = TRUE; - - /* End grab */ - return FALSE; - } - - return TRUE; -} - -static gboolean -process_keyboard_move_grab (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - KeySym keysym) -{ - gboolean handled; - int x, y; - int incr; - gboolean smart_snap; - - handled = FALSE; - - /* don't care about releases, but eat them, don't end grab */ - if (event->type == KeyRelease) - return TRUE; - - /* don't end grab on modifier key presses */ - if (is_modifier (display, event->xkey.keycode)) - return TRUE; - - if (display->grab_wireframe_active) - { - x = display->grab_wireframe_rect.x; - y = display->grab_wireframe_rect.y; - } - else - { - meta_window_get_position (window, &x, &y); - } - - smart_snap = (event->xkey.state & ShiftMask) != 0; - -#define SMALL_INCREMENT 1 -#define NORMAL_INCREMENT 10 - - if (smart_snap) - incr = 1; - else if (event->xkey.state & ControlMask) - incr = SMALL_INCREMENT; - else - incr = NORMAL_INCREMENT; - - if (keysym == XK_Escape) - { - /* End move and restore to original state. If the window was a - * maximized window that had been "shaken loose" we need to - * remaximize it. In normal cases, we need to do a moveresize - * now to get the position back to the original. In wireframe - * mode, we just need to set grab_was_cancelled to tru to avoid - * avoid moveresizing to the position of the wireframe. - */ - if (window->shaken_loose) - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - else if (!display->grab_wireframe_active) - meta_window_move_resize (display->grab_window, - TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); - else - display->grab_was_cancelled = TRUE; - } - - /* When moving by increments, we still snap to edges if the move - * to the edge is smaller than the increment. This is because - * Shift + arrow to snap is sort of a hidden feature. This way - * people using just arrows shouldn't get too frustrated. - */ - switch (keysym) - { - case XK_KP_Home: - case XK_KP_Prior: - case XK_Up: - case XK_KP_Up: - y -= incr; - handled = TRUE; - break; - case XK_KP_End: - case XK_KP_Next: - case XK_Down: - case XK_KP_Down: - y += incr; - handled = TRUE; - break; - } - - switch (keysym) - { - case XK_KP_Home: - case XK_KP_End: - case XK_Left: - case XK_KP_Left: - x -= incr; - handled = TRUE; - break; - case XK_KP_Prior: - case XK_KP_Next: - case XK_Right: - case XK_KP_Right: - x += incr; - handled = TRUE; - break; - } - - if (handled) - { - MetaRectangle old_rect; - meta_topic (META_DEBUG_KEYBINDINGS, - "Computed new window location %d,%d due to keypress\n", - x, y); - - if (display->grab_wireframe_active) - old_rect = display->grab_wireframe_rect; - else - meta_window_get_client_root_coords (window, &old_rect); - - meta_window_edge_resistance_for_move (window, - old_rect.x, - old_rect.y, - &x, - &y, - NULL, - smart_snap, - TRUE); - - if (display->grab_wireframe_active) - { - meta_window_update_wireframe (window, x, y, - display->grab_wireframe_rect.width, - display->grab_wireframe_rect.height); - } - else - { - meta_window_move (window, TRUE, x, y); - } - - meta_window_update_keyboard_move (window); - } - - return handled; -} - -static gboolean -process_keyboard_resize_grab_op_change (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - KeySym keysym) -{ - gboolean handled; - - handled = FALSE; - switch (display->grab_op) - { - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - switch (keysym) - { - case XK_Up: - case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; - handled = TRUE; - break; - case XK_Down: - case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - handled = TRUE; - break; - case XK_Left: - case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - handled = TRUE; - break; - case XK_Right: - case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_S: - switch (keysym) - { - case XK_Left: - case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - handled = TRUE; - break; - case XK_Right: - case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_N: - switch (keysym) - { - case XK_Left: - case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - handled = TRUE; - break; - case XK_Right: - case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_W: - switch (keysym) - { - case XK_Up: - case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; - handled = TRUE; - break; - case XK_Down: - case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_E: - switch (keysym) - { - case XK_Up: - case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; - handled = TRUE; - break; - case XK_Down: - case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - break; - - default: - g_assert_not_reached (); - break; - } - - if (handled) - { - meta_window_update_keyboard_resize (window, TRUE); - return TRUE; - } - - return FALSE; -} - -static gboolean -process_keyboard_resize_grab (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - KeySym keysym) -{ - gboolean handled; - int height_inc; - int width_inc; - int width, height; - gboolean smart_snap; - int gravity; - - handled = FALSE; - - /* don't care about releases, but eat them, don't end grab */ - if (event->type == KeyRelease) - return TRUE; - - /* don't end grab on modifier key presses */ - if (is_modifier (display, event->xkey.keycode)) - return TRUE; - - if (keysym == XK_Escape) - { - /* End resize and restore to original state. If not in - * wireframe mode, we need to do a moveresize now to get the - * position back to the original. If we are in wireframe mode, - * we need to avoid moveresizing to the position of the - * wireframe. - */ - if (!display->grab_wireframe_active) - meta_window_move_resize (display->grab_window, - TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); - else - display->grab_was_cancelled = TRUE; - - return FALSE; - } - - if (process_keyboard_resize_grab_op_change (display, screen, window, - event, keysym)) - return TRUE; - - if (display->grab_wireframe_active) - { - width = display->grab_wireframe_rect.width; - height = display->grab_wireframe_rect.height; - } - else - { - width = window->rect.width; - height = window->rect.height; - } - - gravity = meta_resize_gravity_from_grab_op (display->grab_op); - - smart_snap = (event->xkey.state & ShiftMask) != 0; - -#define SMALL_INCREMENT 1 -#define NORMAL_INCREMENT 10 - - if (smart_snap) - { - height_inc = 1; - width_inc = 1; - } - else if (event->xkey.state & ControlMask) - { - width_inc = SMALL_INCREMENT; - height_inc = SMALL_INCREMENT; - } - else - { - width_inc = NORMAL_INCREMENT; - height_inc = NORMAL_INCREMENT; - } - - /* If this is a resize increment window, make the amount we resize - * the window by match that amount (well, unless snap resizing...) - */ - if (window->size_hints.width_inc > 1) - width_inc = window->size_hints.width_inc; - if (window->size_hints.height_inc > 1) - height_inc = window->size_hints.height_inc; - - switch (keysym) - { - case XK_Up: - case XK_KP_Up: - switch (gravity) - { - case NorthGravity: - case NorthWestGravity: - case NorthEastGravity: - /* Move bottom edge up */ - height -= height_inc; - break; - - case SouthGravity: - case SouthWestGravity: - case SouthEastGravity: - /* Move top edge up */ - height += height_inc; - break; - - case EastGravity: - case WestGravity: - case CenterGravity: - g_assert_not_reached (); - break; - } - - handled = TRUE; - break; - - case XK_Down: - case XK_KP_Down: - switch (gravity) - { - case NorthGravity: - case NorthWestGravity: - case NorthEastGravity: - /* Move bottom edge down */ - height += height_inc; - break; - - case SouthGravity: - case SouthWestGravity: - case SouthEastGravity: - /* Move top edge down */ - height -= height_inc; - break; - - case EastGravity: - case WestGravity: - case CenterGravity: - g_assert_not_reached (); - break; - } - - handled = TRUE; - break; - - case XK_Left: - case XK_KP_Left: - switch (gravity) - { - case EastGravity: - case SouthEastGravity: - case NorthEastGravity: - /* Move left edge left */ - width += width_inc; - break; - - case WestGravity: - case SouthWestGravity: - case NorthWestGravity: - /* Move right edge left */ - width -= width_inc; - break; - - case NorthGravity: - case SouthGravity: - case CenterGravity: - g_assert_not_reached (); - break; - } - - handled = TRUE; - break; - - case XK_Right: - case XK_KP_Right: - switch (gravity) - { - case EastGravity: - case SouthEastGravity: - case NorthEastGravity: - /* Move left edge right */ - width -= width_inc; - break; - - case WestGravity: - case SouthWestGravity: - case NorthWestGravity: - /* Move right edge right */ - width += width_inc; - break; - - case NorthGravity: - case SouthGravity: - case CenterGravity: - g_assert_not_reached (); - break; - } - - handled = TRUE; - break; - - default: - break; - } - - /* fixup hack (just paranoia, not sure it's required) */ - if (height < 1) - height = 1; - if (width < 1) - width = 1; - - if (handled) - { - MetaRectangle old_rect; - meta_topic (META_DEBUG_KEYBINDINGS, - "Computed new window size due to keypress: " - "%dx%d, gravity %s\n", - width, height, meta_gravity_to_string (gravity)); - - if (display->grab_wireframe_active) - old_rect = display->grab_wireframe_rect; - else - old_rect = window->rect; /* Don't actually care about x,y */ - - /* Do any edge resistance/snapping */ - meta_window_edge_resistance_for_resize (window, - old_rect.width, - old_rect.height, - &width, - &height, - gravity, - NULL, - smart_snap, - TRUE); - - if (display->grab_wireframe_active) - { - MetaRectangle new_position; - meta_rectangle_resize_with_gravity (&display->grab_wireframe_rect, - &new_position, - gravity, - width, - height); - meta_window_update_wireframe (window, - new_position.x, - new_position.y, - new_position.width, - new_position.height); - } - else - { - /* We don't need to update unless the specified width and height - * are actually different from what we had before. - */ - if (window->rect.width != width || window->rect.height != height) - meta_window_resize_with_gravity (window, - TRUE, - width, - height, - gravity); - } - meta_window_update_keyboard_resize (window, FALSE); - } - - return handled; -} - -static gboolean -end_keyboard_grab (MetaDisplay *display, - unsigned int keycode) -{ -#ifdef HAVE_XKB - if (display->xkb_base_event_type > 0) - { - unsigned int primary_modifier; - XkbStateRec state; - - primary_modifier = get_primary_modifier (display, display->grab_mask); - - XkbGetState (display->xdisplay, XkbUseCoreKbd, &state); - - if (!(primary_modifier & state.mods)) - return TRUE; - } - else -#endif - { - if (keycode_is_primary_modifier (display, keycode, display->grab_mask)) - return TRUE; - } - - return FALSE; -} - -static gboolean -process_tab_grab (MetaDisplay *display, - MetaScreen *screen, - XEvent *event, - KeySym keysym) -{ - MetaKeyBindingAction action; - gboolean popup_not_showing; - gboolean backward; - gboolean key_used; - Window prev_xwindow; - MetaWindow *prev_window; - - if (screen != display->grab_screen) - return FALSE; - - g_return_val_if_fail (screen->tab_popup != NULL, FALSE); - - if (event->type == KeyRelease && - end_keyboard_grab (display, event->xkey.keycode)) - { - /* We're done, move to the new window. */ - Window target_xwindow; - MetaWindow *target_window; - - target_xwindow = - (Window) meta_ui_tab_popup_get_selected (screen->tab_popup); - target_window = - meta_display_lookup_x_window (display, target_xwindow); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Ending tab operation, primary modifier released\n"); - - if (target_window) - { - target_window->tab_unminimized = FALSE; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Activating target window\n"); - - meta_topic (META_DEBUG_FOCUS, "Activating %s due to tab popup " - "selection and turning mouse_mode off\n", - target_window->desc); - display->mouse_mode = FALSE; - meta_window_activate (target_window, event->xkey.time); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Ending grab early so we can focus the target window\n"); - meta_display_end_grab_op (display, event->xkey.time); - - return TRUE; /* we already ended the grab */ - } - - return FALSE; /* end grab */ - } - - /* don't care about other releases, but eat them, don't end grab */ - if (event->type == KeyRelease) - return TRUE; - - /* don't end grab on modifier key presses */ - if (is_modifier (display, event->xkey.keycode)) - return TRUE; - - prev_xwindow = (Window) meta_ui_tab_popup_get_selected (screen->tab_popup); - prev_window = meta_display_lookup_x_window (display, prev_xwindow); - action = display_get_keybinding_action (display, - keysym, - event->xkey.keycode, - display->grab_mask); - - /* Cancel when alt-Escape is pressed during using alt-Tab, and vice - * versa. - */ - switch (action) - { - case META_KEYBINDING_ACTION_CYCLE_PANELS: - case META_KEYBINDING_ACTION_CYCLE_WINDOWS: - case META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD: - case META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD: - /* CYCLE_* are traditionally Escape-based actions, - * and should cancel traditionally Tab-based ones. - */ - switch (display->grab_op) - { - case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: - case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: - /* carry on */ - break; - default: - return FALSE; - } - break; - case META_KEYBINDING_ACTION_SWITCH_PANELS: - case META_KEYBINDING_ACTION_SWITCH_WINDOWS: - case META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD: - case META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD: - /* SWITCH_* are traditionally Tab-based actions, - * and should cancel traditionally Escape-based ones. - */ - switch (display->grab_op) - { - case META_GRAB_OP_KEYBOARD_TABBING_NORMAL: - case META_GRAB_OP_KEYBOARD_TABBING_DOCK: - /* carry on */ - break; - default: - /* Also, we must re-lower and re-minimize whatever window - * we'd previously raised and unminimized. - */ - meta_stack_set_positions (screen->stack, - screen->display->grab_old_window_stacking); - if (prev_window && prev_window->tab_unminimized) - { - meta_window_minimize (prev_window); - prev_window->tab_unminimized = FALSE; - } - return FALSE; - } - break; - case META_KEYBINDING_ACTION_CYCLE_GROUP: - case META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD: - case META_KEYBINDING_ACTION_SWITCH_GROUP: - case META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD: - switch (display->grab_op) - { - case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: - case META_GRAB_OP_KEYBOARD_TABBING_GROUP: - /* carry on */ - break; - default: - return FALSE; - } - - break; - default: - break; - } - - /* !! TO HERE !! - * alt-f6 during alt-{Tab,Escape} does not end the grab - * but does change the grab op (and redraws the window, - * of course). - * See _{SWITCH,CYCLE}_GROUP.@@@ - */ - - popup_not_showing = FALSE; - key_used = FALSE; - backward = FALSE; - - switch (action) - { - case META_KEYBINDING_ACTION_CYCLE_PANELS: - case META_KEYBINDING_ACTION_CYCLE_WINDOWS: - case META_KEYBINDING_ACTION_CYCLE_GROUP: - popup_not_showing = TRUE; - key_used = TRUE; - break; - case META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD: - case META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD: - case META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD: - popup_not_showing = TRUE; - key_used = TRUE; - backward = TRUE; - break; - case META_KEYBINDING_ACTION_SWITCH_PANELS: - case META_KEYBINDING_ACTION_SWITCH_WINDOWS: - case META_KEYBINDING_ACTION_SWITCH_GROUP: - key_used = TRUE; - break; - case META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD: - case META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD: - case META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD: - key_used = TRUE; - backward = TRUE; - break; - default: - break; - } - - if (key_used) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Key pressed, moving tab focus in popup\n"); - - if (event->xkey.state & ShiftMask) - backward = !backward; - - if (backward) - meta_ui_tab_popup_backward (screen->tab_popup); - else - meta_ui_tab_popup_forward (screen->tab_popup); - - if (popup_not_showing) - { - /* We can't actually change window focus, due to the grab. - * but raise the window. - */ - Window target_xwindow; - MetaWindow *target_window; - - meta_stack_set_positions (screen->stack, - display->grab_old_window_stacking); - - target_xwindow = - (Window) meta_ui_tab_popup_get_selected (screen->tab_popup); - target_window = - meta_display_lookup_x_window (display, target_xwindow); - - if (prev_window && prev_window->tab_unminimized) - { - prev_window->tab_unminimized = FALSE; - meta_window_minimize (prev_window); - } - - if (target_window) - { - meta_window_raise (target_window); - target_window->tab_unminimized = target_window->minimized; - meta_window_unminimize (target_window); - } - } - } - else - { - /* end grab */ - meta_topic (META_DEBUG_KEYBINDINGS, - "Ending tabbing/cycling, uninteresting key pressed\n"); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Syncing to old stack positions.\n"); - meta_stack_set_positions (screen->stack, - screen->display->grab_old_window_stacking); - - if (prev_window && prev_window->tab_unminimized) - { - meta_window_minimize (prev_window); - prev_window->tab_unminimized = FALSE; - } - } - - return key_used; -} - -static void -handle_switch_to_workspace (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *event_window, - XEvent *event, - MetaKeyBinding *binding) -{ - gint which = binding->handler->data; - MetaWorkspace *workspace; - - if (which < 0) - { - /* Negative workspace numbers are directions with respect to the - * current workspace. While we could insta-switch here by setting - * workspace to the result of meta_workspace_get_neighbor(), when - * people request a workspace switch to the left or right via - * the keyboard, they actually want a tab popup. So we should - * go there instead. - * - * Note that we're the only caller of that function, so perhaps - * we should merge with it. - */ - handle_workspace_switch (display, screen, event_window, event, binding); - return; - } - - workspace = meta_screen_get_workspace_by_index (screen, which); - - if (workspace) - { - meta_workspace_activate (workspace, event->xkey.time); - } - else - { - /* We could offer to create it I suppose */ - } -} - -static void -error_on_command (int command_index, - const char *command, - const char *message, - int screen_number, - guint32 timestamp) -{ - if (command_index < 0) - meta_warning ("Error on terminal command \"%s\": %s\n", command, message); - else - meta_warning ("Error on command %d \"%s\": %s\n", - command_index, command, message); - - /* - metacity-dialog said: - - FIXME offer to change the value of the command's gconf key - */ - - if (command && strcmp(command, "")!=0) - { - char *text = g_strdup_printf ( - /* Displayed when a keybinding which is - * supposed to launch a program fails. - */ - _("There was an error running " - "<tt>%s</tt>:\n\n%s"), - command, - message); - - meta_show_dialog ("--error", - text, - NULL, - screen_number, - NULL, NULL); - - g_free (text); - - } - else - { - meta_show_dialog ("--error", - message, - NULL, - screen_number, - NULL, NULL); - } -} - -static void -set_display_setup_func (void *data) -{ - const char *screen_name = data; - char *full; - - full = g_strdup_printf ("DISPLAY=%s", screen_name); - - putenv (full); - - /* do not free full, because putenv is lame */ -} - -static gboolean -meta_spawn_command_line_async_on_screen (const gchar *command_line, - MetaScreen *screen, - GError **error) -{ - gboolean retval; - gchar **argv = NULL; - - g_return_val_if_fail (command_line != NULL, FALSE); - - if (!g_shell_parse_argv (command_line, - NULL, &argv, - error)) - return FALSE; - - retval = g_spawn_async (NULL, - argv, - NULL, - G_SPAWN_SEARCH_PATH, - set_display_setup_func, - screen->screen_name, - NULL, - error); - g_strfreev (argv); - - return retval; -} - - -static void -handle_run_command (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - gint which = binding->handler->data; - const char *command; - GError *err; - - command = meta_prefs_get_command (which); - - if (command == NULL) - { - char *s; - - meta_topic (META_DEBUG_KEYBINDINGS, - "No command %d to run in response to keybinding press\n", - which); - - s = g_strdup_printf (_("No command %d has been defined.\n"), - which + 1); - error_on_command (which, NULL, s, screen->number, event->xkey.time); - g_free (s); - - return; - } - - err = NULL; - if (!meta_spawn_command_line_async_on_screen (command, screen, &err)) - { - error_on_command (which, command, err->message, screen->number, event->xkey.time); - - g_error_free (err); - } -} - - -static void -handle_maximize_vertically (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->has_resize_func) - { - if (window->maximized_vertically) - meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL); - else - meta_window_maximize (window, META_MAXIMIZE_VERTICAL); - } -} - -static void -handle_maximize_horizontally (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->has_resize_func) - { - if (window->maximized_horizontally) - meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL); - else - meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL); - } -} - -/* Move a window to a corner; to_bottom/to_right are FALSE for the - * top or left edge, or TRUE for the bottom/right edge. xchange/ychange - * are FALSE if that dimension is not to be changed, TRUE otherwise. - * Together they describe which of the four corners, or four sides, - * is desired. - */ -static void -handle_move_to_corner_backend (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - gboolean xchange, - gboolean ychange, - gboolean to_right, - gboolean to_bottom) -{ - MetaRectangle work_area; - MetaRectangle outer; - int orig_x, orig_y; - int new_x, new_y; - int frame_width, frame_height; - - meta_window_get_work_area_all_xineramas (window, &work_area); - meta_window_get_outer_rect (window, &outer); - meta_window_get_position (window, &orig_x, &orig_y); - - frame_width = (window->frame ? window->frame->child_x : 0); - frame_height = (window->frame ? window->frame->child_y : 0); - - if (xchange) { - new_x = work_area.x + (to_right ? - (work_area.width + frame_width) - outer.width : - 0); - } else { - new_x = orig_x; - } - - if (ychange) { - new_y = work_area.y + (to_bottom ? - (work_area.height + frame_height) - outer.height : - 0); - } else { - new_y = orig_y; - } - - meta_window_move_resize (window, - FALSE, - new_x, - new_y, - window->rect.width, - window->rect.height); -} - -static void -handle_move_to_corner_nw (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, FALSE); -} - -static void -handle_move_to_corner_ne (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, FALSE); -} - -static void -handle_move_to_corner_sw (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, TRUE); -} - -static void -handle_move_to_corner_se (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, TRUE); -} - -static void -handle_move_to_side_n (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, FALSE); -} - -static void -handle_move_to_side_s (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, TRUE); -} - -static void -handle_move_to_side_e (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, TRUE, FALSE); -} - -static void -handle_move_to_side_w (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, FALSE, FALSE); -} - -static void -handle_move_to_center (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - MetaRectangle work_area; - MetaRectangle outer; - int orig_x, orig_y; - int frame_width, frame_height; - - meta_window_get_work_area_all_xineramas (window, &work_area); - meta_window_get_outer_rect (window, &outer); - meta_window_get_position (window, &orig_x, &orig_y); - - frame_width = (window->frame ? window->frame->child_x : 0); - frame_height = (window->frame ? window->frame->child_y : 0); - - meta_window_move_resize (window, - TRUE, - work_area.x + (work_area.width +frame_width -outer.width )/2, - work_area.y + (work_area.height+frame_height-outer.height)/2, - window->rect.width, - window->rect.height); -} - -static gboolean -process_workspace_switch_grab (MetaDisplay *display, - MetaScreen *screen, - XEvent *event, - KeySym keysym) -{ - MetaWorkspace *workspace; - - if (screen != display->grab_screen) - return FALSE; - - g_return_val_if_fail (screen->tab_popup != NULL, FALSE); - - if (event->type == KeyRelease && - end_keyboard_grab (display, event->xkey.keycode)) - { - /* We're done, move to the new workspace. */ - MetaWorkspace *target_workspace; - - target_workspace = - (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->tab_popup); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Ending workspace tab operation, primary modifier released\n"); - - if (target_workspace == screen->active_workspace) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Ending grab so we can focus on the target workspace\n"); - meta_display_end_grab_op (display, event->xkey.time); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Focusing default window on target workspace\n"); - - meta_workspace_focus_default_window (target_workspace, - NULL, - event->xkey.time); - - return TRUE; /* we already ended the grab */ - } - - /* Workspace switching should have already occurred on KeyPress */ - meta_warning ("target_workspace != active_workspace. Some other event must have occurred.\n"); - - return FALSE; /* end grab */ - } - - /* don't care about other releases, but eat them, don't end grab */ - if (event->type == KeyRelease) - return TRUE; - - /* don't end grab on modifier key presses */ - if (is_modifier (display, event->xkey.keycode)) - return TRUE; - - /* select the next workspace in the tabpopup */ - workspace = - (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->tab_popup); - - if (workspace) - { - MetaWorkspace *target_workspace; - MetaKeyBindingAction action; - - action = display_get_keybinding_action (display, - keysym, - event->xkey.keycode, - display->grab_mask); - - switch (action) - { - case META_KEYBINDING_ACTION_WORKSPACE_UP: - target_workspace = meta_workspace_get_neighbor (workspace, - META_MOTION_UP); - break; - - case META_KEYBINDING_ACTION_WORKSPACE_DOWN: - target_workspace = meta_workspace_get_neighbor (workspace, - META_MOTION_DOWN); - break; - - case META_KEYBINDING_ACTION_WORKSPACE_LEFT: - target_workspace = meta_workspace_get_neighbor (workspace, - META_MOTION_LEFT); - break; - - case META_KEYBINDING_ACTION_WORKSPACE_RIGHT: - target_workspace = meta_workspace_get_neighbor (workspace, - META_MOTION_RIGHT); - break; - - default: - target_workspace = NULL; - break; - } - - if (target_workspace) - { - meta_ui_tab_popup_select (screen->tab_popup, - (MetaTabEntryKey) target_workspace); - meta_topic (META_DEBUG_KEYBINDINGS, - "Tab key pressed, moving tab focus in popup\n"); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Activating target workspace\n"); - - meta_workspace_activate (target_workspace, event->xkey.time); - - return TRUE; /* we already ended the grab */ - } - } - - /* end grab */ - meta_topic (META_DEBUG_KEYBINDINGS, - "Ending workspace tabbing & focusing default window; uninteresting key pressed\n"); - workspace = - (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->tab_popup); - meta_workspace_focus_default_window (workspace, NULL, event->xkey.time); - return FALSE; -} - -static void -handle_show_desktop (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (screen->active_workspace->showing_desktop) - { - meta_screen_unshow_desktop (screen); - meta_workspace_focus_default_window (screen->active_workspace, - NULL, - event->xkey.time); - } - else - meta_screen_show_desktop (screen, event->xkey.time); -} - -static void -handle_panel (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - MetaKeyBindingAction action = binding->handler->data; - Atom action_atom; - XClientMessageEvent ev; - - action_atom = None; - switch (action) - { - /* FIXME: The numbers are wrong */ - case META_KEYBINDING_ACTION_PANEL_MAIN_MENU: - action_atom = display->atom__GNOME_PANEL_ACTION_MAIN_MENU; - break; - case META_KEYBINDING_ACTION_PANEL_RUN_DIALOG: - action_atom = display->atom__GNOME_PANEL_ACTION_RUN_DIALOG; - break; - default: - return; - } - - ev.type = ClientMessage; - ev.window = screen->xroot; - ev.message_type = display->atom__GNOME_PANEL_ACTION; - ev.format = 32; - ev.data.l[0] = action_atom; - ev.data.l[1] = event->xkey.time; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Sending panel message with timestamp %lu, and turning mouse_mode " - "off due to keybinding press\n", event->xkey.time); - display->mouse_mode = FALSE; - - meta_error_trap_push (display); - - /* Release the grab for the panel before sending the event */ - XUngrabKeyboard (display->xdisplay, event->xkey.time); - - XSendEvent (display->xdisplay, - screen->xroot, - False, - StructureNotifyMask, - (XEvent*) &ev); - - meta_error_trap_pop (display, FALSE); -} - -static void -handle_activate_window_menu (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *event_window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (display->focus_window) - { - int x, y; - - meta_window_get_position (display->focus_window, - &x, &y); - - if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - x += display->focus_window->rect.width; - - meta_window_show_menu (display->focus_window, - x, y, - 0, - event->xkey.time); - } -} - -static MetaGrabOp -tab_op_from_tab_type (MetaTabList type) -{ - switch (type) - { - case META_TAB_LIST_NORMAL: - return META_GRAB_OP_KEYBOARD_TABBING_NORMAL; - case META_TAB_LIST_DOCKS: - return META_GRAB_OP_KEYBOARD_TABBING_DOCK; - case META_TAB_LIST_GROUP: - return META_GRAB_OP_KEYBOARD_TABBING_GROUP; - } - - g_assert_not_reached (); - - return 0; -} - -static MetaGrabOp -cycle_op_from_tab_type (MetaTabList type) -{ - switch (type) - { - case META_TAB_LIST_NORMAL: - return META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL; - case META_TAB_LIST_DOCKS: - return META_GRAB_OP_KEYBOARD_ESCAPING_DOCK; - case META_TAB_LIST_GROUP: - return META_GRAB_OP_KEYBOARD_ESCAPING_GROUP; - } - - g_assert_not_reached (); - - return 0; -} - -static void -do_choose_window (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *event_window, - XEvent *event, - MetaKeyBinding *binding, - gboolean backward, - gboolean show_popup) -{ - MetaTabList type = binding->handler->data; - MetaWindow *initial_selection; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Tab list = %u show_popup = %d\n", type, show_popup); - - /* reverse direction if shift is down */ - if (event->xkey.state & ShiftMask) - backward = !backward; - - initial_selection = meta_display_get_tab_next (display, - type, - screen, - screen->active_workspace, - NULL, - backward); - - /* Note that focus_window may not be in the tab chain, but it's OK */ - if (initial_selection == NULL) - initial_selection = meta_display_get_tab_current (display, - type, screen, - screen->active_workspace); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Initially selecting window %s\n", - initial_selection ? initial_selection->desc : "(none)"); - - if (initial_selection != NULL) - { - if (binding->mask == 0) - { - /* If no modifiers, we can't do the "hold down modifier to keep - * moving" thing, so we just instaswitch by one window. - */ - meta_topic (META_DEBUG_FOCUS, - "Activating %s and turning off mouse_mode due to " - "switch/cycle windows with no modifiers\n", - initial_selection->desc); - display->mouse_mode = FALSE; - meta_window_activate (initial_selection, event->xkey.time); - } - else if (meta_display_begin_grab_op (display, - screen, - NULL, - show_popup ? - tab_op_from_tab_type (type) : - cycle_op_from_tab_type (type), - FALSE, - FALSE, - 0, - binding->mask, - event->xkey.time, - 0, 0)) - { - if (!primary_modifier_still_pressed (display, - binding->mask)) - { - /* This handles a race where modifier might be released - * before we establish the grab. must end grab - * prior to trying to focus a window. - */ - meta_topic (META_DEBUG_FOCUS, - "Ending grab, activating %s, and turning off " - "mouse_mode due to switch/cycle windows where " - "modifier was released prior to grab\n", - initial_selection->desc); - meta_display_end_grab_op (display, event->xkey.time); - display->mouse_mode = FALSE; - meta_window_activate (initial_selection, event->xkey.time); - } - else - { - meta_ui_tab_popup_select (screen->tab_popup, - (MetaTabEntryKey) initial_selection->xwindow); - - if (show_popup) - meta_ui_tab_popup_set_showing (screen->tab_popup, - TRUE); - else - { - meta_window_raise (initial_selection); - initial_selection->tab_unminimized = - initial_selection->minimized; - meta_window_unminimize (initial_selection); - } - } - } - } -} - -static void -handle_switch (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *event_window, - XEvent *event, - MetaKeyBinding *binding) -{ - gint backwards = binding->handler->flags & BINDING_IS_REVERSED; - - do_choose_window (display, screen, event_window, event, binding, - backwards, TRUE); -} - -static void -handle_cycle (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *event_window, - XEvent *event, - MetaKeyBinding *binding) -{ - gint backwards = binding->handler->flags & BINDING_IS_REVERSED; - - do_choose_window (display, screen, event_window, event, binding, - backwards, FALSE); -} - - -static void -handle_toggle_fullscreen (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->fullscreen) - meta_window_unmake_fullscreen (window); - else if (window->has_fullscreen_func) - meta_window_make_fullscreen (window); -} - -static void -handle_toggle_above (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->wm_state_above) - meta_window_unmake_above (window); - else - meta_window_make_above (window); -} - -static void -handle_toggle_maximized (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (META_WINDOW_MAXIMIZED (window)) - meta_window_unmaximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - else if (window->has_maximize_func) - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); -} - -static void -handle_maximize (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->has_maximize_func) - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); -} - -static void -handle_unmaximize (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->maximized_vertically || window->maximized_horizontally) - meta_window_unmaximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); -} - -static void -handle_toggle_shaded (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->shaded) - meta_window_unshade (window, event->xkey.time); - else if (window->has_shade_func) - meta_window_shade (window, event->xkey.time); -} - -static void -handle_close (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->has_close_func) - meta_window_delete (window, event->xkey.time); -} - -static void -handle_minimize (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->has_minimize_func) - meta_window_minimize (window); -} - -static void -handle_begin_move (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->has_move_func) - { - meta_window_begin_grab_op (window, - META_GRAB_OP_KEYBOARD_MOVING, - FALSE, - event->xkey.time); - } -} - -static void -handle_begin_resize (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->has_resize_func) - { - meta_window_begin_grab_op (window, - META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, - FALSE, - event->xkey.time); - } -} - -static void -handle_toggle_on_all_workspaces (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - if (window->on_all_workspaces) - meta_window_unstick (window); - else - meta_window_stick (window); -} - -static void -handle_move_to_workspace (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - gint which = binding->handler->data; - gboolean flip = (which < 0); - MetaWorkspace *workspace; - - /* If which is zero or positive, it's a workspace number, and the window - * should move to the workspace with that number. - * - * However, if it's negative, it's a direction with respect to the current - * position; it's expressed as a member of the MetaMotionDirection enum, - * all of whose members are negative. Such a change is called a flip. - */ - - if (window->always_sticky) - return; - - workspace = NULL; - if (flip) - { - workspace = meta_workspace_get_neighbor (screen->active_workspace, - which); - } - else - { - workspace = meta_screen_get_workspace_by_index (screen, which); - } - - if (workspace) - { - /* Activate second, so the window is never unmapped */ - meta_window_change_workspace (window, workspace); - if (flip) - { - meta_topic (META_DEBUG_FOCUS, - "Resetting mouse_mode to FALSE due to " - "handle_move_to_workspace() call with flip set.\n"); - workspace->screen->display->mouse_mode = FALSE; - meta_workspace_activate_with_focus (workspace, - window, - event->xkey.time); - } - } - else - { - /* We could offer to create it I suppose */ - } -} - -static void -handle_raise_or_lower (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - /* Get window at pointer */ - - MetaWindow *above = NULL; - - /* Check if top */ - if (meta_stack_get_top (window->screen->stack) == window) - { - meta_window_lower (window); - return; - } - - /* else check if windows in same layer are intersecting it */ - - above = meta_stack_get_above (window->screen->stack, window, TRUE); - - while (above) - { - MetaRectangle tmp, win_rect, above_rect; - - if (above->mapped) - { - meta_window_get_outer_rect (window, &win_rect); - meta_window_get_outer_rect (above, &above_rect); - - /* Check if obscured */ - if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp)) - { - meta_window_raise (window); - return; - } - } - - above = meta_stack_get_above (window->screen->stack, above, TRUE); - } - - /* window is not obscured */ - meta_window_lower (window); -} - -static void -handle_raise (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - meta_window_raise (window); -} - -static void -handle_lower (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - meta_window_lower (window); -} - -static void -handle_workspace_switch (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - gint motion = binding->handler->data; - unsigned int grab_mask; - - g_assert (motion < 0); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Starting tab between workspaces, showing popup\n"); - - /* FIXME should we use binding->mask ? */ - grab_mask = event->xkey.state & ~(display->ignored_modifier_mask); - - if (meta_display_begin_grab_op (display, - screen, - NULL, - META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING, - FALSE, - FALSE, - 0, - grab_mask, - event->xkey.time, - 0, 0)) - { - MetaWorkspace *next; - gboolean grabbed_before_release; - - next = meta_workspace_get_neighbor (screen->active_workspace, motion); - g_assert (next); - - grabbed_before_release = primary_modifier_still_pressed (display, grab_mask); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Activating target workspace\n"); - - if (!grabbed_before_release) - { - /* end the grab right away, modifier possibly released - * before we could establish the grab and receive the - * release event. Must end grab before we can switch - * spaces. - */ - meta_display_end_grab_op (display, event->xkey.time); - } - - meta_workspace_activate (next, event->xkey.time); - - if (grabbed_before_release) - { - meta_ui_tab_popup_select (screen->tab_popup, (MetaTabEntryKey) next); - - /* only after selecting proper space */ - meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE); - } - } -} - -static void -handle_set_spew_mark (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - meta_verbose ("-- MARK MARK MARK MARK --\n"); -} - -void -meta_set_keybindings_disabled (gboolean setting) -{ - all_bindings_disabled = setting; - meta_topic (META_DEBUG_KEYBINDINGS, - "Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled"); -} - -static void -handle_run_terminal (MetaDisplay *display, - MetaScreen *screen, - MetaWindow *window, - XEvent *event, - MetaKeyBinding *binding) -{ - const char *command; - GError *err; - - command = meta_prefs_get_terminal_command (); - - if (command == NULL) - { - char *s; - - meta_topic (META_DEBUG_KEYBINDINGS, - "No terminal command to run in response to " - "keybinding press\n"); - - s = g_strdup_printf (_("No terminal command has been defined.\n")); - error_on_command (-1, NULL, s, screen->number, event->xkey.time); - g_free (s); - - return; - } - - err = NULL; - if (!meta_spawn_command_line_async_on_screen (command, screen, &err)) - { - error_on_command (-1, command, err->message, screen->number, - event->xkey.time); - - g_error_free (err); - } -} diff --git a/src/core/keybindings.h b/src/core/keybindings.h deleted file mode 100644 index 618520b4..00000000 --- a/src/core/keybindings.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file keybindings.h Grab and ungrab keys, and process the key events - * - * Performs global X grabs on the keys we need to be told about, like - * the one to close a window. It also deals with incoming key events. - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_KEYBINDINGS_H -#define META_KEYBINDINGS_H - -#include "display-private.h" -#include "window.h" - -void meta_display_init_keys (MetaDisplay *display); -void meta_display_shutdown_keys (MetaDisplay *display); -void meta_screen_grab_keys (MetaScreen *screen); -void meta_screen_ungrab_keys (MetaScreen *screen); -gboolean meta_screen_grab_all_keys (MetaScreen *screen, - guint32 timestamp); -void meta_screen_ungrab_all_keys (MetaScreen *screen, - guint32 timestamp); -void meta_window_grab_keys (MetaWindow *window); -void meta_window_ungrab_keys (MetaWindow *window); -gboolean meta_window_grab_all_keys (MetaWindow *window, - guint32 timestamp); -void meta_window_ungrab_all_keys (MetaWindow *window, - guint32 timestamp); -void meta_display_process_key_event (MetaDisplay *display, - MetaWindow *window, - XEvent *event); -void meta_set_keybindings_disabled (gboolean setting); -void meta_display_process_mapping_event (MetaDisplay *display, - XEvent *event); - -#endif - - - - diff --git a/src/core/main.c b/src/core/main.c deleted file mode 100644 index 19c2dd38..00000000 --- a/src/core/main.c +++ /dev/null @@ -1,620 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity main() */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** - * \file - * Program startup. - * Functions which parse the command-line arguments, create the display, - * kick everything off and then close down Metacity when it's time to go. - */ - -/** - * \mainpage - * Metacity - a boring window manager for the adult in you - * - * Many window managers are like Marshmallow Froot Loops; Metacity - * is like Cheerios. - * - * The best way to get a handle on how the whole system fits together - * is discussed in doc/code-overview.txt; if you're looking for functions - * to investigate, read main(), meta_display_open(), and event_callback(). - */ - -#define _GNU_SOURCE -#define _SVID_SOURCE /* for putenv() and some signal-related functions */ - -#include <config.h> -#include "main.h" -#include "util.h" -#include "display-private.h" -#include "errors.h" -#include "ui.h" -#include "session.h" -#include "prefs.h" - -#include <glib-object.h> - -#include <stdlib.h> -#include <sys/types.h> -#include <stdio.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> -#include <locale.h> -#include <time.h> - -/** - * The exit code we'll return to our parent process when we eventually die. - */ -static MetaExitCode meta_exit_code = META_EXIT_SUCCESS; - -/** - * Handle on the main loop, so that we have an easy way of shutting Metacity - * down. - */ -static GMainLoop *meta_main_loop = NULL; - -/** - * If set, Metacity will spawn an identical copy of itself immediately - * before quitting. - */ -static gboolean meta_restart_after_quit = FALSE; - -static void prefs_changed_callback (MetaPreference pref, - gpointer data); - -/** - * Prints log messages. If Metacity was compiled with backtrace support, - * also prints a backtrace (see meta_print_backtrace()). - * - * \param log_domain the domain the error occurred in (we ignore this) - * \param log_level the log level so that we can filter out less - * important messages - * \param message the message to log - * \param user_data arbitrary data (we ignore this) - */ -static void -log_handler (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) -{ - meta_warning ("Log level %d: %s\n", log_level, message); - meta_print_backtrace (); -} - -/** - * Prints the version notice. This is shown when Metacity is called - * with the --version switch. - */ -static void -version (void) -{ - g_print (_("metacity %s\n" - "Copyright (C) 2001-2008 Havoc Pennington, Red Hat, Inc., and others\n" - "This is free software; see the source for copying conditions.\n" - "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"), - VERSION); - exit (0); -} - -/** - * Prints a list of which configure script options were used to - * build this copy of Metacity. This is actually always called - * on startup, but it's all no-op unless we're in verbose mode - * (see meta_set_verbose). - */ -static void -meta_print_compilation_info (void) -{ -#ifdef HAVE_SHAPE - meta_verbose ("Compiled with shape extension\n"); -#else - meta_verbose ("Compiled without shape extension\n"); -#endif -#ifdef HAVE_XINERAMA - meta_topic (META_DEBUG_XINERAMA, "Compiled with Xinerama extension\n"); -#else - meta_topic (META_DEBUG_XINERAMA, "Compiled without Xinerama extension\n"); -#endif -#ifdef HAVE_XFREE_XINERAMA - meta_topic (META_DEBUG_XINERAMA, " (using XFree86 Xinerama)\n"); -#else - meta_topic (META_DEBUG_XINERAMA, " (not using XFree86 Xinerama)\n"); -#endif -#ifdef HAVE_SOLARIS_XINERAMA - meta_topic (META_DEBUG_XINERAMA, " (using Solaris Xinerama)\n"); -#else - meta_topic (META_DEBUG_XINERAMA, " (not using Solaris Xinerama)\n"); -#endif -#ifdef HAVE_XSYNC - meta_verbose ("Compiled with sync extension\n"); -#else - meta_verbose ("Compiled without sync extension\n"); -#endif -#ifdef HAVE_RANDR - meta_verbose ("Compiled with randr extension\n"); -#else - meta_verbose ("Compiled without randr extension\n"); -#endif -#ifdef HAVE_STARTUP_NOTIFICATION - meta_verbose ("Compiled with startup notification\n"); -#else - meta_verbose ("Compiled without startup notification\n"); -#endif -#ifdef HAVE_COMPOSITE_EXTENSIONS - meta_verbose ("Compiled with composite extensions\n"); -#else - meta_verbose ("Compiled without composite extensions\n"); -#endif -} - -/** - * Prints the version number, the current timestamp (not the - * build date), the locale, the character encoding, and a list - * of configure script options that were used to build this - * copy of Metacity. This is actually always called - * on startup, but it's all no-op unless we're in verbose mode - * (see meta_set_verbose). - */ -static void -meta_print_self_identity (void) -{ - char buf[256]; - GDate d; - const char *charset; - - /* Version and current date. */ - g_date_clear (&d, 1); - g_date_set_time_t (&d, time (NULL)); - g_date_strftime (buf, sizeof (buf), "%x", &d); - meta_verbose ("Metacity version %s running on %s\n", - VERSION, buf); - - /* Locale and encoding. */ - g_get_charset (&charset); - meta_verbose ("Running in locale \"%s\" with encoding \"%s\"\n", - setlocale (LC_ALL, NULL), charset); - - /* Compilation settings. */ - meta_print_compilation_info (); -} - -/** - * The set of possible options that can be set on Metacity's - * command line. This type exists so that meta_parse_options() can - * write to an instance of it. - */ -typedef struct -{ - gchar *save_file; - gchar *display_name; - gchar *client_id; - gboolean replace_wm; - gboolean disable_sm; - gboolean print_version; - gboolean sync; - gboolean composite; - gboolean no_composite; -} MetaArguments; - -#ifdef HAVE_COMPOSITE_EXTENSIONS -#define COMPOSITE_OPTS_FLAGS 0 -#else /* HAVE_COMPOSITE_EXTENSIONS */ -/* No compositor, so don't show the arguments in --help */ -#define COMPOSITE_OPTS_FLAGS G_OPTION_FLAG_HIDDEN -#endif /* HAVE_COMPOSITE_EXTENSIONS */ - -/** - * Parses argc and argv and returns the - * arguments that Metacity understands in meta_args. - * - * The strange call signature has to be written like it is so - * that g_option_context_parse() gets a chance to modify argc and - * argv. - * - * \param argc Pointer to the number of arguments Metacity was given - * \param argv Pointer to the array of arguments Metacity was given - * \param meta_args The result of parsing the arguments. - **/ -static void -meta_parse_options (int *argc, char ***argv, - MetaArguments *meta_args) -{ - MetaArguments my_args = {NULL, NULL, NULL, - FALSE, FALSE, FALSE, FALSE, FALSE}; - GOptionEntry options[] = { - { - "sm-disable", 0, 0, G_OPTION_ARG_NONE, - &my_args.disable_sm, - N_("Disable connection to session manager"), - NULL - }, - { - "replace", 0, 0, G_OPTION_ARG_NONE, - &my_args.replace_wm, - N_("Replace the running window manager with Metacity"), - NULL - }, - { - "sm-client-id", 0, 0, G_OPTION_ARG_STRING, - &my_args.client_id, - N_("Specify session management ID"), - "ID" - }, - { - "display", 'd', 0, G_OPTION_ARG_STRING, - &my_args.display_name, N_("X Display to use"), - "DISPLAY" - }, - { - "sm-save-file", 0, 0, G_OPTION_ARG_FILENAME, - &my_args.save_file, - N_("Initialize session from savefile"), - "FILE" - }, - { - "version", 0, 0, G_OPTION_ARG_NONE, - &my_args.print_version, - N_("Print version"), - NULL - }, - { - "sync", 0, 0, G_OPTION_ARG_NONE, - &my_args.sync, - N_("Make X calls synchronous"), - NULL - }, - { - "composite", 'c', COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE, - &my_args.composite, - N_("Turn compositing on"), - NULL - }, - { - "no-composite", 0, COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE, - &my_args.no_composite, - N_("Turn compositing off"), - NULL - }, - {NULL} - }; - GOptionContext *ctx; - GError *error = NULL; - - ctx = g_option_context_new (NULL); - g_option_context_add_main_entries (ctx, options, "metacity"); - if (!g_option_context_parse (ctx, argc, argv, &error)) - { - g_print ("metacity: %s\n", error->message); - exit(1); - } - g_option_context_free (ctx); - /* Return the parsed options through the meta_args param. */ - *meta_args = my_args; -} - -/** - * Selects which display Metacity should use. It first tries to use - * display_name as the display. If display_name is NULL then - * try to use the environment variable METACITY_DISPLAY. If that - * also is NULL, use the default - :0.0 - */ -static void -meta_select_display (gchar *display_name) -{ - gchar *envVar = ""; - if (display_name) - envVar = g_strconcat ("DISPLAY=", display_name, NULL); - else if (g_getenv ("METACITY_DISPLAY")) - envVar = g_strconcat ("DISPLAY=", - g_getenv ("METACITY_DISPLAY"), NULL); - /* DO NOT FREE envVar, putenv() sucks */ - putenv (envVar); -} - -static void -meta_finalize (void) -{ - meta_display_close (meta_get_display (), - CurrentTime); /* I doubt correct timestamps matter here */ - - meta_session_shutdown (); -} - -static void -sigterm_handler (int signum) -{ - meta_finalize (); - - exit (meta_exit_code); -} - -/** - * This is where the story begins. It parses commandline options and - * environment variables, sets up the screen, hands control off to - * GTK, and cleans up afterwards. - * - * \param argc Number of arguments (as usual) - * \param argv Array of arguments (as usual) - * - * \bug It's a bit long. It would be good to split it out into separate - * functions. - */ -int -main (int argc, char **argv) -{ - struct sigaction act; - sigset_t empty_mask; - MetaArguments meta_args; - const gchar *log_domains[] = { - NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib", - "Pango", "GLib-GObject", "GThread" - }; - guint i; - - if (!g_thread_supported ()) - g_thread_init (NULL); - - if (setlocale (LC_ALL, "") == NULL) - meta_warning ("Locale not understood by C library, internationalization will not work\n"); - - sigemptyset (&empty_mask); - act.sa_handler = SIG_IGN; - act.sa_mask = empty_mask; - act.sa_flags = 0; - if (sigaction (SIGPIPE, &act, NULL) < 0) - g_printerr ("Failed to register SIGPIPE handler: %s\n", - g_strerror (errno)); -#ifdef SIGXFSZ - if (sigaction (SIGXFSZ, &act, NULL) < 0) - g_printerr ("Failed to register SIGXFSZ handler: %s\n", - g_strerror (errno)); -#endif - - act.sa_handler = &sigterm_handler; - if (sigaction (SIGTERM, &act, NULL) < 0) - g_printerr ("Failed to register SIGTERM handler: %s\n", - g_strerror (errno)); - - if (g_getenv ("METACITY_VERBOSE")) - meta_set_verbose (TRUE); - if (g_getenv ("METACITY_DEBUG")) - meta_set_debugging (TRUE); - - if (g_get_home_dir ()) - if (chdir (g_get_home_dir ()) < 0) - meta_warning ("Could not change to home directory %s.\n", - g_get_home_dir ()); - - meta_print_self_identity (); - - bindtextdomain (GETTEXT_PACKAGE, METACITY_LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - /* Parse command line arguments.*/ - meta_parse_options (&argc, &argv, &meta_args); - - meta_set_syncing (meta_args.sync || (g_getenv ("METACITY_SYNC") != NULL)); - - if (meta_args.print_version) - version (); - - meta_select_display (meta_args.display_name); - - if (meta_args.replace_wm) - meta_set_replace_current_wm (TRUE); - - if (meta_args.save_file && meta_args.client_id) - meta_fatal ("Can't specify both SM save file and SM client id\n"); - - meta_main_loop = g_main_loop_new (NULL, FALSE); - - g_type_init (); - - meta_ui_init (&argc, &argv); - - /* must be after UI init so we can override GDK handlers */ - meta_errors_init (); - - /* Load prefs */ - meta_prefs_init (); - meta_prefs_add_listener (prefs_changed_callback, NULL); - - -#if 1 - - for (i=0; i<G_N_ELEMENTS(log_domains); i++) - g_log_set_handler (log_domains[i], - G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, - log_handler, NULL); - -#endif - - if (g_getenv ("METACITY_G_FATAL_WARNINGS") != NULL) - g_log_set_always_fatal (G_LOG_LEVEL_MASK); - - meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE); - - /* Try to find some theme that'll work if the theme preference - * doesn't exist. First try Simple (the default theme) then just - * try anything in the themes directory. - */ - if (!meta_ui_have_a_theme ()) - meta_ui_set_current_theme ("Simple", FALSE); - - if (!meta_ui_have_a_theme ()) - { - const char *dir_entry = NULL; - GError *err = NULL; - GDir *themes_dir = NULL; - - if (!(themes_dir = g_dir_open (METACITY_DATADIR"/themes", 0, &err))) - { - meta_fatal (_("Failed to scan themes directory: %s\n"), err->message); - g_error_free (err); - } - else - { - while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) && - (!meta_ui_have_a_theme ())) - { - meta_ui_set_current_theme (dir_entry, FALSE); - } - - g_dir_close (themes_dir); - } - } - - if (!meta_ui_have_a_theme ()) - meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n"), - METACITY_DATADIR"/themes"); - - /* Connect to SM as late as possible - but before managing display, - * or we might try to manage a window before we have the session - * info - */ - if (!meta_args.disable_sm) - { - if (meta_args.client_id == NULL) - { - const gchar *desktop_autostart_id; - - desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID"); - - if (desktop_autostart_id != NULL) - meta_args.client_id = g_strdup (desktop_autostart_id); - } - - /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to - * use the same client id. */ - g_unsetenv ("DESKTOP_AUTOSTART_ID"); - - meta_session_init (meta_args.client_id, meta_args.save_file); - } - /* Free memory possibly allocated by the argument parsing which are - * no longer needed. - */ - g_free (meta_args.save_file); - g_free (meta_args.display_name); - g_free (meta_args.client_id); - - if (meta_args.composite || meta_args.no_composite) - meta_prefs_set_compositing_manager (meta_args.composite); - - if (!meta_display_open ()) - meta_exit (META_EXIT_ERROR); - - g_main_loop_run (meta_main_loop); - - meta_finalize (); - - if (meta_restart_after_quit) - { - GError *err; - - err = NULL; - if (!g_spawn_async (NULL, - argv, - NULL, - G_SPAWN_SEARCH_PATH, - NULL, - NULL, - NULL, - &err)) - { - meta_fatal (_("Failed to restart: %s\n"), - err->message); - g_error_free (err); /* not reached anyhow */ - meta_exit_code = META_EXIT_ERROR; - } - } - - return meta_exit_code; -} - -/** - * Stops Metacity. This tells the event loop to stop processing; it is rather - * dangerous to use this rather than meta_restart() because this will leave - * the user with no window manager. We generally do this only if, for example, - * the session manager asks us to; we assume the session manager knows what - * it's talking about. - * - * \param code The success or failure code to return to the calling process. - */ -void -meta_quit (MetaExitCode code) -{ - meta_exit_code = code; - - if (g_main_loop_is_running (meta_main_loop)) - g_main_loop_quit (meta_main_loop); -} - -/** - * Restarts Metacity. In practice, this tells the event loop to stop - * processing, having first set the meta_restart_after_quit flag which - * tells Metacity to spawn an identical copy of itself before quitting. - * This happens on receipt of a _METACITY_RESTART_MESSAGE client event. - */ -void -meta_restart (void) -{ - meta_restart_after_quit = TRUE; - meta_quit (META_EXIT_SUCCESS); -} - -/** - * Called on pref changes. (One of several functions of its kind and purpose.) - * - * \bug Why are these particular prefs handled in main.c and not others? - * Should they be? - * - * \param pref Which preference has changed - * \param data Arbitrary data (which we ignore) - */ -static void -prefs_changed_callback (MetaPreference pref, - gpointer data) -{ - switch (pref) - { - case META_PREF_THEME: - meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE); - meta_display_retheme_all (); - break; - - case META_PREF_CURSOR_THEME: - case META_PREF_CURSOR_SIZE: - meta_display_set_cursor_theme (meta_prefs_get_cursor_theme (), - meta_prefs_get_cursor_size ()); - break; - default: - /* handled elsewhere or otherwise */ - break; - } -} diff --git a/src/core/metacity-Xatomtype.h b/src/core/metacity-Xatomtype.h deleted file mode 100644 index d14d3ab7..00000000 --- a/src/core/metacity-Xatomtype.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file metacity-Xatomtype.h Types for communicating with X about properties - * - * This files defines crock C structures for calling XGetWindowProperty and - * XChangeProperty. All fields must be longs as the semantics of property - * routines will handle conversion to and from actual 32 bit objects. If your - * compiler doesn't treat &structoflongs the same as &arrayoflongs[0], you - * will have some work to do. - */ - -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -#ifndef _XATOMTYPE_H_ -#define _XATOMTYPE_H_ - -#define BOOL long -#define SIGNEDINT long -#define UNSIGNEDINT unsigned long -#define RESOURCEID unsigned long - - -/* this structure may be extended, but do not change the order */ -typedef struct { - UNSIGNEDINT flags; - SIGNEDINT x, y, width, height; /* need to cvt; only for pre-ICCCM */ - SIGNEDINT minWidth, minHeight; /* need to cvt */ - SIGNEDINT maxWidth, maxHeight; /* need to cvt */ - SIGNEDINT widthInc, heightInc; /* need to cvt */ - SIGNEDINT minAspectX, minAspectY; /* need to cvt */ - SIGNEDINT maxAspectX, maxAspectY; /* need to cvt */ - SIGNEDINT baseWidth,baseHeight; /* need to cvt; ICCCM version 1 */ - SIGNEDINT winGravity; /* need to cvt; ICCCM version 1 */ -} xPropSizeHints; -#define OldNumPropSizeElements 15 /* pre-ICCCM */ -#define NumPropSizeElements 18 /* ICCCM version 1 */ - -/* this structure may be extended, but do not change the order */ -/* RGB properties */ -typedef struct { - RESOURCEID colormap; - UNSIGNEDINT red_max; - UNSIGNEDINT red_mult; - UNSIGNEDINT green_max; - UNSIGNEDINT green_mult; - UNSIGNEDINT blue_max; - UNSIGNEDINT blue_mult; - UNSIGNEDINT base_pixel; - RESOURCEID visualid; /* ICCCM version 1 */ - RESOURCEID killid; /* ICCCM version 1 */ -} xPropStandardColormap; -#define OldNumPropStandardColormapElements 8 /* pre-ICCCM */ -#define NumPropStandardColormapElements 10 /* ICCCM version 1 */ - - -/* this structure may be extended, but do not change the order */ -typedef struct { - UNSIGNEDINT flags; - BOOL input; /* need to convert */ - SIGNEDINT initialState; /* need to cvt */ - RESOURCEID iconPixmap; - RESOURCEID iconWindow; - SIGNEDINT iconX; /* need to cvt */ - SIGNEDINT iconY; /* need to cvt */ - RESOURCEID iconMask; - UNSIGNEDINT windowGroup; - } xPropWMHints; -#define NumPropWMHintsElements 9 /* number of elements in this structure */ - -/* this structure defines the icon size hints information */ -typedef struct { - SIGNEDINT minWidth, minHeight; /* need to cvt */ - SIGNEDINT maxWidth, maxHeight; /* need to cvt */ - SIGNEDINT widthInc, heightInc; /* need to cvt */ - } xPropIconSize; -#define NumPropIconSizeElements 6 /* number of elements in this structure */ - -/* this structure defines the window manager state information */ -typedef struct { - SIGNEDINT state; /* need to cvt */ - RESOURCEID iconWindow; -} xPropWMState; -#define NumPropWMStateElements 2 /* number of elements in struct */ - -#undef BOOL -#undef SIGNEDINT -#undef UNSIGNEDINT -#undef RESOURCEID - -#endif /* _XATOMTYPE_H_ */ diff --git a/src/core/place.c b/src/core/place.c deleted file mode 100644 index 901335c9..00000000 --- a/src/core/place.c +++ /dev/null @@ -1,932 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window placement */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> - -#include "place.h" -#include "workspace.h" -#include "prefs.h" -#include <gdk/gdk.h> -#include <math.h> -#include <stdlib.h> - -typedef enum -{ - META_LEFT, - META_RIGHT, - META_TOP, - META_BOTTOM -} MetaWindowDirection; - -static gint -northwestcmp (gconstpointer a, gconstpointer b) -{ - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; - int from_origin_a; - int from_origin_b; - int ax, ay, bx, by; - - /* we're interested in the frame position for cascading, - * not meta_window_get_position() - */ - if (aw->frame) - { - ax = aw->frame->rect.x; - ay = aw->frame->rect.y; - } - else - { - ax = aw->rect.x; - ay = aw->rect.y; - } - - if (bw->frame) - { - bx = bw->frame->rect.x; - by = bw->frame->rect.y; - } - else - { - bx = bw->rect.x; - by = bw->rect.y; - } - - /* probably there's a fast good-enough-guess we could use here. */ - from_origin_a = sqrt (ax * ax + ay * ay); - from_origin_b = sqrt (bx * bx + by * by); - - if (from_origin_a < from_origin_b) - return -1; - else if (from_origin_a > from_origin_b) - return 1; - else - return 0; -} - -static void -find_next_cascade (MetaWindow *window, - MetaFrameGeometry *fgeom, - /* visible windows on relevant workspaces */ - GList *windows, - int x, - int y, - int *new_x, - int *new_y) -{ - GList *tmp; - GList *sorted; - int cascade_x, cascade_y; - int x_threshold, y_threshold; - int window_width, window_height; - int cascade_stage; - MetaRectangle work_area; - const MetaXineramaScreenInfo* current; - - sorted = g_list_copy (windows); - sorted = g_list_sort (sorted, northwestcmp); - - /* This is a "fuzzy" cascade algorithm. - * For each window in the list, we find where we'd cascade a - * new window after it. If a window is already nearly at that - * position, we move on. - */ - - /* arbitrary-ish threshold, honors user attempts to - * manually cascade. - */ -#define CASCADE_FUZZ 15 - if (fgeom) - { - x_threshold = MAX (fgeom->left_width, CASCADE_FUZZ); - y_threshold = MAX (fgeom->top_height, CASCADE_FUZZ); - } - else - { - x_threshold = CASCADE_FUZZ; - y_threshold = CASCADE_FUZZ; - } - - /* Find furthest-SE origin of all workspaces. - * cascade_x, cascade_y are the target position - * of NW corner of window frame. - */ - - current = meta_screen_get_current_xinerama (window->screen); - meta_window_get_work_area_for_xinerama (window, current->number, &work_area); - - cascade_x = MAX (0, work_area.x); - cascade_y = MAX (0, work_area.y); - - /* Find first cascade position that's not used. */ - - window_width = window->frame ? window->frame->rect.width : window->rect.width; - window_height = window->frame ? window->frame->rect.height : window->rect.height; - - cascade_stage = 0; - tmp = sorted; - while (tmp != NULL) - { - MetaWindow *w; - int wx, wy; - - w = tmp->data; - - /* we want frame position, not window position */ - if (w->frame) - { - wx = w->frame->rect.x; - wy = w->frame->rect.y; - } - else - { - wx = w->rect.x; - wy = w->rect.y; - } - - if (ABS (wx - cascade_x) < x_threshold && - ABS (wy - cascade_y) < y_threshold) - { - /* This window is "in the way", move to next cascade - * point. The new window frame should go at the origin - * of the client window we're stacking above. - */ - meta_window_get_position (w, &wx, &wy); - cascade_x = wx; - cascade_y = wy; - - /* If we go off the screen, start over with a new cascade */ - if (((cascade_x + window_width) > - (work_area.x + work_area.width)) || - ((cascade_y + window_height) > - (work_area.y + work_area.height))) - { - cascade_x = MAX (0, work_area.x); - cascade_y = MAX (0, work_area.y); - -#define CASCADE_INTERVAL 50 /* space between top-left corners of cascades */ - cascade_stage += 1; - cascade_x += CASCADE_INTERVAL * cascade_stage; - - /* start over with a new cascade translated to the right, unless - * we are out of space - */ - if ((cascade_x + window_width) < - (work_area.x + work_area.width)) - { - tmp = sorted; - continue; - } - else - { - /* All out of space, this cascade_x won't work */ - cascade_x = MAX (0, work_area.x); - break; - } - } - } - else - { - /* Keep searching for a further-down-the-diagonal window. */ - } - - tmp = tmp->next; - } - - /* cascade_x and cascade_y will match the last window in the list - * that was "in the way" (in the approximate cascade diagonal) - */ - - g_list_free (sorted); - - /* Convert coords to position of window, not position of frame. */ - if (fgeom == NULL) - { - *new_x = cascade_x; - *new_y = cascade_y; - } - else - { - *new_x = cascade_x + fgeom->left_width; - *new_y = cascade_y + fgeom->top_height; - } -} - -static void -find_most_freespace (MetaWindow *window, - MetaFrameGeometry *fgeom, - /* visible windows on relevant workspaces */ - MetaWindow *focus_window, - int x, - int y, - int *new_x, - int *new_y) -{ - MetaWindowDirection side; - int max_area; - int max_width, max_height, left, right, top, bottom; - int left_space, right_space, top_space, bottom_space; - int frame_size_left, frame_size_top; - MetaRectangle work_area; - MetaRectangle avoid; - MetaRectangle outer; - - frame_size_left = fgeom ? fgeom->left_width : 0; - frame_size_top = fgeom ? fgeom->top_height : 0; - - meta_window_get_work_area_current_xinerama (focus_window, &work_area); - meta_window_get_outer_rect (focus_window, &avoid); - meta_window_get_outer_rect (window, &outer); - - /* Find the areas of choosing the various sides of the focus window */ - max_width = MIN (avoid.width, outer.width); - max_height = MIN (avoid.height, outer.height); - left_space = avoid.x - work_area.x; - right_space = work_area.width - (avoid.x + avoid.width - work_area.x); - top_space = avoid.y - work_area.y; - bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y); - left = MIN (left_space, outer.width); - right = MIN (right_space, outer.width); - top = MIN (top_space, outer.height); - bottom = MIN (bottom_space, outer.height); - - /* Find out which side of the focus_window can show the most of the window */ - side = META_LEFT; - max_area = left*max_height; - if (right*max_height > max_area) - { - side = META_RIGHT; - max_area = right*max_height; - } - if (top*max_width > max_area) - { - side = META_TOP; - max_area = top*max_width; - } - if (bottom*max_width > max_area) - { - side = META_BOTTOM; - max_area = bottom*max_width; - } - - /* Give up if there's no where to put it (i.e. focus window is maximized) */ - if (max_area == 0) - return; - - /* Place the window on the relevant side; if the whole window fits, - * make it adjacent to the focus window; if not, make sure the - * window doesn't go off the edge of the screen. - */ - switch (side) - { - case META_LEFT: - *new_y = avoid.y + frame_size_top; - if (left_space > outer.width) - *new_x = avoid.x - outer.width + frame_size_left; - else - *new_x = work_area.x + frame_size_left; - break; - case META_RIGHT: - *new_y = avoid.y + frame_size_top; - if (right_space > outer.width) - *new_x = avoid.x + avoid.width + frame_size_left; - else - *new_x = work_area.x + work_area.width - outer.width + frame_size_left; - break; - case META_TOP: - *new_x = avoid.x + frame_size_left; - if (top_space > outer.height) - *new_y = avoid.y - outer.height + frame_size_top; - else - *new_y = work_area.y + frame_size_top; - break; - case META_BOTTOM: - *new_x = avoid.x + frame_size_left; - if (bottom_space > outer.height) - *new_y = avoid.y + avoid.height + frame_size_top; - else - *new_y = work_area.y + work_area.height - outer.height + frame_size_top; - break; - } -} - -static void -avoid_being_obscured_as_second_modal_dialog (MetaWindow *window, - MetaFrameGeometry *fgeom, - int *x, - int *y) -{ - /* We can't center this dialog if it was denied focus and it - * overlaps with the focus window and this dialog is modal and this - * dialog is in the same app as the focus window (*phew*...please - * don't make me say that ten times fast). See bug 307875 comment 11 - * and 12 for details, but basically it means this is probably a - * second modal dialog for some app while the focus window is the - * first modal dialog. We should probably make them simultaneously - * visible in general, but it becomes mandatory to do so due to - * buggy apps (e.g. those using gtk+ *sigh*) because in those cases - * this second modal dialog also happens to be modal to the first - * dialog in addition to the main window, while it has only let us - * know about the modal-to-the-main-window part. - */ - - MetaWindow *focus_window; - MetaRectangle overlap; - - focus_window = window->display->focus_window; - - if (window->denied_focus_and_not_transient && - window->wm_state_modal && /* FIXME: Maybe do this for all transients? */ - meta_window_same_application (window, focus_window) && - meta_rectangle_intersect (&window->rect, - &focus_window->rect, - &overlap)) - { - find_most_freespace (window, fgeom, focus_window, *x, *y, x, y); - meta_topic (META_DEBUG_PLACEMENT, - "Dialog window %s was denied focus but may be modal " - "to the focus window; had to move it to avoid the " - "focus window\n", - window->desc); - } -} - -static gboolean -rectangle_overlaps_some_window (MetaRectangle *rect, - GList *windows) -{ - GList *tmp; - MetaRectangle dest; - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *other = tmp->data; - MetaRectangle other_rect; - - switch (other->type) - { - case META_WINDOW_DOCK: - case META_WINDOW_SPLASHSCREEN: - case META_WINDOW_DESKTOP: - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - break; - - case META_WINDOW_NORMAL: - case META_WINDOW_UTILITY: - case META_WINDOW_TOOLBAR: - case META_WINDOW_MENU: - meta_window_get_outer_rect (other, &other_rect); - - if (meta_rectangle_intersect (rect, &other_rect, &dest)) - return TRUE; - break; - } - - tmp = tmp->next; - } - - return FALSE; -} - -static gint -leftmost_cmp (gconstpointer a, gconstpointer b) -{ - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; - int ax, bx; - - /* we're interested in the frame position for cascading, - * not meta_window_get_position() - */ - if (aw->frame) - ax = aw->frame->rect.x; - else - ax = aw->rect.x; - - if (bw->frame) - bx = bw->frame->rect.x; - else - bx = bw->rect.x; - - if (ax < bx) - return -1; - else if (ax > bx) - return 1; - else - return 0; -} - -static gint -topmost_cmp (gconstpointer a, gconstpointer b) -{ - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; - int ay, by; - - /* we're interested in the frame position for cascading, - * not meta_window_get_position() - */ - if (aw->frame) - ay = aw->frame->rect.y; - else - ay = aw->rect.y; - - if (bw->frame) - by = bw->frame->rect.y; - else - by = bw->rect.y; - - if (ay < by) - return -1; - else if (ay > by) - return 1; - else - return 0; -} - -static void -center_tile_rect_in_area (MetaRectangle *rect, - MetaRectangle *work_area) -{ - int fluff; - - /* The point here is to tile a window such that "extra" - * space is equal on either side (i.e. so a full screen - * of windows tiled this way would center the windows - * as a group) - */ - - fluff = (work_area->width % (rect->width+1)) / 2; - rect->x = work_area->x + fluff; - fluff = (work_area->height % (rect->height+1)) / 3; - rect->y = work_area->y + fluff; -} - -/* Find the leftmost, then topmost, empty area on the workspace - * that can contain the new window. - * - * Cool feature to have: if we can't fit the current window size, - * try shrinking the window (within geometry constraints). But - * beware windows such as Emacs with no sane minimum size, we - * don't want to create a 1x1 Emacs. - */ -static gboolean -find_first_fit (MetaWindow *window, - MetaFrameGeometry *fgeom, - /* visible windows on relevant workspaces */ - GList *windows, - int xinerama, - int x, - int y, - int *new_x, - int *new_y) -{ - /* This algorithm is limited - it just brute-force tries - * to fit the window in a small number of locations that are aligned - * with existing windows. It tries to place the window on - * the bottom of each existing window, and then to the right - * of each existing window, aligned with the left/top of the - * existing window in each of those cases. - */ - int retval; - GList *below_sorted; - GList *right_sorted; - GList *tmp; - MetaRectangle rect; - MetaRectangle work_area; - - retval = FALSE; - - /* Below each window */ - below_sorted = g_list_copy (windows); - below_sorted = g_list_sort (below_sorted, leftmost_cmp); - below_sorted = g_list_sort (below_sorted, topmost_cmp); - - /* To the right of each window */ - right_sorted = g_list_copy (windows); - right_sorted = g_list_sort (right_sorted, topmost_cmp); - right_sorted = g_list_sort (right_sorted, leftmost_cmp); - - rect.width = window->rect.width; - rect.height = window->rect.height; - - if (fgeom) - { - rect.width += fgeom->left_width + fgeom->right_width; - rect.height += fgeom->top_height + fgeom->bottom_height; - } - -#ifdef WITH_VERBOSE_MODE - { - char xinerama_location_string[RECT_LENGTH]; - meta_rectangle_to_string (&window->screen->xinerama_infos[xinerama].rect, - xinerama_location_string); - meta_topic (META_DEBUG_XINERAMA, - "Natural xinerama is %s\n", - xinerama_location_string); - } -#endif - - meta_window_get_work_area_for_xinerama (window, xinerama, &work_area); - - center_tile_rect_in_area (&rect, &work_area); - - if (meta_rectangle_contains_rect (&work_area, &rect) && - !rectangle_overlaps_some_window (&rect, windows)) - { - *new_x = rect.x; - *new_y = rect.y; - if (fgeom) - { - *new_x += fgeom->left_width; - *new_y += fgeom->top_height; - } - - retval = TRUE; - - goto out; - } - - /* try below each window */ - tmp = below_sorted; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - MetaRectangle outer_rect; - - meta_window_get_outer_rect (w, &outer_rect); - - rect.x = outer_rect.x; - rect.y = outer_rect.y + outer_rect.height; - - if (meta_rectangle_contains_rect (&work_area, &rect) && - !rectangle_overlaps_some_window (&rect, below_sorted)) - { - *new_x = rect.x; - *new_y = rect.y; - if (fgeom) - { - *new_x += fgeom->left_width; - *new_y += fgeom->top_height; - } - - retval = TRUE; - - goto out; - } - - tmp = tmp->next; - } - - /* try to the right of each window */ - tmp = right_sorted; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - MetaRectangle outer_rect; - - meta_window_get_outer_rect (w, &outer_rect); - - rect.x = outer_rect.x + outer_rect.width; - rect.y = outer_rect.y; - - if (meta_rectangle_contains_rect (&work_area, &rect) && - !rectangle_overlaps_some_window (&rect, right_sorted)) - { - *new_x = rect.x; - *new_y = rect.y; - if (fgeom) - { - *new_x += fgeom->left_width; - *new_y += fgeom->top_height; - } - - retval = TRUE; - - goto out; - } - - tmp = tmp->next; - } - - out: - - g_list_free (below_sorted); - g_list_free (right_sorted); - return retval; -} - -void -meta_window_place (MetaWindow *window, - MetaFrameGeometry *fgeom, - int x, - int y, - int *new_x, - int *new_y) -{ - GList *windows; - const MetaXineramaScreenInfo *xi; - - /* frame member variables should NEVER be used in here, only - * MetaFrameGeometry. But remember fgeom == NULL - * for undecorated windows. Also, this function should - * NEVER have side effects other than computing the - * placement coordinates. - */ - - meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc); - - windows = NULL; - - switch (window->type) - { - /* Run placement algorithm on these. */ - case META_WINDOW_NORMAL: - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - case META_WINDOW_SPLASHSCREEN: - break; - - /* Assume the app knows best how to place these, no placement - * algorithm ever (other than "leave them as-is") - */ - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_MENU: - case META_WINDOW_UTILITY: - goto done_no_constraints; - } - - if (meta_prefs_get_disable_workarounds ()) - { - switch (window->type) - { - /* Only accept USPosition on normal windows because the app is full - * of shit claiming the user set -geometry for a dialog or dock - */ - case META_WINDOW_NORMAL: - if (window->size_hints.flags & USPosition) - { - /* don't constrain with placement algorithm */ - meta_topic (META_DEBUG_PLACEMENT, - "Honoring USPosition for %s instead of using placement algorithm\n", window->desc); - - goto done; - } - break; - - /* Ignore even USPosition on dialogs, splashscreen */ - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - case META_WINDOW_SPLASHSCREEN: - break; - - /* Assume the app knows best how to place these. */ - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_MENU: - case META_WINDOW_UTILITY: - if (window->size_hints.flags & PPosition) - { - meta_topic (META_DEBUG_PLACEMENT, - "Not placing non-normal non-dialog window with PPosition set\n"); - goto done_no_constraints; - } - break; - } - } - else - { - /* workarounds enabled */ - - if ((window->size_hints.flags & PPosition) || - (window->size_hints.flags & USPosition)) - { - meta_topic (META_DEBUG_PLACEMENT, - "Not placing window with PPosition or USPosition set\n"); - avoid_being_obscured_as_second_modal_dialog (window, fgeom, &x, &y); - goto done_no_constraints; - } - } - - if ((window->type == META_WINDOW_DIALOG || - window->type == META_WINDOW_MODAL_DIALOG) && - window->xtransient_for != None) - { - /* Center horizontally, at top of parent vertically */ - - MetaWindow *parent; - - parent = - meta_display_lookup_x_window (window->display, - window->xtransient_for); - - if (parent) - { - int w; - - meta_window_get_position (parent, &x, &y); - w = parent->rect.width; - - /* center of parent */ - x = x + w / 2; - /* center of child over center of parent */ - x -= window->rect.width / 2; - - /* "visually" center window over parent, leaving twice as - * much space below as on top. - */ - y += (parent->rect.height - window->rect.height)/3; - - /* put top of child's frame, not top of child's client */ - if (fgeom) - y += fgeom->top_height; - - meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n", - window->desc); - - avoid_being_obscured_as_second_modal_dialog (window, fgeom, &x, &y); - - goto done; - } - } - - /* FIXME UTILITY with transient set should be stacked up - * on the sides of the parent window or something. - */ - - if (window->type == META_WINDOW_DIALOG || - window->type == META_WINDOW_MODAL_DIALOG || - window->type == META_WINDOW_SPLASHSCREEN) - { - /* Center on current xinerama (i.e. on current monitor) */ - int w, h; - - /* Warning, this function is a round trip! */ - xi = meta_screen_get_current_xinerama (window->screen); - - w = xi->rect.width; - h = xi->rect.height; - - x = (w - window->rect.width) / 2; - y = (h - window->rect.height) / 2; - - x += xi->rect.x; - y += xi->rect.y; - - meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d xinerama %d\n", - window->desc, window->screen->number, xi->number); - - goto done_check_denied_focus; - } - - /* Find windows that matter (not minimized, on same workspace - * as placed window, may be shaded - if shaded we pretend it isn't - * for placement purposes) - */ - { - GSList *all_windows; - GSList *tmp; - - all_windows = meta_display_list_windows (window->display); - - tmp = all_windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (meta_window_showing_on_its_workspace (w) && - w != window && - (window->workspace == w->workspace || - window->on_all_workspaces || w->on_all_workspaces)) - windows = g_list_prepend (windows, w); - - tmp = tmp->next; - } - - g_slist_free (all_windows); - } - - /* Warning, this is a round trip! */ - xi = meta_screen_get_current_xinerama (window->screen); - - /* "Origin" placement algorithm */ - x = xi->rect.x; - y = xi->rect.y; - - if (find_first_fit (window, fgeom, windows, - xi->number, - x, y, &x, &y)) - goto done_check_denied_focus; - - /* Maximize windows if they are too big for their work area (bit of - * a hack here). Assume undecorated windows probably don't intend to - * be maximized. - */ - if (window->has_maximize_func && window->decorated && - !window->fullscreen) - { - MetaRectangle workarea; - MetaRectangle outer; - - meta_window_get_work_area_for_xinerama (window, - xi->number, - &workarea); - meta_window_get_outer_rect (window, &outer); - - /* If the window is bigger than the screen, then automaximize. Do NOT - * auto-maximize the directions independently. See #419810. - */ - if (outer.width >= workarea.width && outer.height >= workarea.height) - { - window->maximize_horizontally_after_placement = TRUE; - window->maximize_vertically_after_placement = TRUE; - } - } - - /* If no placement has been done, revert to cascade to avoid - * fully overlapping window (e.g. starting multiple terminals) - * */ - if (x == xi->rect.x && y == xi->rect.y) - find_next_cascade (window, fgeom, windows, x, y, &x, &y); - - done_check_denied_focus: - /* If the window is being denied focus and isn't a transient of the - * focus window, we do NOT want it to overlap with the focus window - * if at all possible. This is guaranteed to only be called if the - * focus_window is non-NULL, and we try to avoid that window. - */ - if (window->denied_focus_and_not_transient) - { - gboolean found_fit; - MetaWindow *focus_window; - MetaRectangle overlap; - - focus_window = window->display->focus_window; - g_assert (focus_window != NULL); - - /* No need to do anything if the window doesn't overlap at all */ - found_fit = !meta_rectangle_intersect (&window->rect, - &focus_window->rect, - &overlap); - - /* Try to do a first fit again, this time only taking into account the - * focus window. - */ - if (!found_fit) - { - GList *focus_window_list; - focus_window_list = g_list_prepend (NULL, focus_window); - - /* Reset x and y ("origin" placement algorithm) */ - x = xi->rect.x; - y = xi->rect.y; - - found_fit = find_first_fit (window, fgeom, focus_window_list, - xi->number, - x, y, &x, &y); - g_list_free (focus_window_list); - } - - /* If that still didn't work, just place it where we can see as much - * as possible. - */ - if (!found_fit) - find_most_freespace (window, fgeom, focus_window, x, y, &x, &y); - } - - done: - g_list_free (windows); - - done_no_constraints: - - *new_x = x; - *new_y = y; -} diff --git a/src/core/place.h b/src/core/place.h deleted file mode 100644 index 10bf4a1c..00000000 --- a/src/core/place.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window placement */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_PLACE_H -#define META_PLACE_H - -#include "window-private.h" -#include "frame-private.h" - -void meta_window_place (MetaWindow *window, - MetaFrameGeometry *fgeom, - int x, - int y, - int *new_x, - int *new_y); - -#endif diff --git a/src/core/prefs.c b/src/core/prefs.c deleted file mode 100644 index ca928e9e..00000000 --- a/src/core/prefs.c +++ /dev/null @@ -1,2776 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity preferences */ - -/* - * Copyright (C) 2001 Havoc Pennington, Copyright (C) 2002 Red Hat Inc. - * Copyright (C) 2006 Elijah Newren - * Copyright (C) 2008 Thomas Thurman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "prefs.h" -#include "ui.h" -#include "util.h" -#ifdef HAVE_GCONF -#include <gconf/gconf-client.h> -#endif -#include <string.h> -#include <stdlib.h> - -#define MAX_REASONABLE_WORKSPACES 36 - -#define MAX_COMMANDS (32 + NUM_EXTRA_COMMANDS) -#define NUM_EXTRA_COMMANDS 2 -#define SCREENSHOT_COMMAND_IDX (MAX_COMMANDS - 2) -#define WIN_SCREENSHOT_COMMAND_IDX (MAX_COMMANDS - 1) - -/* If you add a key, it needs updating in init() and in the gconf - * notify listener and of course in the .schemas file. - * - * Keys which are handled by one of the unified handlers below are - * not given a name here, because the purpose of the unified handlers - * is that keys should be referred to exactly once. - */ -#define KEY_TITLEBAR_FONT "/apps/metacity/general/titlebar_font" -#define KEY_NUM_WORKSPACES "/apps/metacity/general/num_workspaces" -#define KEY_COMPOSITOR "/apps/metacity/general/compositing_manager" -#define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility" - -#define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_" - -#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal" -#define KEY_TERMINAL_COMMAND KEY_TERMINAL_DIR "/exec" - -#define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings" -#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings" -#define KEY_LIST_BINDINGS_SUFFIX "_list" - -#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_" - - -#ifdef HAVE_GCONF -static GConfClient *default_client = NULL; -static GList *changes = NULL; -static guint changed_idle; -static GList *listeners = NULL; -#endif - -static gboolean use_system_font = FALSE; -static PangoFontDescription *titlebar_font = NULL; -static MetaVirtualModifier mouse_button_mods = Mod1Mask; -static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK; -static MetaFocusNewWindows focus_new_windows = META_FOCUS_NEW_WINDOWS_SMART; -static gboolean raise_on_click = TRUE; -static char* current_theme = NULL; -static int num_workspaces = 4; -static MetaActionTitlebar action_double_click_titlebar = META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE; -static MetaActionTitlebar action_middle_click_titlebar = META_ACTION_TITLEBAR_LOWER; -static MetaActionTitlebar action_right_click_titlebar = META_ACTION_TITLEBAR_MENU; -static gboolean application_based = FALSE; -static gboolean disable_workarounds = FALSE; -static gboolean auto_raise = FALSE; -static gboolean auto_raise_delay = 500; -static gboolean provide_visual_bell = FALSE; -static gboolean bell_is_audible = TRUE; -static gboolean reduced_resources = FALSE; -static gboolean gnome_accessibility = FALSE; -static gboolean gnome_animations = TRUE; -static char *cursor_theme = NULL; -static int cursor_size = 24; -static gboolean compositing_manager = FALSE; - -static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH; -static MetaButtonLayout button_layout; - -/* The screenshot commands are at the end */ -static char *commands[MAX_COMMANDS] = { NULL, }; - -static char *terminal_command = NULL; - -static char *workspace_names[MAX_REASONABLE_WORKSPACES] = { NULL, }; - -#ifdef HAVE_GCONF -static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value); - -static gboolean update_key_binding (const char *name, - const char *value); -static gboolean find_and_update_list_binding (MetaKeyPref *bindings, - const char *name, - GSList *value); -static gboolean update_key_list_binding (const char *name, - GSList *value); -static gboolean update_command (const char *name, - const char *value); -static gboolean update_workspace_name (const char *name, - const char *value); - -static void change_notify (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data); - -static char* gconf_key_for_workspace_name (int i); - -static void queue_changed (MetaPreference pref); - -typedef enum - { - META_LIST_OF_STRINGS, - META_LIST_OF_GCONFVALUE_STRINGS - } MetaStringListType; - -static gboolean update_list_binding (MetaKeyPref *binding, - GSList *value, - MetaStringListType type_of_value); - -static void cleanup_error (GError **error); -static gboolean get_bool (const char *key, gboolean *val); -static void maybe_give_disable_workarounds_warning (void); - -static void titlebar_handler (MetaPreference, const gchar*, gboolean*); -static void theme_name_handler (MetaPreference, const gchar*, gboolean*); -static void mouse_button_mods_handler (MetaPreference, const gchar*, gboolean*); -static void button_layout_handler (MetaPreference, const gchar*, gboolean*); - -#endif /* HAVE_GCONF */ - -static gboolean update_binding (MetaKeyPref *binding, - const char *value); - -static void init_bindings (void); -static void init_commands (void); -static void init_workspace_names (void); - -#ifndef HAVE_GCONF -static void init_button_layout (void); -#endif /* !HAVE_GCONF */ - -#ifdef HAVE_GCONF - -typedef struct -{ - MetaPrefsChangedFunc func; - gpointer data; -} MetaPrefsListener; - -static GConfEnumStringPair symtab_focus_mode[] = - { - { META_FOCUS_MODE_CLICK, "click" }, - { META_FOCUS_MODE_SLOPPY, "sloppy" }, - { META_FOCUS_MODE_MOUSE, "mouse" }, - { 0, NULL }, - }; - -static GConfEnumStringPair symtab_focus_new_windows[] = - { - { META_FOCUS_NEW_WINDOWS_SMART, "smart" }, - { META_FOCUS_NEW_WINDOWS_STRICT, "strict" }, - { 0, NULL }, - }; - -static GConfEnumStringPair symtab_visual_bell_type[] = - { - /* Note to the reader: 0 is an invalid value; these start at 1. */ - { META_VISUAL_BELL_FULLSCREEN_FLASH, "fullscreen" }, - { META_VISUAL_BELL_FRAME_FLASH, "frame_flash" }, - { 0, NULL }, - }; - -static GConfEnumStringPair symtab_titlebar_action[] = - { - { META_ACTION_TITLEBAR_TOGGLE_SHADE, "toggle_shade" }, - { META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE, "toggle_maximize" }, - { META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_HORIZONTALLY, - "toggle_maximize_horizontally" }, - { META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_VERTICALLY, - "toggle_maximize_vertically" }, - { META_ACTION_TITLEBAR_MINIMIZE, "minimize" }, - { META_ACTION_TITLEBAR_NONE, "none" }, - { META_ACTION_TITLEBAR_LOWER, "lower" }, - { META_ACTION_TITLEBAR_MENU, "menu" }, - { META_ACTION_TITLEBAR_TOGGLE_SHADE, "toggle_shade" }, - { 0, NULL }, - }; - -/** - * The details of one preference which is constrained to be - * one of a small number of string values-- in other words, - * an enumeration. - * - * We could have done this other ways. One particularly attractive - * possibility would have been to represent the entire symbol table - * as a space-separated string literal in the list of symtabs, so - * the focus mode enums could have been represented simply by - * "click sloppy mouse". However, the simplicity gained would have - * been outweighed by the bugs caused when the ordering of the enum - * strings got out of sync with the actual enum statement. Also, - * there is existing library code to use this kind of symbol tables. - * - * Other things we might consider doing to clean this up in the - * future include: - * - * - most of the keys begin with the same prefix, and perhaps we - * could assume it if they don't start with a slash - * - * - there are several cases where a single identifier could be used - * to generate an entire entry, and perhaps this could be done - * with a macro. (This would reduce clarity, however, and is - * probably a bad thing.) - * - * - these types all begin with a gchar* (and contain a MetaPreference) - * and we can factor out the repeated code in the handlers by taking - * advantage of this using some kind of union arrangement. - */ -typedef struct -{ - gchar *key; - MetaPreference pref; - GConfEnumStringPair *symtab; - gpointer target; -} MetaEnumPreference; - -typedef struct -{ - gchar *key; - MetaPreference pref; - gboolean *target; - gboolean becomes_true_on_destruction; -} MetaBoolPreference; - -typedef struct -{ - gchar *key; - MetaPreference pref; - - /** - * A handler. Many of the string preferences aren't stored as - * strings and need parsing; others of them have default values - * which can't be solved in the general case. If you include a - * function pointer here, it will be called before the string - * value is written out to the target variable. - * - * The function is passed two arguments: the preference, and - * the new string as a gchar*. It returns a gboolean; - * only if this is true, the listeners will be informed that - * the preference has changed. - * - * This may be NULL. If it is, see "target", below. - */ - void (*handler) (MetaPreference pref, - const gchar *string_value, - gboolean *inform_listeners); - - /** - * Where to write the incoming string. - * - * This must be NULL if the handler is non-NULL. - * If the incoming string is NULL, no change will be made. - */ - gchar **target; - -} MetaStringPreference; - -#define METAINTPREFERENCE_NO_CHANGE_ON_DESTROY G_MININT - -typedef struct -{ - gchar *key; - MetaPreference pref; - gint *target; - /** - * Minimum and maximum values of the integer. - * If the new value is out of bounds, it will be discarded with a warning. - */ - gint minimum, maximum; - /** - * Value to use if the key is destroyed. - * If this is METAINTPREFERENCE_NO_CHANGE_ON_DESTROY, it will - * not be changed when the key is destroyed. - */ - gint value_if_destroyed; -} MetaIntPreference; - -/* FIXMEs: */ -/* @@@ Don't use NULL lines at the end; glib can tell you how big it is */ -/* @@@ /apps/metacity/general should be assumed if first char is not / */ -/* @@@ Will it ever be possible to merge init and update? If not, why not? */ - -static MetaEnumPreference preferences_enum[] = - { - { "/apps/metacity/general/focus_new_windows", - META_PREF_FOCUS_NEW_WINDOWS, - symtab_focus_new_windows, - &focus_new_windows, - }, - { "/apps/metacity/general/focus_mode", - META_PREF_FOCUS_MODE, - symtab_focus_mode, - &focus_mode, - }, - { "/apps/metacity/general/visual_bell_type", - META_PREF_VISUAL_BELL_TYPE, - symtab_visual_bell_type, - &visual_bell_type, - }, - { "/apps/metacity/general/action_double_click_titlebar", - META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR, - symtab_titlebar_action, - &action_double_click_titlebar, - }, - { "/apps/metacity/general/action_middle_click_titlebar", - META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR, - symtab_titlebar_action, - &action_middle_click_titlebar, - }, - { "/apps/metacity/general/action_right_click_titlebar", - META_PREF_ACTION_RIGHT_CLICK_TITLEBAR, - symtab_titlebar_action, - &action_right_click_titlebar, - }, - { NULL, 0, NULL, NULL }, - }; - -static MetaBoolPreference preferences_bool[] = - { - { "/apps/metacity/general/raise_on_click", - META_PREF_RAISE_ON_CLICK, - &raise_on_click, - TRUE, - }, - { "/apps/metacity/general/titlebar_uses_system_font", - META_PREF_TITLEBAR_FONT, /* note! shares a pref */ - &use_system_font, - TRUE, - }, - { "/apps/metacity/general/application_based", - META_PREF_APPLICATION_BASED, - NULL, /* feature is known but disabled */ - FALSE, - }, - { "/apps/metacity/general/disable_workarounds", - META_PREF_DISABLE_WORKAROUNDS, - &disable_workarounds, - FALSE, - }, - { "/apps/metacity/general/auto_raise", - META_PREF_AUTO_RAISE, - &auto_raise, - FALSE, - }, - { "/apps/metacity/general/visual_bell", - META_PREF_VISUAL_BELL, - &provide_visual_bell, /* FIXME: change the name: it's confusing */ - FALSE, - }, - { "/apps/metacity/general/audible_bell", - META_PREF_AUDIBLE_BELL, - &bell_is_audible, /* FIXME: change the name: it's confusing */ - FALSE, - }, - { "/apps/metacity/general/reduced_resources", - META_PREF_REDUCED_RESOURCES, - &reduced_resources, - FALSE, - }, - { "/desktop/gnome/interface/accessibility", - META_PREF_GNOME_ACCESSIBILITY, - &gnome_accessibility, - FALSE, - }, - { "/desktop/gnome/interface/enable_animations", - META_PREF_GNOME_ANIMATIONS, - &gnome_animations, - TRUE, - }, - { "/apps/metacity/general/compositing_manager", - META_PREF_COMPOSITING_MANAGER, - &compositing_manager, - FALSE, - }, - { NULL, 0, NULL, FALSE }, - }; - -static MetaStringPreference preferences_string[] = - { - { "/apps/metacity/general/mouse_button_modifier", - META_PREF_MOUSE_BUTTON_MODS, - mouse_button_mods_handler, - NULL, - }, - { "/apps/metacity/general/theme", - META_PREF_THEME, - theme_name_handler, - NULL, - }, - { KEY_TITLEBAR_FONT, - META_PREF_TITLEBAR_FONT, - titlebar_handler, - NULL, - }, - { KEY_TERMINAL_COMMAND, - META_PREF_TERMINAL_COMMAND, - NULL, - &terminal_command, - }, - { "/apps/metacity/general/button_layout", - META_PREF_BUTTON_LAYOUT, - button_layout_handler, - NULL, - }, - { "/desktop/gnome/peripherals/mouse/cursor_theme", - META_PREF_CURSOR_THEME, - NULL, - &cursor_theme, - }, - { NULL, 0, NULL, NULL }, - }; - -static MetaIntPreference preferences_int[] = - { - { "/apps/metacity/general/num_workspaces", - META_PREF_NUM_WORKSPACES, - &num_workspaces, - /* I would actually recommend we change the destroy value to 4 - * and get rid of METAINTPREFERENCE_NO_CHANGE_ON_DESTROY entirely. - * -- tthurman - */ - 1, MAX_REASONABLE_WORKSPACES, METAINTPREFERENCE_NO_CHANGE_ON_DESTROY, - }, - { "/apps/metacity/general/auto_raise_delay", - META_PREF_AUTO_RAISE_DELAY, - &auto_raise_delay, - 0, 10000, 0, - /* @@@ Get rid of MAX_REASONABLE_AUTO_RAISE_DELAY */ - }, - { "/desktop/gnome/peripherals/mouse/cursor_size", - META_PREF_CURSOR_SIZE, - &cursor_size, - 1, 128, 24, - }, - { NULL, 0, NULL, 0, 0, 0, }, - }; - -static void -handle_preference_init_enum (void) -{ - MetaEnumPreference *cursor = preferences_enum; - - while (cursor->key!=NULL) - { - char *value; - GError *error = NULL; - - if (cursor->target==NULL) - { - ++cursor; - continue; - } - - value = gconf_client_get_string (default_client, - cursor->key, - &error); - cleanup_error (&error); - - if (value==NULL) - { - ++cursor; - continue; - } - - if (!gconf_string_to_enum (cursor->symtab, - value, - (gint *) cursor->target)) - meta_warning (_("GConf key '%s' is set to an invalid value\n"), - cursor->key); - - g_free (value); - - ++cursor; - } -} - -static void -handle_preference_init_bool (void) -{ - MetaBoolPreference *cursor = preferences_bool; - - while (cursor->key!=NULL) - { - if (cursor->target!=NULL) - get_bool (cursor->key, cursor->target); - - ++cursor; - } - - maybe_give_disable_workarounds_warning (); -} - -static void -handle_preference_init_string (void) -{ - MetaStringPreference *cursor = preferences_string; - - while (cursor->key!=NULL) - { - char *value; - GError *error = NULL; - gboolean dummy = TRUE; - - /* the string "value" will be newly allocated */ - value = gconf_client_get_string (default_client, - cursor->key, - &error); - cleanup_error (&error); - - if (cursor->handler) - { - if (cursor->target) - meta_bug ("%s has both a target and a handler\n", cursor->key); - - cursor->handler (cursor->pref, value, &dummy); - - g_free (value); - } - else if (cursor->target) - { - if (*(cursor->target)) - g_free (*(cursor->target)); - - *(cursor->target) = value; - } - - ++cursor; - } -} - -static void -handle_preference_init_int (void) -{ - MetaIntPreference *cursor = preferences_int; - - - while (cursor->key!=NULL) - { - gint value; - GError *error = NULL; - - value = gconf_client_get_int (default_client, - cursor->key, - &error); - cleanup_error (&error); - - if (value < cursor->minimum || value > cursor->maximum) - { - meta_warning (_("%d stored in GConf key %s is out of range %d to %d\n"), - value, cursor->key, cursor->minimum, cursor->maximum); - /* Former behaviour for out-of-range values was: - * - number of workspaces was clamped; - * - auto raise delay was always reset to zero even if too high!; - * - cursor size was ignored. - * - * These seem to be meaningless variations. If they did - * have meaning we could have put them into MetaIntPreference. - * The last of these is the closest to how we behave for - * other types, so I think we should standardise on that. - */ - } - else if (cursor->target) - *cursor->target = value; - - ++cursor; - } -} - -static gboolean -handle_preference_update_enum (const gchar *key, GConfValue *value) -{ - MetaEnumPreference *cursor = preferences_enum; - gint old_value; - - while (cursor->key!=NULL && strcmp (key, cursor->key)!=0) - ++cursor; - - if (cursor->key==NULL) - /* Didn't recognise that key. */ - return FALSE; - - /* Setting it to null (that is, removing it) always means - * "don't change". - */ - - if (value==NULL) - return TRUE; - - /* Check the type. Enums are always strings. */ - - if (value->type != GCONF_VALUE_STRING) - { - meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), - key); - /* But we did recognise it. */ - return TRUE; - } - - /* We need to know whether the value changes, so - * store the current value away. - */ - - old_value = * ((gint *) cursor->target); - - /* Now look it up... */ - - if (!gconf_string_to_enum (cursor->symtab, - gconf_value_get_string (value), - (gint *) cursor->target)) - { - /* - * We found it, but it was invalid. Complain. - * - * FIXME: This replicates the original behaviour, but in the future - * we might consider reverting invalid keys to their original values. - * (We know the old value, so we can look up a suitable string in - * the symtab.) - * - * (Empty comment follows so the translators don't see this.) - */ - - /* */ - meta_warning (_("GConf key '%s' is set to an invalid value\n"), - key); - return TRUE; - } - - /* Did it change? If so, tell the listeners about it. */ - - if (old_value != *((gint *) cursor->target)) - queue_changed (cursor->pref); - - return TRUE; -} - -static gboolean -handle_preference_update_bool (const gchar *key, GConfValue *value) -{ - MetaBoolPreference *cursor = preferences_bool; - gboolean old_value; - - while (cursor->key!=NULL && strcmp (key, cursor->key)!=0) - ++cursor; - - if (cursor->key==NULL) - /* Didn't recognise that key. */ - return FALSE; - - if (cursor->target==NULL) - /* No work for us to do. */ - return TRUE; - - if (value==NULL) - { - /* Value was destroyed; let's get out of here. */ - - if (cursor->becomes_true_on_destruction) - /* This preserves the behaviour of the old system, but - * for all I know that might have been an oversight. - */ - *((gboolean *)cursor->target) = TRUE; - - return TRUE; - } - - /* Check the type. */ - - if (value->type != GCONF_VALUE_BOOL) - { - meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), - key); - /* But we did recognise it. */ - return TRUE; - } - - /* We need to know whether the value changes, so - * store the current value away. - */ - - old_value = * ((gboolean *) cursor->target); - - /* Now look it up... */ - - *((gboolean *) cursor->target) = gconf_value_get_bool (value); - - /* Did it change? If so, tell the listeners about it. */ - - if (old_value != *((gboolean *) cursor->target)) - queue_changed (cursor->pref); - - if (cursor->pref==META_PREF_DISABLE_WORKAROUNDS) - maybe_give_disable_workarounds_warning (); - - return TRUE; -} - -static gboolean -handle_preference_update_string (const gchar *key, GConfValue *value) -{ - MetaStringPreference *cursor = preferences_string; - const gchar *value_as_string; - gboolean inform_listeners = TRUE; - - while (cursor->key!=NULL && strcmp (key, cursor->key)!=0) - ++cursor; - - if (cursor->key==NULL) - /* Didn't recognise that key. */ - return FALSE; - - if (value==NULL) - return TRUE; - - /* Check the type. */ - - if (value->type != GCONF_VALUE_STRING) - { - meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), - key); - /* But we did recognise it. */ - return TRUE; - } - - /* Docs: "The returned string is not a copy, don't try to free it." */ - value_as_string = gconf_value_get_string (value); - - if (cursor->handler) - cursor->handler (cursor->pref, value_as_string, &inform_listeners); - else if (cursor->target) - { - if (*(cursor->target)) - g_free(*(cursor->target)); - - if (value_as_string!=NULL) - *(cursor->target) = g_strdup (value_as_string); - else - *(cursor->target) = NULL; - - inform_listeners = - (value_as_string==NULL && *(cursor->target)==NULL) || - (value_as_string!=NULL && *(cursor->target)!=NULL && - strcmp (value_as_string, *(cursor->target))==0); - } - - if (inform_listeners) - queue_changed (cursor->pref); - - return TRUE; -} - -static gboolean -handle_preference_update_int (const gchar *key, GConfValue *value) -{ - MetaIntPreference *cursor = preferences_int; - gint new_value; - - while (cursor->key!=NULL && strcmp (key, cursor->key)!=0) - ++cursor; - - if (cursor->key==NULL) - /* Didn't recognise that key. */ - return FALSE; - - if (cursor->target==NULL) - /* No work for us to do. */ - return TRUE; - - if (value==NULL) - { - /* Value was destroyed. */ - - if (cursor->value_if_destroyed != METAINTPREFERENCE_NO_CHANGE_ON_DESTROY) - *((gint *)cursor->target) = cursor->value_if_destroyed; - - return TRUE; - } - - /* Check the type. */ - - if (value->type != GCONF_VALUE_INT) - { - meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), - key); - /* But we did recognise it. */ - return TRUE; - } - - new_value = gconf_value_get_int (value); - - if (new_value < cursor->minimum || new_value > cursor->maximum) - { - meta_warning (_("%d stored in GConf key %s is out of range %d to %d\n"), - new_value, cursor->key, - cursor->minimum, cursor->maximum); - return TRUE; - } - - /* Did it change? If so, tell the listeners about it. */ - - if (*cursor->target != new_value) - { - *cursor->target = new_value; - queue_changed (cursor->pref); - } - - return TRUE; - -} - - -/****************************************************************************/ -/* Listeners. */ -/****************************************************************************/ - -void -meta_prefs_add_listener (MetaPrefsChangedFunc func, - gpointer data) -{ - MetaPrefsListener *l; - - l = g_new (MetaPrefsListener, 1); - l->func = func; - l->data = data; - - listeners = g_list_prepend (listeners, l); -} - -void -meta_prefs_remove_listener (MetaPrefsChangedFunc func, - gpointer data) -{ - GList *tmp; - - tmp = listeners; - while (tmp != NULL) - { - MetaPrefsListener *l = tmp->data; - - if (l->func == func && - l->data == data) - { - g_free (l); - listeners = g_list_delete_link (listeners, tmp); - - return; - } - - tmp = tmp->next; - } - - meta_bug ("Did not find listener to remove\n"); -} - -static void -emit_changed (MetaPreference pref) -{ - GList *tmp; - GList *copy; - - meta_topic (META_DEBUG_PREFS, "Notifying listeners that pref %s changed\n", - meta_preference_to_string (pref)); - - copy = g_list_copy (listeners); - - tmp = copy; - - while (tmp != NULL) - { - MetaPrefsListener *l = tmp->data; - - (* l->func) (pref, l->data); - - tmp = tmp->next; - } - - g_list_free (copy); -} - -static gboolean -changed_idle_handler (gpointer data) -{ - GList *tmp; - GList *copy; - - changed_idle = 0; - - copy = g_list_copy (changes); /* reentrancy paranoia */ - - g_list_free (changes); - changes = NULL; - - tmp = copy; - while (tmp != NULL) - { - MetaPreference pref = GPOINTER_TO_INT (tmp->data); - - emit_changed (pref); - - tmp = tmp->next; - } - - g_list_free (copy); - - return FALSE; -} - -static void -queue_changed (MetaPreference pref) -{ - meta_topic (META_DEBUG_PREFS, "Queueing change of pref %s\n", - meta_preference_to_string (pref)); - - if (g_list_find (changes, GINT_TO_POINTER (pref)) == NULL) - changes = g_list_prepend (changes, GINT_TO_POINTER (pref)); - else - meta_topic (META_DEBUG_PREFS, "Change of pref %s was already pending\n", - meta_preference_to_string (pref)); - - /* add idle at priority below the gconf notify idle */ - if (changed_idle == 0) - changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY, - changed_idle_handler, NULL, NULL); -} - -#else /* HAVE_GCONF */ - -void -meta_prefs_add_listener (MetaPrefsChangedFunc func, - gpointer data) -{ - /* Nothing, because they have gconf turned off */ -} - -void -meta_prefs_remove_listener (MetaPrefsChangedFunc func, - gpointer data) -{ - /* Nothing, because they have gconf turned off */ -} - -#endif /* HAVE_GCONF */ - - -/****************************************************************************/ -/* Initialisation. */ -/****************************************************************************/ - -#ifdef HAVE_GCONF -/* @@@ again, use glib's ability to tell you the size of the array */ -static gchar *gconf_dirs_we_are_interested_in[] = { - "/apps/metacity", - KEY_TERMINAL_DIR, - KEY_GNOME_ACCESSIBILITY, - "/desktop/gnome/peripherals/mouse", - "/desktop/gnome/interface", - NULL, -}; -#endif - -void -meta_prefs_init (void) -{ -#ifdef HAVE_GCONF - GError *err = NULL; - gchar **gconf_dir_cursor; - - if (default_client != NULL) - return; - - /* returns a reference which we hold forever */ - default_client = gconf_client_get_default (); - - for (gconf_dir_cursor=gconf_dirs_we_are_interested_in; - *gconf_dir_cursor!=NULL; - gconf_dir_cursor++) - { - gconf_client_add_dir (default_client, - *gconf_dir_cursor, - GCONF_CLIENT_PRELOAD_RECURSIVE, - &err); - cleanup_error (&err); - } - - /* Pick up initial values. */ - - handle_preference_init_enum (); - handle_preference_init_bool (); - handle_preference_init_string (); - handle_preference_init_int (); - - /* @@@ Is there any reason we don't do the add_dir here? */ - for (gconf_dir_cursor=gconf_dirs_we_are_interested_in; - *gconf_dir_cursor!=NULL; - gconf_dir_cursor++) - { - gconf_client_notify_add (default_client, - *gconf_dir_cursor, - change_notify, - NULL, - NULL, - &err); - cleanup_error (&err); - } - -#else /* HAVE_GCONF */ - - /* Set defaults for some values that can't be set at initialization time of - * the static globals. In the case of the theme, note that there is code - * elsewhere that will do everything possible to fallback to an existing theme - * if the one here does not exist. - */ - titlebar_font = pango_font_description_from_string ("Sans Bold 10"); - current_theme = g_strdup ("Atlanta"); - - init_button_layout(); -#endif /* HAVE_GCONF */ - - init_bindings (); - init_commands (); - init_workspace_names (); -} - - -/****************************************************************************/ -/* Updates. */ -/****************************************************************************/ - -#ifdef HAVE_GCONF - -gboolean (*preference_update_handler[]) (const gchar*, GConfValue*) = { - handle_preference_update_enum, - handle_preference_update_bool, - handle_preference_update_string, - handle_preference_update_int, - NULL -}; - -static void -change_notify (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer user_data) -{ - const char *key; - GConfValue *value; - gint i=0; - - key = gconf_entry_get_key (entry); - value = gconf_entry_get_value (entry); - - /* First, search for a handler that might know what to do. */ - - /* FIXME: When this is all working, since the first item in every - * array is the gchar* of the key, there's no reason we can't - * find the correct record for that key here and save code duplication. - */ - - while (preference_update_handler[i]!=NULL) - { - if (preference_update_handler[i] (key, value)) - goto out; /* Get rid of this eventually */ - - i++; - } - - if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX) || - g_str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX)) - { - if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX)) - { - GSList *list; - - if (value && value->type != GCONF_VALUE_LIST) - { - meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), - key); - goto out; - } - - list = value ? gconf_value_get_list (value) : NULL; - - if (update_key_list_binding (key, list)) - queue_changed (META_PREF_KEYBINDINGS); - } - else - { - const char *str; - - if (value && value->type != GCONF_VALUE_STRING) - { - meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), - key); - goto out; - } - - str = value ? gconf_value_get_string (value) : NULL; - - if (update_key_binding (key, str)) - queue_changed (META_PREF_KEYBINDINGS); - } - } - else if (g_str_has_prefix (key, KEY_COMMAND_PREFIX)) - { - const char *str; - - if (value && value->type != GCONF_VALUE_STRING) - { - meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), - key); - goto out; - } - - str = value ? gconf_value_get_string (value) : NULL; - - if (update_command (key, str)) - queue_changed (META_PREF_COMMANDS); - } - else if (g_str_has_prefix (key, KEY_WORKSPACE_NAME_PREFIX)) - { - const char *str; - - if (value && value->type != GCONF_VALUE_STRING) - { - meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), - key); - goto out; - } - - str = value ? gconf_value_get_string (value) : NULL; - - if (update_workspace_name (key, str)) - queue_changed (META_PREF_WORKSPACE_NAMES); - } - else - { - meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Metacity\n", - key); - } - - out: - /* nothing */ - return; /* AIX compiler wants something after a label like out: */ -} - -static void -cleanup_error (GError **error) -{ - if (*error) - { - meta_warning ("%s\n", (*error)->message); - - g_error_free (*error); - *error = NULL; - } -} - -/* get_bool returns TRUE if *val is filled in, FALSE otherwise */ -/* @@@ probably worth moving this inline; only used once */ -static gboolean -get_bool (const char *key, gboolean *val) -{ - GError *err = NULL; - GConfValue *value; - gboolean filled_in = FALSE; - - value = gconf_client_get (default_client, key, &err); - cleanup_error (&err); - if (value) - { - if (value->type == GCONF_VALUE_BOOL) - { - *val = gconf_value_get_bool (value); - filled_in = TRUE; - } - gconf_value_free (value); - } - - return filled_in; -} - -/** - * Special case: give a warning the first time disable_workarounds - * is turned on. - */ -static void -maybe_give_disable_workarounds_warning (void) -{ - static gboolean first_disable = TRUE; - - if (first_disable && disable_workarounds) - { - first_disable = FALSE; - - meta_warning (_("Workarounds for broken applications disabled. " - "Some applications may not behave properly.\n")); - } -} - -#endif /* HAVE_GCONF */ - -MetaVirtualModifier -meta_prefs_get_mouse_button_mods (void) -{ - return mouse_button_mods; -} - -MetaFocusMode -meta_prefs_get_focus_mode (void) -{ - return focus_mode; -} - -MetaFocusNewWindows -meta_prefs_get_focus_new_windows (void) -{ - return focus_new_windows; -} - -gboolean -meta_prefs_get_raise_on_click (void) -{ - /* Force raise_on_click on for click-to-focus, as requested by Havoc - * in #326156. - */ - return raise_on_click || focus_mode == META_FOCUS_MODE_CLICK; -} - -const char* -meta_prefs_get_theme (void) -{ - return current_theme; -} - -const char* -meta_prefs_get_cursor_theme (void) -{ - return cursor_theme; -} - -int -meta_prefs_get_cursor_size (void) -{ - return cursor_size; -} - - -/****************************************************************************/ -/* Handlers for string preferences. */ -/****************************************************************************/ - -#ifdef HAVE_GCONF - -static void -titlebar_handler (MetaPreference pref, - const gchar *string_value, - gboolean *inform_listeners) -{ - PangoFontDescription *new_desc = NULL; - - if (string_value) - new_desc = pango_font_description_from_string (string_value); - - if (new_desc == NULL) - { - meta_warning (_("Could not parse font description " - "\"%s\" from GConf key %s\n"), - string_value ? string_value : "(null)", - KEY_TITLEBAR_FONT); - - *inform_listeners = FALSE; - - return; - } - - /* Is the new description the same as the old? */ - - if (titlebar_font && - pango_font_description_equal (new_desc, titlebar_font)) - { - pango_font_description_free (new_desc); - *inform_listeners = FALSE; - return; - } - - /* No, so free the old one and put ours in instead. */ - - if (titlebar_font) - pango_font_description_free (titlebar_font); - - titlebar_font = new_desc; - -} - -static void -theme_name_handler (MetaPreference pref, - const gchar *string_value, - gboolean *inform_listeners) -{ - /* Fallback crackrock */ - if (string_value == NULL) - current_theme = g_strdup ("Atlanta"); - else - current_theme = g_strdup (string_value); -} - -static void -mouse_button_mods_handler (MetaPreference pref, - const gchar *string_value, - gboolean *inform_listeners) -{ - MetaVirtualModifier mods; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Mouse button modifier has new gconf value \"%s\"\n", - string_value); - if (string_value && meta_ui_parse_modifier (string_value, &mods)) - { - mouse_button_mods = mods; - } - else - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to parse new gconf value\n"); - - meta_warning (_("\"%s\" found in configuration database is " - "not a valid value for mouse button modifier\n"), - string_value); - - *inform_listeners = FALSE; - } -} - -static gboolean -button_layout_equal (const MetaButtonLayout *a, - const MetaButtonLayout *b) -{ - int i; - - i = 0; - while (i < MAX_BUTTONS_PER_CORNER) - { - if (a->left_buttons[i] != b->left_buttons[i]) - return FALSE; - if (a->right_buttons[i] != b->right_buttons[i]) - return FALSE; - if (a->left_buttons_has_spacer[i] != b->left_buttons_has_spacer[i]) - return FALSE; - if (a->right_buttons_has_spacer[i] != b->right_buttons_has_spacer[i]) - return FALSE; - ++i; - } - - return TRUE; -} - -static MetaButtonFunction -button_function_from_string (const char *str) -{ - /* FIXME: gconf_string_to_enum is the obvious way to do this */ - - if (strcmp (str, "menu") == 0) - return META_BUTTON_FUNCTION_MENU; - else if (strcmp (str, "minimize") == 0) - return META_BUTTON_FUNCTION_MINIMIZE; - else if (strcmp (str, "maximize") == 0) - return META_BUTTON_FUNCTION_MAXIMIZE; - else if (strcmp (str, "close") == 0) - return META_BUTTON_FUNCTION_CLOSE; - else if (strcmp (str, "shade") == 0) - return META_BUTTON_FUNCTION_SHADE; - else if (strcmp (str, "above") == 0) - return META_BUTTON_FUNCTION_ABOVE; - else if (strcmp (str, "stick") == 0) - return META_BUTTON_FUNCTION_STICK; - else - /* don't know; give up */ - return META_BUTTON_FUNCTION_LAST; -} - -static MetaButtonFunction -button_opposite_function (MetaButtonFunction ofwhat) -{ - switch (ofwhat) - { - case META_BUTTON_FUNCTION_SHADE: - return META_BUTTON_FUNCTION_UNSHADE; - case META_BUTTON_FUNCTION_UNSHADE: - return META_BUTTON_FUNCTION_SHADE; - - case META_BUTTON_FUNCTION_ABOVE: - return META_BUTTON_FUNCTION_UNABOVE; - case META_BUTTON_FUNCTION_UNABOVE: - return META_BUTTON_FUNCTION_ABOVE; - - case META_BUTTON_FUNCTION_STICK: - return META_BUTTON_FUNCTION_UNSTICK; - case META_BUTTON_FUNCTION_UNSTICK: - return META_BUTTON_FUNCTION_STICK; - - default: - return META_BUTTON_FUNCTION_LAST; - } -} - -static void -button_layout_handler (MetaPreference pref, - const gchar *string_value, - gboolean *inform_listeners) -{ - MetaButtonLayout new_layout; - char **sides = NULL; - int i; - - /* We need to ignore unknown button functions, for - * compat with future versions - */ - - if (string_value) - sides = g_strsplit (string_value, ":", 2); - - if (sides != NULL && sides[0] != NULL) - { - char **buttons; - int b; - gboolean used[META_BUTTON_FUNCTION_LAST]; - - i = 0; - while (i < META_BUTTON_FUNCTION_LAST) - { - used[i] = FALSE; - new_layout.left_buttons_has_spacer[i] = FALSE; - ++i; - } - - buttons = g_strsplit (sides[0], ",", -1); - i = 0; - b = 0; - while (buttons[b] != NULL) - { - MetaButtonFunction f = button_function_from_string (buttons[b]); - if (i > 0 && strcmp("spacer", buttons[b]) == 0) - { - new_layout.left_buttons_has_spacer[i-1] = TRUE; - f = button_opposite_function (f); - - if (f != META_BUTTON_FUNCTION_LAST) - { - new_layout.left_buttons_has_spacer[i-2] = TRUE; - } - } - else - { - if (f != META_BUTTON_FUNCTION_LAST && !used[f]) - { - new_layout.left_buttons[i] = f; - used[f] = TRUE; - ++i; - - f = button_opposite_function (f); - - if (f != META_BUTTON_FUNCTION_LAST) - new_layout.left_buttons[i++] = f; - - } - else - { - meta_topic (META_DEBUG_PREFS, "Ignoring unknown or already-used button name \"%s\"\n", - buttons[b]); - } - } - - ++b; - } - - new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST; - new_layout.left_buttons_has_spacer[i] = FALSE; - - g_strfreev (buttons); - } - - if (sides != NULL && sides[0] != NULL && sides[1] != NULL) - { - char **buttons; - int b; - gboolean used[META_BUTTON_FUNCTION_LAST]; - - i = 0; - while (i < META_BUTTON_FUNCTION_LAST) - { - used[i] = FALSE; - new_layout.right_buttons_has_spacer[i] = FALSE; - ++i; - } - - buttons = g_strsplit (sides[1], ",", -1); - i = 0; - b = 0; - while (buttons[b] != NULL) - { - MetaButtonFunction f = button_function_from_string (buttons[b]); - if (i > 0 && strcmp("spacer", buttons[b]) == 0) - { - new_layout.right_buttons_has_spacer[i-1] = TRUE; - f = button_opposite_function (f); - if (f != META_BUTTON_FUNCTION_LAST) - { - new_layout.right_buttons_has_spacer[i-2] = TRUE; - } - } - else - { - if (f != META_BUTTON_FUNCTION_LAST && !used[f]) - { - new_layout.right_buttons[i] = f; - used[f] = TRUE; - ++i; - - f = button_opposite_function (f); - - if (f != META_BUTTON_FUNCTION_LAST) - new_layout.right_buttons[i++] = f; - - } - else - { - meta_topic (META_DEBUG_PREFS, "Ignoring unknown or already-used button name \"%s\"\n", - buttons[b]); - } - } - - ++b; - } - - new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; - new_layout.right_buttons_has_spacer[i] = FALSE; - - g_strfreev (buttons); - } - - g_strfreev (sides); - - /* Invert the button layout for RTL languages */ - if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - { - MetaButtonLayout rtl_layout; - int j; - - for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++); - for (j = 0; j < i; j++) - { - rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1]; - if (j == 0) - rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1]; - else - rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1]; - } - rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST; - rtl_layout.right_buttons_has_spacer[j] = FALSE; - - for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++); - for (j = 0; j < i; j++) - { - rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1]; - if (j == 0) - rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1]; - else - rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1]; - } - rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST; - rtl_layout.left_buttons_has_spacer[j] = FALSE; - - new_layout = rtl_layout; - } - - if (button_layout_equal (&button_layout, &new_layout)) - { - /* Same as before, so duck out */ - *inform_listeners = FALSE; - } - else - { - button_layout = new_layout; - } -} - -#endif /* HAVE_GCONF */ - -const PangoFontDescription* -meta_prefs_get_titlebar_font (void) -{ - if (use_system_font) - return NULL; - else - return titlebar_font; -} - -int -meta_prefs_get_num_workspaces (void) -{ - return num_workspaces; -} - -gboolean -meta_prefs_get_application_based (void) -{ - return FALSE; /* For now, we never want this to do anything */ - - return application_based; -} - -gboolean -meta_prefs_get_disable_workarounds (void) -{ - return disable_workarounds; -} - -#ifdef HAVE_GCONF -#define MAX_REASONABLE_AUTO_RAISE_DELAY 10000 - -#endif /* HAVE_GCONF */ - -#ifdef WITH_VERBOSE_MODE -const char* -meta_preference_to_string (MetaPreference pref) -{ - /* FIXME: another case for gconf_string_to_enum */ - switch (pref) - { - case META_PREF_MOUSE_BUTTON_MODS: - return "MOUSE_BUTTON_MODS"; - - case META_PREF_FOCUS_MODE: - return "FOCUS_MODE"; - - case META_PREF_FOCUS_NEW_WINDOWS: - return "FOCUS_NEW_WINDOWS"; - - case META_PREF_RAISE_ON_CLICK: - return "RAISE_ON_CLICK"; - - case META_PREF_THEME: - return "THEME"; - - case META_PREF_TITLEBAR_FONT: - return "TITLEBAR_FONT"; - - case META_PREF_NUM_WORKSPACES: - return "NUM_WORKSPACES"; - - case META_PREF_APPLICATION_BASED: - return "APPLICATION_BASED"; - - case META_PREF_KEYBINDINGS: - return "KEYBINDINGS"; - - case META_PREF_DISABLE_WORKAROUNDS: - return "DISABLE_WORKAROUNDS"; - - case META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR: - return "ACTION_DOUBLE_CLICK_TITLEBAR"; - - case META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR: - return "ACTION_MIDDLE_CLICK_TITLEBAR"; - - case META_PREF_ACTION_RIGHT_CLICK_TITLEBAR: - return "ACTION_RIGHT_CLICK_TITLEBAR"; - - case META_PREF_AUTO_RAISE: - return "AUTO_RAISE"; - - case META_PREF_AUTO_RAISE_DELAY: - return "AUTO_RAISE_DELAY"; - - case META_PREF_COMMANDS: - return "COMMANDS"; - - case META_PREF_TERMINAL_COMMAND: - return "TERMINAL_COMMAND"; - - case META_PREF_BUTTON_LAYOUT: - return "BUTTON_LAYOUT"; - - case META_PREF_WORKSPACE_NAMES: - return "WORKSPACE_NAMES"; - - case META_PREF_VISUAL_BELL: - return "VISUAL_BELL"; - - case META_PREF_AUDIBLE_BELL: - return "AUDIBLE_BELL"; - - case META_PREF_VISUAL_BELL_TYPE: - return "VISUAL_BELL_TYPE"; - - case META_PREF_REDUCED_RESOURCES: - return "REDUCED_RESOURCES"; - - case META_PREF_GNOME_ACCESSIBILITY: - return "GNOME_ACCESSIBILTY"; - - case META_PREF_GNOME_ANIMATIONS: - return "GNOME_ANIMATIONS"; - - case META_PREF_CURSOR_THEME: - return "CURSOR_THEME"; - - case META_PREF_CURSOR_SIZE: - return "CURSOR_SIZE"; - - case META_PREF_COMPOSITING_MANAGER: - return "COMPOSITING_MANAGER"; - } - - return "(unknown)"; -} -#endif /* WITH_VERBOSE_MODE */ - -void -meta_prefs_set_num_workspaces (int n_workspaces) -{ -#ifdef HAVE_GCONF - GError *err; - - if (default_client == NULL) - return; - - if (n_workspaces < 1) - n_workspaces = 1; - if (n_workspaces > MAX_REASONABLE_WORKSPACES) - n_workspaces = MAX_REASONABLE_WORKSPACES; - - err = NULL; - gconf_client_set_int (default_client, - KEY_NUM_WORKSPACES, - n_workspaces, - &err); - - if (err) - { - meta_warning (_("Error setting number of workspaces to %d: %s\n"), - num_workspaces, - err->message); - g_error_free (err); - } -#endif /* HAVE_GCONF */ -} - -#define keybind(name, handler, param, flags, stroke, description) \ - { #name, NULL, !!(flags & BINDING_REVERSES), !!(flags & BINDING_PER_WINDOW) }, -static MetaKeyPref key_bindings[] = { -#include "all-keybindings.h" - { NULL, NULL, FALSE } -}; -#undef keybind - -#ifndef HAVE_GCONF - -/** - * A type to map names of keybindings (such as "switch_windows") - * to the binding strings themselves (such as "<Alt>Tab"). - * It exists only when GConf is turned off in ./configure and - * functions as a sort of ersatz GConf. - */ -typedef struct -{ - const char *name; - const char *keybinding; -} MetaSimpleKeyMapping; - -/* FIXME: This would be neater if the array only contained entries whose - * default keystroke was non-null. You COULD do this by defining - * ONLY_BOUND_BY_DEFAULT around various blocks at the cost of making - * the bindings file way more complicated. However, we could stop this being - * data and move it into code. Then the compiler would optimise away - * the problem lines. - */ - -#define keybind(name, handler, param, flags, stroke, description) \ - { #name, stroke }, - -static MetaSimpleKeyMapping key_string_bindings[] = { -#include "all-keybindings.h" - { NULL, NULL } -}; -#undef keybind - -#endif /* NOT HAVE_GCONF */ - -static void -init_bindings (void) -{ -#ifdef HAVE_GCONF - int i = 0; - GError *err; - - while (key_bindings[i].name) - { - GSList *list_val, *tmp; - char *str_val; - char *key; - - key = g_strconcat (key_bindings[i].per_window? - KEY_WINDOW_BINDINGS_PREFIX: - KEY_SCREEN_BINDINGS_PREFIX, - "/", - key_bindings[i].name, NULL); - - err = NULL; - str_val = gconf_client_get_string (default_client, key, &err); - cleanup_error (&err); - - update_binding (&key_bindings[i], str_val); - - g_free (str_val); - g_free (key); - - key = g_strconcat (key_bindings[i].per_window? - KEY_WINDOW_BINDINGS_PREFIX: - KEY_SCREEN_BINDINGS_PREFIX, - "/", - key_bindings[i].name, - KEY_LIST_BINDINGS_SUFFIX, NULL); - - err = NULL; - - list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err); - cleanup_error (&err); - - update_list_binding (&key_bindings[i], list_val, META_LIST_OF_STRINGS); - - tmp = list_val; - while (tmp) - { - g_free (tmp->data); - tmp = tmp->next; - } - g_slist_free (list_val); - g_free (key); - - ++i; - } -#else /* HAVE_GCONF */ - int i = 0; - int which = 0; - while (key_string_bindings[i].name) - { - if (key_string_bindings[i].keybinding == NULL) { - ++i; - continue; - } - - while (strcmp(key_bindings[which].name, - key_string_bindings[i].name) != 0) - which++; - - /* Set the binding */ - update_binding (&key_bindings[which], - key_string_bindings[i].keybinding); - - ++i; - } -#endif /* HAVE_GCONF */ -} - -static void -init_commands (void) -{ -#ifdef HAVE_GCONF - int i; - GError *err; - - i = 0; - while (i < MAX_COMMANDS) - { - char *str_val; - char *key; - - key = meta_prefs_get_gconf_key_for_command (i); - - err = NULL; - str_val = gconf_client_get_string (default_client, key, &err); - cleanup_error (&err); - - update_command (key, str_val); - - g_free (str_val); - g_free (key); - - ++i; - } -#else - int i; - for (i = 0; i < MAX_COMMANDS; i++) - commands[i] = NULL; -#endif /* HAVE_GCONF */ -} - -static void -init_workspace_names (void) -{ -#ifdef HAVE_GCONF - int i; - GError *err; - - i = 0; - while (i < MAX_REASONABLE_WORKSPACES) - { - char *str_val; - char *key; - - key = gconf_key_for_workspace_name (i); - - err = NULL; - str_val = gconf_client_get_string (default_client, key, &err); - cleanup_error (&err); - - update_workspace_name (key, str_val); - - g_assert (workspace_names[i] != NULL); - - g_free (str_val); - g_free (key); - - ++i; - } -#else - int i; - for (i = 0; i < MAX_REASONABLE_WORKSPACES; i++) - workspace_names[i] = g_strdup_printf (_("Workspace %d"), i + 1); - - meta_topic (META_DEBUG_PREFS, - "Initialized workspace names\n"); -#endif /* HAVE_GCONF */ -} - -static gboolean -update_binding (MetaKeyPref *binding, - const char *value) -{ - unsigned int keysym; - unsigned int keycode; - MetaVirtualModifier mods; - MetaKeyCombo *combo; - gboolean changed; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Binding \"%s\" has new gconf value \"%s\"\n", - binding->name, value ? value : "none"); - - keysym = 0; - keycode = 0; - mods = 0; - if (value) - { - if (!meta_ui_parse_accelerator (value, &keysym, &keycode, &mods)) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to parse new gconf value\n"); - meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"), - value, binding->name); - - return FALSE; - } - } - - /* If there isn't already a first element, make one. */ - if (!binding->bindings) - { - MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo)); - binding->bindings = g_slist_alloc(); - binding->bindings->data = blank; - } - - combo = binding->bindings->data; - -#ifdef HAVE_GCONF - /* Bug 329676: Bindings which can be shifted must not have no modifiers, - * nor only SHIFT as a modifier. - */ - - if (binding->add_shift && - 0 != keysym && - (META_VIRTUAL_SHIFT_MASK == mods || 0 == mods)) - { - gchar *old_setting; - gchar *key; - GError *err = NULL; - - meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier " - "such as Ctrl or Alt.\n", - binding->name, - value); - - old_setting = meta_ui_accelerator_name (combo->keysym, - combo->modifiers); - - if (!strcmp(old_setting, value)) - { - /* We were about to set it to the same value - * that it had originally! This must be caused - * by getting an invalid string back from - * meta_ui_accelerator_name. Bail out now - * so we don't get into an infinite loop. - */ - g_free (old_setting); - return TRUE; - } - - meta_warning ("Reverting \"%s\" to %s.\n", - binding->name, - old_setting); - - /* FIXME: add_shift is currently screen_bindings only, but - * there's no really good reason it should always be. - * So we shouldn't blindly add KEY_SCREEN_BINDINGS_PREFIX - * onto here. - */ - key = g_strconcat (KEY_SCREEN_BINDINGS_PREFIX, "/", - binding->name, NULL); - - gconf_client_set_string (gconf_client_get_default (), - key, old_setting, &err); - - if (err) - { - meta_warning ("Error while reverting keybinding: %s\n", - err->message); - g_error_free (err); - err = NULL; - } - - g_free (old_setting); - g_free (key); - - /* The call to gconf_client_set_string() will cause this function - * to be called again with the new value, so there's no need to - * carry on. - */ - return TRUE; - } -#endif - - changed = FALSE; - if (keysym != combo->keysym || - keycode != combo->keycode || - mods != combo->modifiers) - { - changed = TRUE; - - combo->keysym = keysym; - combo->keycode = keycode; - combo->modifiers = mods; - - meta_topic (META_DEBUG_KEYBINDINGS, - "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n", - binding->name, combo->keysym, combo->keycode, - combo->modifiers); - } - else - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Keybinding for \"%s\" is unchanged\n", binding->name); - } - - return changed; -} - -#ifdef HAVE_GCONF -static gboolean -update_list_binding (MetaKeyPref *binding, - GSList *value, - MetaStringListType type_of_value) -{ - unsigned int keysym; - unsigned int keycode; - MetaVirtualModifier mods; - gboolean changed = FALSE; - const gchar *pref_string; - GSList *pref_iterator = value, *tmp; - MetaKeyCombo *combo; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Binding \"%s\" has new gconf value\n", - binding->name); - - if (binding->bindings == NULL) - { - /* We need to insert a dummy element into the list, because the first - * element is the one governed by update_binding. We only handle the - * subsequent elements. - */ - MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo)); - binding->bindings = g_slist_alloc(); - binding->bindings->data = blank; - } - - /* Okay, so, we're about to provide a new list of key combos for this - * action. Delete any pre-existing list. - */ - tmp = binding->bindings->next; - while (tmp) - { - g_free (tmp->data); - tmp = tmp->next; - } - g_slist_free (binding->bindings->next); - binding->bindings->next = NULL; - - while (pref_iterator) - { - keysym = 0; - keycode = 0; - mods = 0; - - if (!pref_iterator->data) - { - pref_iterator = pref_iterator->next; - continue; - } - - switch (type_of_value) - { - case META_LIST_OF_STRINGS: - pref_string = pref_iterator->data; - break; - case META_LIST_OF_GCONFVALUE_STRINGS: - pref_string = gconf_value_get_string (pref_iterator->data); - break; - default: - g_assert_not_reached (); - } - - if (!meta_ui_parse_accelerator (pref_string, &keysym, &keycode, &mods)) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to parse new gconf value\n"); - meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"), - pref_string, binding->name); - - /* Should we remove this value from the list in gconf? */ - pref_iterator = pref_iterator->next; - continue; - } - - /* Bug 329676: Bindings which can be shifted must not have no modifiers, - * nor only SHIFT as a modifier. - */ - - if (binding->add_shift && - 0 != keysym && - (META_VIRTUAL_SHIFT_MASK == mods || 0 == mods)) - { - meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier " - "such as Ctrl or Alt.\n", - binding->name, - pref_string); - - /* Should we remove this value from the list in gconf? */ - - pref_iterator = pref_iterator->next; - continue; - } - - changed = TRUE; - - combo = g_malloc0 (sizeof (MetaKeyCombo)); - combo->keysym = keysym; - combo->keycode = keycode; - combo->modifiers = mods; - binding->bindings->next = g_slist_prepend (binding->bindings->next, combo); - - meta_topic (META_DEBUG_KEYBINDINGS, - "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n", - binding->name, keysym, keycode, mods); - - pref_iterator = pref_iterator->next; - } - return changed; -} - -static const gchar* -relative_key (const gchar* key) -{ - const gchar* end; - - end = strrchr (key, '/'); - - ++end; - - return end; -} - -/* Return value is TRUE if a preference changed and we need to - * notify - */ -static gboolean -find_and_update_binding (MetaKeyPref *bindings, - const char *name, - const char *value) -{ - const char *key; - int i; - - if (*name == '/') - key = relative_key (name); - else - key = name; - - i = 0; - while (bindings[i].name && - strcmp (key, bindings[i].name) != 0) - ++i; - - if (bindings[i].name) - return update_binding (&bindings[i], value); - else - return FALSE; -} - -static gboolean -update_key_binding (const char *name, - const char *value) -{ - return find_and_update_binding (key_bindings, name, value); -} - -static gboolean -find_and_update_list_binding (MetaKeyPref *bindings, - const char *name, - GSList *value) -{ - const char *key; - int i; - gchar *name_without_suffix = g_strdup(name); - - name_without_suffix[strlen(name_without_suffix) - strlen(KEY_LIST_BINDINGS_SUFFIX)] = 0; - - if (*name_without_suffix == '/') - key = relative_key (name_without_suffix); - else - key = name_without_suffix; - - i = 0; - while (bindings[i].name && - strcmp (key, bindings[i].name) != 0) - ++i; - - g_free (name_without_suffix); - - if (bindings[i].name) - return update_list_binding (&bindings[i], value, META_LIST_OF_GCONFVALUE_STRINGS); - else - return FALSE; -} - -static gboolean -update_key_list_binding (const char *name, - GSList *value) -{ - return find_and_update_list_binding (key_bindings, name, value); -} - -static gboolean -update_command (const char *name, - const char *value) -{ - char *p; - int i; - - p = strrchr (name, '_'); - if (p == NULL) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Command %s has no underscore?\n", name); - return FALSE; - } - - ++p; - - if (g_ascii_isdigit (*p)) - { - i = atoi (p); - i -= 1; /* count from 0 not 1 */ - } - else - { - p = strrchr (name, '/'); - ++p; - - if (strcmp (p, "command_screenshot") == 0) - { - i = SCREENSHOT_COMMAND_IDX; - } - else if (strcmp (p, "command_window_screenshot") == 0) - { - i = WIN_SCREENSHOT_COMMAND_IDX; - } - else - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Command %s doesn't end in number?\n", name); - return FALSE; - } - } - - if (i >= MAX_COMMANDS) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Command %d is too highly numbered, ignoring\n", i); - return FALSE; - } - - if ((commands[i] == NULL && value == NULL) || - (commands[i] && value && strcmp (commands[i], value) == 0)) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Command %d is unchanged\n", i); - return FALSE; - } - - g_free (commands[i]); - commands[i] = g_strdup (value); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Updated command %d to \"%s\"\n", - i, commands[i] ? commands[i] : "none"); - - return TRUE; -} - -#endif /* HAVE_GCONF */ - -const char* -meta_prefs_get_command (int i) -{ - g_return_val_if_fail (i >= 0 && i < MAX_COMMANDS, NULL); - - return commands[i]; -} - -char* -meta_prefs_get_gconf_key_for_command (int i) -{ - char *key; - - switch (i) - { - case SCREENSHOT_COMMAND_IDX: - key = g_strdup (KEY_COMMAND_PREFIX "screenshot"); - break; - case WIN_SCREENSHOT_COMMAND_IDX: - key = g_strdup (KEY_COMMAND_PREFIX "window_screenshot"); - break; - default: - key = g_strdup_printf (KEY_COMMAND_PREFIX"%d", i + 1); - break; - } - - return key; -} - -const char* -meta_prefs_get_terminal_command (void) -{ - return terminal_command; -} - -const char* -meta_prefs_get_gconf_key_for_terminal_command (void) -{ - return KEY_TERMINAL_COMMAND; -} - -#ifdef HAVE_GCONF -static gboolean -update_workspace_name (const char *name, - const char *value) -{ - char *p; - int i; - - p = strrchr (name, '_'); - if (p == NULL) - { - meta_topic (META_DEBUG_PREFS, - "Workspace name %s has no underscore?\n", name); - return FALSE; - } - - ++p; - - if (!g_ascii_isdigit (*p)) - { - meta_topic (META_DEBUG_PREFS, - "Workspace name %s doesn't end in number?\n", name); - return FALSE; - } - - i = atoi (p); - i -= 1; /* count from 0 not 1 */ - - if (i >= MAX_REASONABLE_WORKSPACES) - { - meta_topic (META_DEBUG_PREFS, - "Workspace name %d is too highly numbered, ignoring\n", i); - return FALSE; - } - - if (workspace_names[i] && value && strcmp (workspace_names[i], value) == 0) - { - meta_topic (META_DEBUG_PREFS, - "Workspace name %d is unchanged\n", i); - return FALSE; - } - - /* This is a bad hack. We have to treat empty string as - * "unset" because the root window property can't contain - * null. So it gets empty string instead and we don't want - * that to result in setting the empty string as a value that - * overrides "unset". - */ - if (value != NULL && *value != '\0') - { - g_free (workspace_names[i]); - workspace_names[i] = g_strdup (value); - } - else - { - /* use a default name */ - char *d; - - d = g_strdup_printf (_("Workspace %d"), i + 1); - if (workspace_names[i] && strcmp (workspace_names[i], d) == 0) - { - g_free (d); - return FALSE; - } - else - { - g_free (workspace_names[i]); - workspace_names[i] = d; - } - } - - meta_topic (META_DEBUG_PREFS, - "Updated workspace name %d to \"%s\"\n", - i, workspace_names[i] ? workspace_names[i] : "none"); - - return TRUE; -} -#endif /* HAVE_GCONF */ - -const char* -meta_prefs_get_workspace_name (int i) -{ - g_return_val_if_fail (i >= 0 && i < MAX_REASONABLE_WORKSPACES, NULL); - - g_assert (workspace_names[i] != NULL); - - meta_topic (META_DEBUG_PREFS, - "Getting workspace name for %d: \"%s\"\n", - i, workspace_names[i]); - - return workspace_names[i]; -} - -void -meta_prefs_change_workspace_name (int i, - const char *name) -{ -#ifdef HAVE_GCONF - char *key; - GError *err; - - g_return_if_fail (i >= 0 && i < MAX_REASONABLE_WORKSPACES); - - meta_topic (META_DEBUG_PREFS, - "Changing name of workspace %d to %s\n", - i, name ? name : "none"); - - /* This is a bad hack. We have to treat empty string as - * "unset" because the root window property can't contain - * null. So it gets empty string instead and we don't want - * that to result in setting the empty string as a value that - * overrides "unset". - */ - if (name && *name == '\0') - name = NULL; - - if ((name == NULL && workspace_names[i] == NULL) || - (name && workspace_names[i] && strcmp (name, workspace_names[i]) == 0)) - { - meta_topic (META_DEBUG_PREFS, - "Workspace %d already has name %s\n", - i, name ? name : "none"); - return; - } - - key = gconf_key_for_workspace_name (i); - - err = NULL; - if (name != NULL) - gconf_client_set_string (default_client, - key, name, - &err); - else - gconf_client_unset (default_client, - key, &err); - - - if (err) - { - meta_warning (_("Error setting name for workspace %d to \"%s\": %s\n"), - i, name ? name : "none", - err->message); - g_error_free (err); - } - - g_free (key); -#else - g_free (workspace_names[i]); - workspace_names[i] = g_strdup (name); -#endif /* HAVE_GCONF */ -} - -#ifdef HAVE_GCONF -static char* -gconf_key_for_workspace_name (int i) -{ - char *key; - - key = g_strdup_printf (KEY_WORKSPACE_NAME_PREFIX"%d", i + 1); - - return key; -} -#endif /* HAVE_GCONF */ - -void -meta_prefs_get_button_layout (MetaButtonLayout *button_layout_p) -{ - *button_layout_p = button_layout; -} - -gboolean -meta_prefs_get_visual_bell (void) -{ - return provide_visual_bell; -} - -gboolean -meta_prefs_bell_is_audible (void) -{ - return bell_is_audible; -} - -MetaVisualBellType -meta_prefs_get_visual_bell_type (void) -{ - return visual_bell_type; -} - -void -meta_prefs_get_key_bindings (const MetaKeyPref **bindings, - int *n_bindings) -{ - - *bindings = key_bindings; - *n_bindings = (int) G_N_ELEMENTS (key_bindings) - 1; -} - -MetaActionTitlebar -meta_prefs_get_action_double_click_titlebar (void) -{ - return action_double_click_titlebar; -} - -MetaActionTitlebar -meta_prefs_get_action_middle_click_titlebar (void) -{ - return action_middle_click_titlebar; -} - -MetaActionTitlebar -meta_prefs_get_action_right_click_titlebar (void) -{ - return action_right_click_titlebar; -} - -gboolean -meta_prefs_get_auto_raise (void) -{ - return auto_raise; -} - -int -meta_prefs_get_auto_raise_delay (void) -{ - return auto_raise_delay; -} - -gboolean -meta_prefs_get_reduced_resources (void) -{ - return reduced_resources; -} - -gboolean -meta_prefs_get_gnome_accessibility () -{ - return gnome_accessibility; -} - -gboolean -meta_prefs_get_gnome_animations () -{ - return gnome_animations; -} - -MetaKeyBindingAction -meta_prefs_get_keybinding_action (const char *name) -{ - int i; - - i = G_N_ELEMENTS (key_bindings) - 2; /* -2 for dummy entry at end */ - while (i >= 0) - { - if (strcmp (key_bindings[i].name, name) == 0) - return (MetaKeyBindingAction) i; - - --i; - } - - return META_KEYBINDING_ACTION_NONE; -} - -/* This is used by the menu system to decide what key binding - * to display next to an option. We return the first non-disabled - * binding, if any. - */ -void -meta_prefs_get_window_binding (const char *name, - unsigned int *keysym, - MetaVirtualModifier *modifiers) -{ - int i; - - i = G_N_ELEMENTS (key_bindings) - 2; /* -2 for dummy entry at end */ - while (i >= 0) - { - if (key_bindings[i].per_window && - strcmp (key_bindings[i].name, name) == 0) - { - GSList *s = key_bindings[i].bindings; - - while (s) - { - MetaKeyCombo *c = s->data; - - if (c->keysym!=0 || c->modifiers!=0) - { - *keysym = c->keysym; - *modifiers = c->modifiers; - return; - } - - s = s->next; - } - - /* Not found; return the disabled value */ - *keysym = *modifiers = 0; - return; - } - - --i; - } - - g_assert_not_reached (); -} - -gboolean -meta_prefs_get_compositing_manager (void) -{ - return compositing_manager; -} - -void -meta_prefs_set_compositing_manager (gboolean whether) -{ -#ifdef HAVE_GCONF - GError *err = NULL; - - gconf_client_set_bool (default_client, - KEY_COMPOSITOR, - whether, - &err); - - if (err) - { - meta_warning (_("Error setting compositor status: %s\n"), - err->message); - g_error_free (err); - } -#else - compositing_manager = whether; -#endif -} - -#ifndef HAVE_GCONF -static void -init_button_layout(void) -{ - MetaButtonLayout button_layout_ltr = { - { - /* buttons in the group on the left side */ - META_BUTTON_FUNCTION_MENU, - META_BUTTON_FUNCTION_LAST - }, - { - /* buttons in the group on the right side */ - META_BUTTON_FUNCTION_MINIMIZE, - META_BUTTON_FUNCTION_MAXIMIZE, - META_BUTTON_FUNCTION_CLOSE, - META_BUTTON_FUNCTION_LAST - } - }; - MetaButtonLayout button_layout_rtl = { - { - /* buttons in the group on the left side */ - META_BUTTON_FUNCTION_CLOSE, - META_BUTTON_FUNCTION_MAXIMIZE, - META_BUTTON_FUNCTION_MINIMIZE, - META_BUTTON_FUNCTION_LAST - }, - { - /* buttons in the group on the right side */ - META_BUTTON_FUNCTION_MENU, - META_BUTTON_FUNCTION_LAST - } - }; - - button_layout = meta_ui_get_direction() == META_UI_DIRECTION_LTR ? - button_layout_ltr : button_layout_rtl; -}; - -#endif diff --git a/src/core/schema-bindings.c b/src/core/schema-bindings.c deleted file mode 100644 index 77a42899..00000000 --- a/src/core/schema-bindings.c +++ /dev/null @@ -1,191 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Thomas Thurman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** \file Schema bindings generator. - * - * This program simply takes the items given in the binding list in - * all-keybindings.h and turns them into a portion of - * the GConf .schemas file. - * - * FIXME: also need to make 50-metacity-desktop-key.xml - */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> - -#include <glib.h> -#include "config.h" - -#define _(x) x - -static void single_stanza (gboolean is_window, const char *name, - const char *default_value, - gboolean can_reverse, - const char *description); - -char *about_keybindings, *about_reversible_keybindings; - -char *source_filename, *target_filename; -FILE *source_file, *target_file; - -static void -single_stanza (gboolean is_window, const char *name, - const char *default_value, - gboolean can_reverse, - const char *description) -{ - char *keybinding_type = is_window? "window": "global"; - char *escaped_default_value, *escaped_description; - - if (description==NULL) - return; /* it must be undocumented, so it can't go in this table */ - - escaped_description = g_markup_escape_text (description, -1); - escaped_default_value = default_value==NULL? "disabled": - g_markup_escape_text (default_value, -1); - - fprintf (target_file, " <schema>\n"); - fprintf (target_file, " <key>/schemas/apps/metacity/%s_keybindings/%s</key>\n", - keybinding_type, name); - fprintf (target_file, " <applyto>/apps/metacity/%s_keybindings/%s</applyto>\n", - keybinding_type, name); - fprintf (target_file, " <owner>metacity</owner>\n"); - fprintf (target_file, " <type>string</type>\n"); - fprintf (target_file, " <default>%s</default>\n", escaped_default_value); - - fprintf (target_file, " <locale name=\"C\">\n"); - fprintf (target_file, " <short>%s</short>\n", description); - fprintf (target_file, " <long>%s</long>\n", - can_reverse? about_reversible_keybindings: - about_keybindings); - fprintf (target_file, " </locale>\n"); - fprintf (target_file, " </schema>\n\n"); - - g_free (escaped_description); - - if (default_value!=NULL) - g_free (escaped_default_value); -} - -static void produce_bindings (); - -static void -produce_bindings () -{ - /* 10240 is ridiculous overkill; we're writing the input file and - * the lines are always 80 chars or less. - */ - char buffer[10240]; - - source_file = fopen(source_filename, "r"); - - if (!source_file) - { - g_error ("Cannot compile without %s: %s\n", - source_filename, strerror (errno)); - } - - target_file = fopen(target_filename, "w"); - - if (!target_file) - { - g_error ("Cannot create %s: %s\n", - target_filename, strerror (errno)); - } - - while (fgets (buffer, sizeof (buffer), source_file)) - { - if (strstr (buffer, "<!-- GENERATED -->")) - break; - - fprintf (target_file, "%s", buffer); - } - - if (!feof (source_file)) - { -#define keybind(name, handler, param, flags, stroke, description) \ - single_stanza ( \ - flags & BINDING_PER_WINDOW, \ - #name, \ - stroke, \ - flags & BINDING_REVERSES, \ - description); -#include "all-keybindings.h" -#undef keybind - } - - while (fgets (buffer, sizeof (buffer), source_file)) - fprintf (target_file, "%s", buffer); - - if (fclose (source_file)!=0) - g_error ("Cannot close %s: %s\n", - source_filename, strerror (errno)); - - if (fclose (target_file)!=0) - g_error ("Cannot close %s: %s\n", - target_filename, strerror (errno)); -} - -int -main (int argc, char **argv) -{ - if (argc!=3) - { - g_error ("Syntax: %s <source.in.in> <target.in>\n", argv[0]); - } - - source_filename = argv[1]; - target_filename = argv[2]; - - /* Translators: Please don't translate "Control", "Shift", etc, since these - * are hardcoded (in gtk/gtkaccelgroup.c; it's not metacity's fault). - * "disabled" must also stay as it is. - */ - about_keybindings = g_markup_escape_text(_( \ - "The format looks like \"<Control>a\" or <Shift><Alt>F1\".\n\n"\ - "The parser is fairly liberal and allows "\ - "lower or upper case, and also abbreviations such as \"<Ctl>\" and " \ - "\"<Ctrl>\". If you set the option to the special string " \ - "\"disabled\", then there will be no keybinding for this action."), - -1); - - about_reversible_keybindings = g_markup_escape_text(_( \ - "The format looks like \"<Control>a\" or <Shift><Alt>F1\".\n\n"\ - "The parser is fairly liberal and allows "\ - "lower or upper case, and also abbreviations such as \"<Ctl>\" and " \ - "\"<Ctrl>\". If you set the option to the special string " \ - "\"disabled\", then there will be no keybinding for this action.\n\n"\ - "This keybinding may be reversed by holding down the \"shift\" key; " - "therefore, \"shift\" cannot be one of the keys it uses."), - -1); - - produce_bindings (); - - g_free (about_keybindings); - g_free (about_reversible_keybindings); - - return 0; -} - -/* eof schema-bindings.c */ - diff --git a/src/core/screen-private.h b/src/core/screen-private.h deleted file mode 100644 index d9de2f53..00000000 --- a/src/core/screen-private.h +++ /dev/null @@ -1,225 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file screen-private.h Screens which Metacity manages - * - * Managing X screens. - * This file contains methods on this class which are available to - * routines in core but not outside it. (See screen.h for the routines - * which the rest of the world is allowed to use.) - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_SCREEN_PRIVATE_H -#define META_SCREEN_PRIVATE_H - -#include "display-private.h" -#include "screen.h" -#include <X11/Xutil.h> -#include "ui.h" - -typedef struct _MetaXineramaScreenInfo MetaXineramaScreenInfo; - -struct _MetaXineramaScreenInfo -{ - int number; - MetaRectangle rect; -}; - -typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window, - gpointer user_data); - -typedef enum -{ - META_SCREEN_TOPLEFT, - META_SCREEN_TOPRIGHT, - META_SCREEN_BOTTOMLEFT, - META_SCREEN_BOTTOMRIGHT -} MetaScreenCorner; - -typedef enum -{ - META_SCREEN_UP, - META_SCREEN_DOWN, - META_SCREEN_LEFT, - META_SCREEN_RIGHT -} MetaScreenDirection; - -#define META_WIREFRAME_XOR_LINE_WIDTH 2 - -struct _MetaScreen -{ - MetaDisplay *display; - int number; - char *screen_name; - Screen *xscreen; - Window xroot; - int default_depth; - Visual *default_xvisual; - MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */ - MetaUI *ui; - MetaTabPopup *tab_popup; - - MetaWorkspace *active_workspace; - - /* This window holds the focus when we don't want to focus - * any actual clients - */ - Window no_focus_window; - - GList *workspaces; - - MetaStack *stack; - - MetaCursor current_cursor; - - Window flash_window; - - Window wm_sn_selection_window; - Atom wm_sn_atom; - guint32 wm_sn_timestamp; - - MetaXineramaScreenInfo *xinerama_infos; - int n_xinerama_infos; - - /* Cache the current Xinerama */ - int last_xinerama_index; - -#ifdef HAVE_STARTUP_NOTIFICATION - SnMonitorContext *sn_context; - GSList *startup_sequences; - guint startup_sequence_timeout; -#endif - -#ifdef HAVE_COMPOSITE_EXTENSIONS - Window wm_cm_selection_window; -#endif - - guint work_area_idle; - - int rows_of_workspaces; - int columns_of_workspaces; - MetaScreenCorner starting_corner; - guint vertical_workspaces : 1; - - guint keys_grabbed : 1; - guint all_keys_grabbed : 1; - - int closing; - - /* gc for XOR on root window */ - GC root_xor_gc; - - /* Managed by compositor.c */ - gpointer compositor_data; -}; - -MetaScreen* meta_screen_new (MetaDisplay *display, - int number, - guint32 timestamp); -void meta_screen_free (MetaScreen *screen, - guint32 timestamp); -void meta_screen_manage_all_windows (MetaScreen *screen); -void meta_screen_foreach_window (MetaScreen *screen, - MetaScreenWindowFunc func, - gpointer data); -void meta_screen_queue_frame_redraws (MetaScreen *screen); -void meta_screen_queue_window_resizes (MetaScreen *screen); - -int meta_screen_get_n_workspaces (MetaScreen *screen); - -MetaWorkspace* meta_screen_get_workspace_by_index (MetaScreen *screen, - int index); - -void meta_screen_set_cursor (MetaScreen *screen, - MetaCursor cursor); -void meta_screen_update_cursor (MetaScreen *screen); - -void meta_screen_ensure_tab_popup (MetaScreen *screen, - MetaTabList list_type, - MetaTabShowType show_type); -void meta_screen_ensure_workspace_popup (MetaScreen *screen); - -MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen, - MetaWindow *not_this_one); - -const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen); -const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_rect (MetaScreen *screen, - MetaRectangle *rect); -const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen, - MetaWindow *window); - - -const MetaXineramaScreenInfo* meta_screen_get_xinerama_neighbor (MetaScreen *screen, - int which_xinerama, - MetaScreenDirection dir); -void meta_screen_get_natural_xinerama_list (MetaScreen *screen, - int** xineramas_list, - int* n_xineramas); - -void meta_screen_update_workspace_layout (MetaScreen *screen); -void meta_screen_update_workspace_names (MetaScreen *screen); -void meta_screen_queue_workarea_recalc (MetaScreen *screen); - -Window meta_create_offscreen_window (Display *xdisplay, - Window parent, - long valuemask); - -typedef struct MetaWorkspaceLayout MetaWorkspaceLayout; - -struct MetaWorkspaceLayout -{ - int rows; - int cols; - int *grid; - int grid_area; - int current_row; - int current_col; -}; - -void meta_screen_calc_workspace_layout (MetaScreen *screen, - int num_workspaces, - int current_space, - MetaWorkspaceLayout *layout); -void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout); - -void meta_screen_resize (MetaScreen *screen, - int width, - int height); - -void meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen, - MetaWindow *keep); - -/* Show/hide the desktop (temporarily hide all windows) */ -void meta_screen_show_desktop (MetaScreen *screen, - guint32 timestamp); -void meta_screen_unshow_desktop (MetaScreen *screen); - -/* Update whether the destkop is being shown for the current active_workspace */ -void meta_screen_update_showing_desktop_hint (MetaScreen *screen); - -gboolean meta_screen_apply_startup_properties (MetaScreen *screen, - MetaWindow *window); -void meta_screen_composite_all_windows (MetaScreen *screen); - -#endif diff --git a/src/core/screen.c b/src/core/screen.c deleted file mode 100644 index e82dd932..00000000 --- a/src/core/screen.c +++ /dev/null @@ -1,2802 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X screen handler */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "screen-private.h" -#include "util.h" -#include "errors.h" -#include "window-private.h" -#include "frame-private.h" -#include "prefs.h" -#include "workspace.h" -#include "keybindings.h" -#include "stack.h" -#include "xprops.h" -#include "compositor.h" - -#ifdef HAVE_SOLARIS_XINERAMA -#include <X11/extensions/xinerama.h> -#endif -#ifdef HAVE_XFREE_XINERAMA -#include <X11/extensions/Xinerama.h> -#endif - -#include <X11/Xatom.h> -#include <locale.h> -#include <string.h> -#include <stdio.h> - -static char* get_screen_name (MetaDisplay *display, - int number); - -static void update_num_workspaces (MetaScreen *screen, - guint32 timestamp); -static void update_focus_mode (MetaScreen *screen); -static void set_workspace_names (MetaScreen *screen); -static void prefs_changed_callback (MetaPreference pref, - gpointer data); - -static void set_desktop_geometry_hint (MetaScreen *screen); -static void set_desktop_viewport_hint (MetaScreen *screen); - -#ifdef HAVE_STARTUP_NOTIFICATION -static void meta_screen_sn_event (SnMonitorEvent *event, - void *user_data); -#endif - -static int -set_wm_check_hint (MetaScreen *screen) -{ - unsigned long data[1]; - - g_return_val_if_fail (screen->display->leader_window != None, 0); - - data[0] = screen->display->leader_window; - - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom__NET_SUPPORTING_WM_CHECK, - XA_WINDOW, - 32, PropModeReplace, (guchar*) data, 1); - - return Success; -} - -static int -set_supported_hint (MetaScreen *screen) -{ - Atom atoms[] = { -#define EWMH_ATOMS_ONLY -#define item(x) screen->display->atom_##x, -#include "atomnames.h" -#undef item -#undef EWMH_ATOMS_ONLY - }; - - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom__NET_SUPPORTED, - XA_ATOM, - 32, PropModeReplace, - (guchar*) atoms, G_N_ELEMENTS(atoms)); - - return Success; -} - -static int -set_wm_icon_size_hint (MetaScreen *screen) -{ -#define N_VALS 6 - gulong vals[N_VALS]; - - /* min width, min height, max w, max h, width inc, height inc */ - vals[0] = META_ICON_WIDTH; - vals[1] = META_ICON_HEIGHT; - vals[2] = META_ICON_WIDTH; - vals[3] = META_ICON_HEIGHT; - vals[4] = 0; - vals[5] = 0; - - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom_WM_ICON_SIZE, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) vals, N_VALS); - - return Success; -#undef N_VALS -} - -static void -reload_xinerama_infos (MetaScreen *screen) -{ - MetaDisplay *display; - - { - GList *tmp; - - tmp = screen->workspaces; - while (tmp != NULL) - { - MetaWorkspace *space = tmp->data; - - meta_workspace_invalidate_work_area (space); - - tmp = tmp->next; - } - } - - display = screen->display; - - if (screen->xinerama_infos) - g_free (screen->xinerama_infos); - - screen->xinerama_infos = NULL; - screen->n_xinerama_infos = 0; - screen->last_xinerama_index = 0; - - screen->display->xinerama_cache_invalidated = TRUE; - -#ifdef HAVE_XFREE_XINERAMA - if (XineramaIsActive (display->xdisplay)) - { - XineramaScreenInfo *infos; - int n_infos; - int i; - - n_infos = 0; - infos = XineramaQueryScreens (display->xdisplay, &n_infos); - - meta_topic (META_DEBUG_XINERAMA, - "Found %d Xinerama screens on display %s\n", - n_infos, display->name); - - if (n_infos > 0) - { - screen->xinerama_infos = g_new (MetaXineramaScreenInfo, n_infos); - screen->n_xinerama_infos = n_infos; - - i = 0; - while (i < n_infos) - { - screen->xinerama_infos[i].number = infos[i].screen_number; - screen->xinerama_infos[i].rect.x = infos[i].x_org; - screen->xinerama_infos[i].rect.y = infos[i].y_org; - screen->xinerama_infos[i].rect.width = infos[i].width; - screen->xinerama_infos[i].rect.height = infos[i].height; - - meta_topic (META_DEBUG_XINERAMA, - "Xinerama %d is %d,%d %d x %d\n", - screen->xinerama_infos[i].number, - screen->xinerama_infos[i].rect.x, - screen->xinerama_infos[i].rect.y, - screen->xinerama_infos[i].rect.width, - screen->xinerama_infos[i].rect.height); - - ++i; - } - } - - meta_XFree (infos); - } - else - { - meta_topic (META_DEBUG_XINERAMA, - "No XFree86 Xinerama extension or XFree86 Xinerama inactive on display %s\n", - display->name); - } -#else - meta_topic (META_DEBUG_XINERAMA, - "Metacity compiled without XFree86 Xinerama support\n"); -#endif /* HAVE_XFREE_XINERAMA */ - -#ifdef HAVE_SOLARIS_XINERAMA - /* This code from GDK, Copyright (C) 2002 Sun Microsystems */ - if (screen->n_xinerama_infos == 0 && - XineramaGetState (screen->display->xdisplay, - screen->number)) - { - XRectangle monitors[MAXFRAMEBUFFERS]; - unsigned char hints[16]; - int result; - int n_monitors; - int i; - - n_monitors = 0; - result = XineramaGetInfo (screen->display->xdisplay, - screen->number, - monitors, hints, - &n_monitors); - /* Yes I know it should be Success but the current implementation - * returns the num of monitor - */ - if (result > 0) - { - g_assert (n_monitors > 0); - - screen->xinerama_infos = g_new (MetaXineramaScreenInfo, n_monitors); - screen->n_xinerama_infos = n_monitors; - - i = 0; - while (i < n_monitors) - { - screen->xinerama_infos[i].number = i; - screen->xinerama_infos[i].rect.x = monitors[i].x; - screen->xinerama_infos[i].rect.y = monitors[i].y; - screen->xinerama_infos[i].rect.width = monitors[i].width; - screen->xinerama_infos[i].rect.height = monitors[i].height; - - meta_topic (META_DEBUG_XINERAMA, - "Xinerama %d is %d,%d %d x %d\n", - screen->xinerama_infos[i].number, - screen->xinerama_infos[i].rect.x, - screen->xinerama_infos[i].rect.y, - screen->xinerama_infos[i].rect.width, - screen->xinerama_infos[i].rect.height); - - ++i; - } - } - } - else if (screen->n_xinerama_infos == 0) - { - meta_topic (META_DEBUG_XINERAMA, - "No Solaris Xinerama extension or Solaris Xinerama inactive on display %s\n", - display->name); - } -#else - meta_topic (META_DEBUG_XINERAMA, - "Metacity compiled without Solaris Xinerama support\n"); -#endif /* HAVE_SOLARIS_XINERAMA */ - - - /* If no Xinerama, fill in the single screen info so - * we can use the field unconditionally - */ - if (screen->n_xinerama_infos == 0) - { - if (g_getenv ("METACITY_DEBUG_XINERAMA")) - { - meta_topic (META_DEBUG_XINERAMA, - "Pretending a single monitor has two Xinerama screens\n"); - - screen->xinerama_infos = g_new (MetaXineramaScreenInfo, 2); - screen->n_xinerama_infos = 2; - - screen->xinerama_infos[0].number = 0; - screen->xinerama_infos[0].rect = screen->rect; - screen->xinerama_infos[0].rect.width = screen->rect.width / 2; - - screen->xinerama_infos[1].number = 1; - screen->xinerama_infos[1].rect = screen->rect; - screen->xinerama_infos[1].rect.x = screen->rect.width / 2; - screen->xinerama_infos[1].rect.width = screen->rect.width / 2; - } - else - { - meta_topic (META_DEBUG_XINERAMA, - "No Xinerama screens, using default screen info\n"); - - screen->xinerama_infos = g_new (MetaXineramaScreenInfo, 1); - screen->n_xinerama_infos = 1; - - screen->xinerama_infos[0].number = 0; - screen->xinerama_infos[0].rect = screen->rect; - } - } - - g_assert (screen->n_xinerama_infos > 0); - g_assert (screen->xinerama_infos != NULL); -} - -MetaScreen* -meta_screen_new (MetaDisplay *display, - int number, - guint32 timestamp) -{ - MetaScreen *screen; - Window xroot; - Display *xdisplay; - XWindowAttributes attr; - Window new_wm_sn_owner; - Window current_wm_sn_owner; - gboolean replace_current_wm; - Atom wm_sn_atom; - char buf[128]; - guint32 manager_timestamp; - gulong current_workspace; - - replace_current_wm = meta_get_replace_current_wm (); - - /* Only display->name, display->xdisplay, and display->error_traps - * can really be used in this function, since normally screens are - * created from the MetaDisplay constructor - */ - - xdisplay = display->xdisplay; - - meta_verbose ("Trying screen %d on display '%s'\n", - number, display->name); - - xroot = RootWindow (xdisplay, number); - - /* FVWM checks for None here, I don't know if this - * ever actually happens - */ - if (xroot == None) - { - meta_warning (_("Screen %d on display '%s' is invalid\n"), - number, display->name); - return NULL; - } - - sprintf (buf, "WM_S%d", number); - wm_sn_atom = XInternAtom (xdisplay, buf, False); - - current_wm_sn_owner = XGetSelectionOwner (xdisplay, wm_sn_atom); - - if (current_wm_sn_owner != None) - { - XSetWindowAttributes attrs; - - if (!replace_current_wm) - { - meta_warning (_("Screen %d on display \"%s\" already has a window manager; try using the --replace option to replace the current window manager.\n"), - number, display->name); - - return NULL; - } - - /* We want to find out when the current selection owner dies */ - meta_error_trap_push_with_return (display); - attrs.event_mask = StructureNotifyMask; - XChangeWindowAttributes (xdisplay, - current_wm_sn_owner, CWEventMask, &attrs); - if (meta_error_trap_pop_with_return (display, FALSE) != Success) - current_wm_sn_owner = None; /* don't wait for it to die later on */ - } - - /* We need SelectionClear and SelectionRequest events on the new_wm_sn_owner, - * but those cannot be masked, so we only need NoEventMask. - */ - new_wm_sn_owner = meta_create_offscreen_window (xdisplay, xroot, NoEventMask); - - manager_timestamp = timestamp; - - XSetSelectionOwner (xdisplay, wm_sn_atom, new_wm_sn_owner, - manager_timestamp); - - if (XGetSelectionOwner (xdisplay, wm_sn_atom) != new_wm_sn_owner) - { - meta_warning (_("Could not acquire window manager selection on screen %d display \"%s\"\n"), - number, display->name); - - XDestroyWindow (xdisplay, new_wm_sn_owner); - - return NULL; - } - - { - /* Send client message indicating that we are now the WM */ - XClientMessageEvent ev; - - ev.type = ClientMessage; - ev.window = xroot; - ev.message_type = display->atom_MANAGER; - ev.format = 32; - ev.data.l[0] = manager_timestamp; - ev.data.l[1] = wm_sn_atom; - - XSendEvent (xdisplay, xroot, False, StructureNotifyMask, (XEvent*)&ev); - } - - /* Wait for old window manager to go away */ - if (current_wm_sn_owner != None) - { - XEvent event; - - /* We sort of block infinitely here which is probably lame. */ - - meta_verbose ("Waiting for old window manager to exit\n"); - do - { - XWindowEvent (xdisplay, current_wm_sn_owner, - StructureNotifyMask, &event); - } - while (event.type != DestroyNotify); - } - - /* select our root window events */ - meta_error_trap_push_with_return (display); - - /* We need to or with the existing event mask since - * gtk+ may be interested in other events. - */ - XGetWindowAttributes (xdisplay, xroot, &attr); - XSelectInput (xdisplay, - xroot, - SubstructureRedirectMask | SubstructureNotifyMask | - ColormapChangeMask | PropertyChangeMask | - LeaveWindowMask | EnterWindowMask | - KeyPressMask | KeyReleaseMask | - FocusChangeMask | StructureNotifyMask | -#ifdef HAVE_COMPOSITE_EXTENSIONS - ExposureMask | -#endif - attr.your_event_mask); - if (meta_error_trap_pop_with_return (display, FALSE) != Success) - { - meta_warning (_("Screen %d on display \"%s\" already has a window manager\n"), - number, display->name); - - XDestroyWindow (xdisplay, new_wm_sn_owner); - - return NULL; - } - - screen = g_new (MetaScreen, 1); - screen->closing = 0; - - screen->display = display; - screen->number = number; - screen->screen_name = get_screen_name (display, number); - screen->xscreen = ScreenOfDisplay (xdisplay, number); - screen->xroot = xroot; - screen->rect.x = screen->rect.y = 0; - screen->rect.width = WidthOfScreen (screen->xscreen); - screen->rect.height = HeightOfScreen (screen->xscreen); - screen->current_cursor = -1; /* invalid/unset */ - screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen); - screen->default_depth = DefaultDepthOfScreen (screen->xscreen); - screen->flash_window = None; - - screen->wm_sn_selection_window = new_wm_sn_owner; - screen->wm_sn_atom = wm_sn_atom; - screen->wm_sn_timestamp = manager_timestamp; - -#ifdef HAVE_COMPOSITE_EXTENSIONS - screen->wm_cm_selection_window = meta_create_offscreen_window (xdisplay, - xroot, - NoEventMask); -#endif - screen->work_area_idle = 0; - - screen->active_workspace = NULL; - screen->workspaces = NULL; - screen->rows_of_workspaces = 1; - screen->columns_of_workspaces = -1; - screen->vertical_workspaces = FALSE; - screen->starting_corner = META_SCREEN_TOPLEFT; - screen->compositor_data = NULL; - - { - XFontStruct *font_info; - XGCValues gc_values; - gulong value_mask = 0; - - gc_values.subwindow_mode = IncludeInferiors; - value_mask |= GCSubwindowMode; - gc_values.function = GXinvert; - value_mask |= GCFunction; - gc_values.line_width = META_WIREFRAME_XOR_LINE_WIDTH; - value_mask |= GCLineWidth; - - font_info = XLoadQueryFont (screen->display->xdisplay, "fixed"); - - if (font_info != NULL) - { - gc_values.font = font_info->fid; - value_mask |= GCFont; - XFreeFontInfo (NULL, font_info, 1); - } - else - meta_warning ("xserver doesn't have 'fixed' font.\n"); - - screen->root_xor_gc = XCreateGC (screen->display->xdisplay, - screen->xroot, - value_mask, - &gc_values); - } - - screen->xinerama_infos = NULL; - screen->n_xinerama_infos = 0; - screen->last_xinerama_index = 0; - - reload_xinerama_infos (screen); - - meta_screen_set_cursor (screen, META_CURSOR_DEFAULT); - - /* Handle creating a no_focus_window for this screen */ - screen->no_focus_window = - meta_create_offscreen_window (display->xdisplay, - screen->xroot, - FocusChangeMask|KeyPressMask|KeyReleaseMask); - XMapWindow (display->xdisplay, screen->no_focus_window); - /* Done with no_focus_window stuff */ - - set_wm_icon_size_hint (screen); - - set_supported_hint (screen); - - set_wm_check_hint (screen); - - set_desktop_viewport_hint (screen); - - set_desktop_geometry_hint (screen); - - meta_screen_update_workspace_layout (screen); - - /* Get current workspace */ - current_workspace = 0; - if (meta_prop_get_cardinal (screen->display, - screen->xroot, - screen->display->atom__NET_CURRENT_DESKTOP, - ¤t_workspace)) - meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n", - (int) current_workspace); - else - meta_verbose ("No _NET_CURRENT_DESKTOP present\n"); - - /* Screens must have at least one workspace at all times, - * so create that required workspace. - */ - meta_workspace_activate (meta_workspace_new (screen), timestamp); - update_num_workspaces (screen, timestamp); - - set_workspace_names (screen); - - screen->all_keys_grabbed = FALSE; - screen->keys_grabbed = FALSE; - meta_screen_grab_keys (screen); - - screen->ui = meta_ui_new (screen->display->xdisplay, - screen->xscreen); - - screen->tab_popup = NULL; - - screen->stack = meta_stack_new (screen); - - meta_prefs_add_listener (prefs_changed_callback, screen); - -#ifdef HAVE_STARTUP_NOTIFICATION - screen->sn_context = - sn_monitor_context_new (screen->display->sn_display, - screen->number, - meta_screen_sn_event, - screen, - NULL); - screen->startup_sequences = NULL; - screen->startup_sequence_timeout = 0; -#endif - - /* Switch to the _NET_CURRENT_DESKTOP workspace */ - { - MetaWorkspace *space; - - space = meta_screen_get_workspace_by_index (screen, - current_workspace); - - if (space != NULL) - meta_workspace_activate (space, timestamp); - } - - meta_verbose ("Added screen %d ('%s') root 0x%lx\n", - screen->number, screen->screen_name, screen->xroot); - - return screen; -} - -void -meta_screen_free (MetaScreen *screen, - guint32 timestamp) -{ - MetaDisplay *display; - XGCValues gc_values = { 0 }; - - display = screen->display; - - screen->closing += 1; - - meta_display_grab (display); - - if (screen->display->compositor) - { - meta_compositor_unmanage_screen (screen->display->compositor, - screen); - } - - meta_display_unmanage_windows_for_screen (display, screen, timestamp); - - meta_prefs_remove_listener (prefs_changed_callback, screen); - - meta_screen_ungrab_keys (screen); - -#ifdef HAVE_STARTUP_NOTIFICATION - g_slist_foreach (screen->startup_sequences, - (GFunc) sn_startup_sequence_unref, NULL); - g_slist_free (screen->startup_sequences); - screen->startup_sequences = NULL; - - if (screen->startup_sequence_timeout != 0) - { - g_source_remove (screen->startup_sequence_timeout); - screen->startup_sequence_timeout = 0; - } - if (screen->sn_context) - { - sn_monitor_context_unref (screen->sn_context); - screen->sn_context = NULL; - } -#endif - - meta_ui_free (screen->ui); - - meta_stack_free (screen->stack); - - meta_error_trap_push_with_return (screen->display); - XSelectInput (screen->display->xdisplay, screen->xroot, 0); - if (meta_error_trap_pop_with_return (screen->display, FALSE) != Success) - meta_warning (_("Could not release screen %d on display \"%s\"\n"), - screen->number, screen->display->name); - - XDestroyWindow (screen->display->xdisplay, - screen->wm_sn_selection_window); - - if (screen->work_area_idle != 0) - g_source_remove (screen->work_area_idle); - - - if (XGetGCValues (screen->display->xdisplay, - screen->root_xor_gc, - GCFont, - &gc_values)) - { - XUnloadFont (screen->display->xdisplay, - gc_values.font); - } - - XFreeGC (screen->display->xdisplay, - screen->root_xor_gc); - - if (screen->xinerama_infos) - g_free (screen->xinerama_infos); - - g_free (screen->screen_name); - g_free (screen); - - XFlush (display->xdisplay); - meta_display_ungrab (display); -} - -typedef struct -{ - Window xwindow; - XWindowAttributes attrs; -} WindowInfo; - -static GList * -list_windows (MetaScreen *screen) -{ - Window ignored1, ignored2; - Window *children; - guint n_children, i; - GList *result; - - XQueryTree (screen->display->xdisplay, - screen->xroot, - &ignored1, &ignored2, &children, &n_children); - - result = NULL; - for (i = 0; i < n_children; ++i) - { - WindowInfo *info = g_new0 (WindowInfo, 1); - - meta_error_trap_push_with_return (screen->display); - - XGetWindowAttributes (screen->display->xdisplay, - children[i], &info->attrs); - - if (meta_error_trap_pop_with_return (screen->display, TRUE)) - { - meta_verbose ("Failed to get attributes for window 0x%lx\n", - children[i]); - g_free (info); - } - else - { - info->xwindow = children[i]; - } - - result = g_list_prepend (result, info); - } - - if (children) - XFree (children); - - return g_list_reverse (result); -} - -void -meta_screen_manage_all_windows (MetaScreen *screen) -{ - GList *windows; - GList *list; - - meta_display_grab (screen->display); - - windows = list_windows (screen); - - meta_stack_freeze (screen->stack); - for (list = windows; list != NULL; list = list->next) - { - WindowInfo *info = list->data; - MetaWindow *window; - - window = meta_window_new_with_attrs (screen->display, info->xwindow, TRUE, - &info->attrs); - if (info->xwindow == screen->no_focus_window || - info->xwindow == screen->flash_window || -#ifdef HAVE_COMPOSITE_EXTENSIONS - info->xwindow == screen->wm_cm_selection_window || -#endif - info->xwindow == screen->wm_sn_selection_window) { - meta_verbose ("Not managing our own windows\n"); - continue; - } - - if (screen->display->compositor) - meta_compositor_add_window (screen->display->compositor, window, - info->xwindow, &info->attrs); - } - meta_stack_thaw (screen->stack); - - g_list_foreach (windows, (GFunc)g_free, NULL); - g_list_free (windows); - - meta_display_ungrab (screen->display); -} - -void -meta_screen_composite_all_windows (MetaScreen *screen) -{ -#ifdef HAVE_COMPOSITE_EXTENSIONS - MetaDisplay *display; - GList *windows, *list; - - display = screen->display; - if (!display->compositor) - return; - - windows = list_windows (screen); - - meta_stack_freeze (screen->stack); - - for (list = windows; list != NULL; list = list->next) - { - WindowInfo *info = list->data; - - if (info->xwindow == screen->no_focus_window || - info->xwindow == screen->flash_window || - info->xwindow == screen->wm_sn_selection_window || - info->xwindow == screen->wm_cm_selection_window) { - meta_verbose ("Not managing our own windows\n"); - continue; - } - - meta_compositor_add_window (display->compositor, - meta_display_lookup_x_window (display, - info->xwindow), - info->xwindow, &info->attrs); - } - - meta_stack_thaw (screen->stack); - - g_list_foreach (windows, (GFunc)g_free, NULL); - g_list_free (windows); -#endif -} - -MetaScreen* -meta_screen_for_x_screen (Screen *xscreen) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (DisplayOfScreen (xscreen)); - - if (display == NULL) - return NULL; - - return meta_display_screen_for_x_screen (display, xscreen); -} - -static void -prefs_changed_callback (MetaPreference pref, - gpointer data) -{ - MetaScreen *screen = data; - - if (pref == META_PREF_NUM_WORKSPACES) - { - /* GConf doesn't provide timestamps, but luckily update_num_workspaces - * often doesn't need it... - */ - guint32 timestamp = - meta_display_get_current_time_roundtrip (screen->display); - update_num_workspaces (screen, timestamp); - } - else if (pref == META_PREF_FOCUS_MODE) - { - update_focus_mode (screen); - } - else if (pref == META_PREF_WORKSPACE_NAMES) - { - set_workspace_names (screen); - } -} - - -static char* -get_screen_name (MetaDisplay *display, - int number) -{ - char *p; - char *dname; - char *scr; - - /* DisplayString gives us a sort of canonical display, - * vs. the user-entered name from XDisplayName() - */ - dname = g_strdup (DisplayString (display->xdisplay)); - - /* Change display name to specify this screen. - */ - p = strrchr (dname, ':'); - if (p) - { - p = strchr (p, '.'); - if (p) - *p = '\0'; - } - - scr = g_strdup_printf ("%s.%d", dname, number); - - g_free (dname); - - return scr; -} - -static gint -ptrcmp (gconstpointer a, gconstpointer b) -{ - if (a < b) - return -1; - else if (a > b) - return 1; - else - return 0; -} - -static void -listify_func (gpointer key, gpointer value, gpointer data) -{ - GSList **listp; - - listp = data; - - *listp = g_slist_prepend (*listp, value); -} - -void -meta_screen_foreach_window (MetaScreen *screen, - MetaScreenWindowFunc func, - gpointer data) -{ - GSList *winlist; - GSList *tmp; - - /* If we end up doing this often, just keeping a list - * of windows might be sensible. - */ - - winlist = NULL; - g_hash_table_foreach (screen->display->window_ids, - listify_func, - &winlist); - - winlist = g_slist_sort (winlist, ptrcmp); - - tmp = winlist; - while (tmp != NULL) - { - /* If the next node doesn't contain this window - * a second time, delete the window. - */ - if (tmp->next == NULL || - (tmp->next && tmp->next->data != tmp->data)) - { - MetaWindow *window = tmp->data; - - if (window->screen == screen) - (* func) (screen, window, data); - } - - tmp = tmp->next; - } - g_slist_free (winlist); -} - -static void -queue_draw (MetaScreen *screen, MetaWindow *window, gpointer data) -{ - if (window->frame) - meta_frame_queue_draw (window->frame); -} - -void -meta_screen_queue_frame_redraws (MetaScreen *screen) -{ - meta_screen_foreach_window (screen, queue_draw, NULL); -} - -static void -queue_resize (MetaScreen *screen, MetaWindow *window, gpointer data) -{ - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); -} - -void -meta_screen_queue_window_resizes (MetaScreen *screen) -{ - meta_screen_foreach_window (screen, queue_resize, NULL); -} - -int -meta_screen_get_n_workspaces (MetaScreen *screen) -{ - return g_list_length (screen->workspaces); -} - -MetaWorkspace* -meta_screen_get_workspace_by_index (MetaScreen *screen, - int idx) -{ - GList *tmp; - int i; - - /* should be robust, idx is maybe from an app */ - if (idx < 0) - return NULL; - - i = 0; - tmp = screen->workspaces; - while (tmp != NULL) - { - MetaWorkspace *w = tmp->data; - - if (i == idx) - return w; - - ++i; - tmp = tmp->next; - } - - return NULL; -} - -static void -set_number_of_spaces_hint (MetaScreen *screen, - int n_spaces) -{ - unsigned long data[1]; - - if (screen->closing > 0) - return; - - data[0] = n_spaces; - - meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu\n", data[0]); - - meta_error_trap_push (screen->display); - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom__NET_NUMBER_OF_DESKTOPS, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - meta_error_trap_pop (screen->display, FALSE); -} - -static void -set_desktop_geometry_hint (MetaScreen *screen) -{ - unsigned long data[2]; - - if (screen->closing > 0) - return; - - data[0] = screen->rect.width; - data[1] = screen->rect.height; - - meta_verbose ("Setting _NET_DESKTOP_GEOMETRY to %lu, %lu\n", data[0], data[1]); - - meta_error_trap_push (screen->display); - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom__NET_DESKTOP_GEOMETRY, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 2); - meta_error_trap_pop (screen->display, FALSE); -} - -static void -set_desktop_viewport_hint (MetaScreen *screen) -{ - unsigned long data[2]; - - if (screen->closing > 0) - return; - - /* - * Metacity does not implement viewports, so this is a fixed 0,0 - */ - data[0] = 0; - data[1] = 0; - - meta_verbose ("Setting _NET_DESKTOP_VIEWPORT to 0, 0\n"); - - meta_error_trap_push (screen->display); - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom__NET_DESKTOP_VIEWPORT, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 2); - meta_error_trap_pop (screen->display, FALSE); -} - -static void -update_num_workspaces (MetaScreen *screen, - guint32 timestamp) -{ - int new_num; - GList *tmp; - int i; - GList *extras; - MetaWorkspace *last_remaining; - gboolean need_change_space; - - new_num = meta_prefs_get_num_workspaces (); - - g_assert (new_num > 0); - - last_remaining = NULL; - extras = NULL; - i = 0; - tmp = screen->workspaces; - while (tmp != NULL) - { - MetaWorkspace *w = tmp->data; - - if (i >= new_num) - extras = g_list_prepend (extras, w); - else - last_remaining = w; - - ++i; - tmp = tmp->next; - } - - g_assert (last_remaining); - - /* Get rid of the extra workspaces by moving all their windows - * to last_remaining, then activating last_remaining if - * one of the removed workspaces was active. This will be a bit - * wacky if the config tool for changing number of workspaces - * is on a removed workspace ;-) - */ - need_change_space = FALSE; - tmp = extras; - while (tmp != NULL) - { - MetaWorkspace *w = tmp->data; - - meta_workspace_relocate_windows (w, last_remaining); - - if (w == screen->active_workspace) - need_change_space = TRUE; - - tmp = tmp->next; - } - - if (need_change_space) - meta_workspace_activate (last_remaining, timestamp); - - /* Should now be safe to free the workspaces */ - tmp = extras; - while (tmp != NULL) - { - MetaWorkspace *w = tmp->data; - - g_assert (w->windows == NULL); - meta_workspace_free (w); - - tmp = tmp->next; - } - - g_list_free (extras); - - while (i < new_num) - { - meta_workspace_new (screen); - ++i; - } - - set_number_of_spaces_hint (screen, new_num); - - meta_screen_queue_workarea_recalc (screen); -} - -static void -update_focus_mode (MetaScreen *screen) -{ - /* nothing to do anymore */ ; -} - -void -meta_screen_set_cursor (MetaScreen *screen, - MetaCursor cursor) -{ - Cursor xcursor; - - if (cursor == screen->current_cursor) - return; - - screen->current_cursor = cursor; - - xcursor = meta_display_create_x_cursor (screen->display, cursor); - XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor); - XFlush (screen->display->xdisplay); - XFreeCursor (screen->display->xdisplay, xcursor); -} - -void -meta_screen_update_cursor (MetaScreen *screen) -{ - Cursor xcursor; - - xcursor = meta_display_create_x_cursor (screen->display, - screen->current_cursor); - XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor); - XFlush (screen->display->xdisplay); - XFreeCursor (screen->display->xdisplay, xcursor); -} - -#define MAX_PREVIEW_SIZE 150.0 - -static GdkPixbuf * -get_window_pixbuf (MetaWindow *window, - int *width, - int *height) -{ - Pixmap pmap; - GdkPixbuf *pixbuf, *scaled; - double ratio; - - pmap = meta_compositor_get_window_pixmap (window->display->compositor, - window); - if (pmap == None) - return NULL; - - pixbuf = meta_ui_get_pixbuf_from_pixmap (pmap); - if (pixbuf == NULL) - return NULL; - - *width = gdk_pixbuf_get_width (pixbuf); - *height = gdk_pixbuf_get_height (pixbuf); - - /* Scale pixbuf to max dimension MAX_PREVIEW_SIZE */ - if (*width > *height) - { - ratio = ((double) *width) / MAX_PREVIEW_SIZE; - *width = (int) MAX_PREVIEW_SIZE; - *height = (int) (((double) *height) / ratio); - } - else - { - ratio = ((double) *height) / MAX_PREVIEW_SIZE; - *height = (int) MAX_PREVIEW_SIZE; - *width = (int) (((double) *width) / ratio); - } - - scaled = gdk_pixbuf_scale_simple (pixbuf, *width, *height, - GDK_INTERP_BILINEAR); - g_object_unref (pixbuf); - return scaled; -} - -void -meta_screen_ensure_tab_popup (MetaScreen *screen, - MetaTabList list_type, - MetaTabShowType show_type) -{ - MetaTabEntry *entries; - GList *tab_list; - GList *tmp; - int len; - int i; - - if (screen->tab_popup) - return; - - tab_list = meta_display_get_tab_list (screen->display, - list_type, - screen, - screen->active_workspace); - - len = g_list_length (tab_list); - - entries = g_new (MetaTabEntry, len + 1); - entries[len].key = NULL; - entries[len].title = NULL; - entries[len].icon = NULL; - - i = 0; - tmp = tab_list; - while (i < len) - { - MetaWindow *window; - MetaRectangle r; - GdkPixbuf *win_pixbuf; - int width, height; - - window = tmp->data; - - entries[i].key = (MetaTabEntryKey) window->xwindow; - entries[i].title = window->title; - - win_pixbuf = get_window_pixbuf (window, &width, &height); - if (win_pixbuf == NULL) - entries[i].icon = g_object_ref (window->icon); - else - { - int icon_width, icon_height, t_width, t_height; -#define ICON_OFFSET 6 - - icon_width = gdk_pixbuf_get_width (window->icon); - icon_height = gdk_pixbuf_get_height (window->icon); - - t_width = width + ICON_OFFSET; - t_height = height + ICON_OFFSET; - - entries[i].icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, - t_width, t_height); - gdk_pixbuf_fill (entries[i].icon, 0x00000000); - gdk_pixbuf_copy_area (win_pixbuf, 0, 0, width, height, - entries[i].icon, 0, 0); - g_object_unref (win_pixbuf); - gdk_pixbuf_composite (window->icon, entries[i].icon, - t_width - icon_width, t_height - icon_height, - icon_width, icon_height, - t_width - icon_width, t_height - icon_height, - 1.0, 1.0, GDK_INTERP_BILINEAR, 255); - } - - entries[i].blank = FALSE; - entries[i].hidden = !meta_window_showing_on_its_workspace (window); - entries[i].demands_attention = window->wm_state_demands_attention; - - if (show_type == META_TAB_SHOW_INSTANTLY || - !entries[i].hidden || - !meta_window_get_icon_geometry (window, &r)) - meta_window_get_outer_rect (window, &r); - - entries[i].rect = r; - - /* Find inside of highlight rectangle to be used when window is - * outlined for tabbing. This should be the size of the - * east/west frame, and the size of the south frame, on those - * sides. On the top it should be the size of the south frame - * edge. - */ -#define OUTLINE_WIDTH 5 - /* Top side */ - if (!entries[i].hidden && - window->frame && window->frame->bottom_height > 0 && - window->frame->child_y >= window->frame->bottom_height) - entries[i].inner_rect.y = window->frame->bottom_height; - else - entries[i].inner_rect.y = OUTLINE_WIDTH; - - /* Bottom side */ - if (!entries[i].hidden && - window->frame && window->frame->bottom_height != 0) - entries[i].inner_rect.height = r.height - - entries[i].inner_rect.y - window->frame->bottom_height; - else - entries[i].inner_rect.height = r.height - - entries[i].inner_rect.y - OUTLINE_WIDTH; - - /* Left side */ - if (!entries[i].hidden && window->frame && window->frame->child_x != 0) - entries[i].inner_rect.x = window->frame->child_x; - else - entries[i].inner_rect.x = OUTLINE_WIDTH; - - /* Right side */ - if (!entries[i].hidden && - window->frame && window->frame->right_width != 0) - entries[i].inner_rect.width = r.width - - entries[i].inner_rect.x - window->frame->right_width; - else - entries[i].inner_rect.width = r.width - - entries[i].inner_rect.x - OUTLINE_WIDTH; - - ++i; - tmp = tmp->next; - } - - screen->tab_popup = meta_ui_tab_popup_new (entries, - screen->number, - len, - 5, /* FIXME */ - TRUE); - - for (i = 0; i < len; i++) - g_object_unref (entries[i].icon); - - g_free (entries); - - g_list_free (tab_list); - - /* don't show tab popup, since proper window isn't selected yet */ -} - -void -meta_screen_ensure_workspace_popup (MetaScreen *screen) -{ - MetaTabEntry *entries; - int len; - int i; - MetaWorkspaceLayout layout; - int n_workspaces; - int current_workspace; - - if (screen->tab_popup) - return; - - current_workspace = meta_workspace_index (screen->active_workspace); - n_workspaces = meta_screen_get_n_workspaces (screen); - - meta_screen_calc_workspace_layout (screen, n_workspaces, - current_workspace, &layout); - - len = layout.grid_area; - - entries = g_new (MetaTabEntry, len + 1); - entries[len].key = NULL; - entries[len].title = NULL; - entries[len].icon = NULL; - - i = 0; - while (i < len) - { - if (layout.grid[i] >= 0) - { - MetaWorkspace *workspace; - - workspace = meta_screen_get_workspace_by_index (screen, - layout.grid[i]); - - entries[i].key = (MetaTabEntryKey) workspace; - entries[i].title = meta_workspace_get_name (workspace); - entries[i].icon = NULL; - entries[i].blank = FALSE; - - g_assert (entries[i].title != NULL); - } - else - { - entries[i].key = NULL; - entries[i].title = NULL; - entries[i].icon = NULL; - entries[i].blank = TRUE; - } - entries[i].hidden = FALSE; - entries[i].demands_attention = FALSE; - - ++i; - } - - screen->tab_popup = meta_ui_tab_popup_new (entries, - screen->number, - len, - layout.cols, - FALSE); - - g_free (entries); - meta_screen_free_workspace_layout (&layout); - - /* don't show tab popup, since proper space isn't selected yet */ -} - -MetaWindow* -meta_screen_get_mouse_window (MetaScreen *screen, - MetaWindow *not_this_one) -{ - MetaWindow *window; - Window root_return, child_return; - int root_x_return, root_y_return; - int win_x_return, win_y_return; - unsigned int mask_return; - - if (not_this_one) - meta_topic (META_DEBUG_FOCUS, - "Focusing mouse window excluding %s\n", not_this_one->desc); - - meta_error_trap_push (screen->display); - XQueryPointer (screen->display->xdisplay, - screen->xroot, - &root_return, - &child_return, - &root_x_return, - &root_y_return, - &win_x_return, - &win_y_return, - &mask_return); - meta_error_trap_pop (screen->display, TRUE); - - window = meta_stack_get_default_focus_window_at_point (screen->stack, - screen->active_workspace, - not_this_one, - root_x_return, - root_y_return); - - return window; -} - -const MetaXineramaScreenInfo* -meta_screen_get_xinerama_for_rect (MetaScreen *screen, - MetaRectangle *rect) -{ - int i; - int best_xinerama, xinerama_score; - - if (screen->n_xinerama_infos == 1) - return &screen->xinerama_infos[0]; - - best_xinerama = 0; - xinerama_score = 0; - - for (i = 0; i < screen->n_xinerama_infos; i++) - { - MetaRectangle dest; - if (meta_rectangle_intersect (&screen->xinerama_infos[i].rect, - rect, - &dest)) - { - int cur = meta_rectangle_area (&dest); - if (cur > xinerama_score) - { - xinerama_score = cur; - best_xinerama = i; - } - } - } - - return &screen->xinerama_infos[best_xinerama]; -} - -const MetaXineramaScreenInfo* -meta_screen_get_xinerama_for_window (MetaScreen *screen, - MetaWindow *window) -{ - MetaRectangle window_rect; - - meta_window_get_outer_rect (window, &window_rect); - - return meta_screen_get_xinerama_for_rect (screen, &window_rect); -} - -const MetaXineramaScreenInfo* -meta_screen_get_xinerama_neighbor (MetaScreen *screen, - int which_xinerama, - MetaScreenDirection direction) -{ - MetaXineramaScreenInfo* input = screen->xinerama_infos + which_xinerama; - MetaXineramaScreenInfo* current; - int i; - - for (i = 0; i < screen->n_xinerama_infos; i++) - { - current = screen->xinerama_infos + i; - - if ((direction == META_SCREEN_RIGHT && - current->rect.x == input->rect.x + input->rect.width && - meta_rectangle_vert_overlap(¤t->rect, &input->rect)) || - (direction == META_SCREEN_LEFT && - input->rect.x == current->rect.x + current->rect.width && - meta_rectangle_vert_overlap(¤t->rect, &input->rect)) || - (direction == META_SCREEN_UP && - input->rect.y == current->rect.y + current->rect.height && - meta_rectangle_horiz_overlap(¤t->rect, &input->rect)) || - (direction == META_SCREEN_DOWN && - current->rect.y == input->rect.y + input->rect.height && - meta_rectangle_horiz_overlap(¤t->rect, &input->rect))) - { - return current; - } - } - - return NULL; -} - -void -meta_screen_get_natural_xinerama_list (MetaScreen *screen, - int** xineramas_list, - int* n_xineramas) -{ - const MetaXineramaScreenInfo* current; - const MetaXineramaScreenInfo* tmp; - GQueue* xinerama_queue; - int* visited; - int cur = 0; - int i; - - *n_xineramas = screen->n_xinerama_infos; - *xineramas_list = g_new (int, screen->n_xinerama_infos); - - /* we calculate a natural ordering by which to choose xineramas for - * window placement. We start at the current xinerama, and perform - * a breadth-first search of the xineramas starting from that - * xinerama. We choose preferentially left, then right, then down, - * then up. The visitation order produced by this traversal is the - * natural xinerama ordering. - */ - - visited = g_new (int, screen->n_xinerama_infos); - for (i = 0; i < screen->n_xinerama_infos; i++) - { - visited[i] = FALSE; - } - - current = meta_screen_get_current_xinerama (screen); - xinerama_queue = g_queue_new (); - g_queue_push_tail (xinerama_queue, (gpointer) current); - visited[current->number] = TRUE; - - while (!g_queue_is_empty (xinerama_queue)) - { - current = (const MetaXineramaScreenInfo*) - g_queue_pop_head (xinerama_queue); - - (*xineramas_list)[cur++] = current->number; - - /* enqueue each of the directions */ - tmp = meta_screen_get_xinerama_neighbor (screen, - current->number, - META_SCREEN_LEFT); - if (tmp && !visited[tmp->number]) - { - g_queue_push_tail (xinerama_queue, - (MetaXineramaScreenInfo*) tmp); - visited[tmp->number] = TRUE; - } - tmp = meta_screen_get_xinerama_neighbor (screen, - current->number, - META_SCREEN_RIGHT); - if (tmp && !visited[tmp->number]) - { - g_queue_push_tail (xinerama_queue, - (MetaXineramaScreenInfo*) tmp); - visited[tmp->number] = TRUE; - } - tmp = meta_screen_get_xinerama_neighbor (screen, - current->number, - META_SCREEN_UP); - if (tmp && !visited[tmp->number]) - { - g_queue_push_tail (xinerama_queue, - (MetaXineramaScreenInfo*) tmp); - visited[tmp->number] = TRUE; - } - tmp = meta_screen_get_xinerama_neighbor (screen, - current->number, - META_SCREEN_DOWN); - if (tmp && !visited[tmp->number]) - { - g_queue_push_tail (xinerama_queue, - (MetaXineramaScreenInfo*) tmp); - visited[tmp->number] = TRUE; - } - } - - /* in case we somehow missed some set of xineramas, go through the - * visited list and add in any xineramas that were missed - */ - for (i = 0; i < screen->n_xinerama_infos; i++) - { - if (visited[i] == FALSE) - { - (*xineramas_list)[cur++] = i; - } - } - - g_free (visited); - g_queue_free (xinerama_queue); -} - -const MetaXineramaScreenInfo* -meta_screen_get_current_xinerama (MetaScreen *screen) -{ - if (screen->n_xinerama_infos == 1) - return &screen->xinerama_infos[0]; - - /* Sadly, we have to do it this way. Yuck. - */ - - if (screen->display->xinerama_cache_invalidated) - { - Window root_return, child_return; - int win_x_return, win_y_return; - unsigned int mask_return; - int i; - MetaRectangle pointer_position; - - screen->display->xinerama_cache_invalidated = FALSE; - - pointer_position.width = pointer_position.height = 1; - XQueryPointer (screen->display->xdisplay, - screen->xroot, - &root_return, - &child_return, - &pointer_position.x, - &pointer_position.y, - &win_x_return, - &win_y_return, - &mask_return); - - screen->last_xinerama_index = 0; - for (i = 0; i < screen->n_xinerama_infos; i++) - { - if (meta_rectangle_contains_rect (&screen->xinerama_infos[i].rect, - &pointer_position)) - { - screen->last_xinerama_index = i; - break; - } - } - - meta_topic (META_DEBUG_XINERAMA, - "Rechecked current Xinerama, now %d\n", - screen->last_xinerama_index); - } - - return &screen->xinerama_infos[screen->last_xinerama_index]; -} - -#define _NET_WM_ORIENTATION_HORZ 0 -#define _NET_WM_ORIENTATION_VERT 1 - -#define _NET_WM_TOPLEFT 0 -#define _NET_WM_TOPRIGHT 1 -#define _NET_WM_BOTTOMRIGHT 2 -#define _NET_WM_BOTTOMLEFT 3 - -void -meta_screen_update_workspace_layout (MetaScreen *screen) -{ - gulong *list; - int n_items; - - list = NULL; - n_items = 0; - - if (meta_prop_get_cardinal_list (screen->display, - screen->xroot, - screen->display->atom__NET_DESKTOP_LAYOUT, - &list, &n_items)) - { - if (n_items == 3 || n_items == 4) - { - int cols, rows; - - switch (list[0]) - { - case _NET_WM_ORIENTATION_HORZ: - screen->vertical_workspaces = FALSE; - break; - case _NET_WM_ORIENTATION_VERT: - screen->vertical_workspaces = TRUE; - break; - default: - meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT\n"); - break; - } - - cols = list[1]; - rows = list[2]; - - if (rows <= 0 && cols <= 0) - { - meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense\n", rows, cols); - } - else - { - if (rows > 0) - screen->rows_of_workspaces = rows; - else - screen->rows_of_workspaces = -1; - - if (cols > 0) - screen->columns_of_workspaces = cols; - else - screen->columns_of_workspaces = -1; - } - - if (n_items == 4) - { - switch (list[3]) - { - case _NET_WM_TOPLEFT: - screen->starting_corner = META_SCREEN_TOPLEFT; - break; - case _NET_WM_TOPRIGHT: - screen->starting_corner = META_SCREEN_TOPRIGHT; - break; - case _NET_WM_BOTTOMRIGHT: - screen->starting_corner = META_SCREEN_BOTTOMRIGHT; - break; - case _NET_WM_BOTTOMLEFT: - screen->starting_corner = META_SCREEN_BOTTOMLEFT; - break; - default: - meta_warning ("Someone set a weird starting corner in _NET_DESKTOP_LAYOUT\n"); - break; - } - } - else - screen->starting_corner = META_SCREEN_TOPLEFT; - } - else - { - meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 4 " - "(3 is accepted for backwards compat)\n", n_items); - } - - meta_XFree (list); - } - - meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d starting corner = %u\n", - screen->rows_of_workspaces, - screen->columns_of_workspaces, - screen->vertical_workspaces, - screen->starting_corner); -} - -static void -set_workspace_names (MetaScreen *screen) -{ - /* This updates names on root window when the pref changes, - * note we only get prefs change notify if things have - * really changed. - */ - GString *flattened; - int i; - int n_spaces; - - /* flatten to nul-separated list */ - n_spaces = meta_screen_get_n_workspaces (screen); - flattened = g_string_new (""); - i = 0; - while (i < n_spaces) - { - const char *name; - - name = meta_prefs_get_workspace_name (i); - - if (name) - g_string_append_len (flattened, name, - strlen (name) + 1); - else - g_string_append_len (flattened, "", 1); - - ++i; - } - - meta_error_trap_push (screen->display); - XChangeProperty (screen->display->xdisplay, - screen->xroot, - screen->display->atom__NET_DESKTOP_NAMES, - screen->display->atom_UTF8_STRING, - 8, PropModeReplace, - (unsigned char *)flattened->str, flattened->len); - meta_error_trap_pop (screen->display, FALSE); - - g_string_free (flattened, TRUE); -} - -void -meta_screen_update_workspace_names (MetaScreen *screen) -{ - char **names; - int n_names; - int i; - - /* this updates names in prefs when the root window property changes, - * iff the new property contents don't match what's already in prefs - */ - - names = NULL; - n_names = 0; - if (!meta_prop_get_utf8_list (screen->display, - screen->xroot, - screen->display->atom__NET_DESKTOP_NAMES, - &names, &n_names)) - { - meta_verbose ("Failed to get workspace names from root window %d\n", - screen->number); - return; - } - - i = 0; - while (i < n_names) - { - meta_topic (META_DEBUG_PREFS, - "Setting workspace %d name to \"%s\" due to _NET_DESKTOP_NAMES change\n", - i, names[i] ? names[i] : "null"); - meta_prefs_change_workspace_name (i, names[i]); - - ++i; - } - - g_strfreev (names); -} - -Window -meta_create_offscreen_window (Display *xdisplay, - Window parent, - long valuemask) -{ - XSetWindowAttributes attrs; - - /* we want to be override redirect because sometimes we - * create a window on a screen we aren't managing. - * (but on a display we are managing at least one screen for) - */ - attrs.override_redirect = True; - attrs.event_mask = valuemask; - - return XCreateWindow (xdisplay, - parent, - -100, -100, 1, 1, - 0, - CopyFromParent, - CopyFromParent, - (Visual *)CopyFromParent, - CWOverrideRedirect | CWEventMask, - &attrs); -} - -static void -set_work_area_hint (MetaScreen *screen) -{ - int num_workspaces; - GList *tmp_list; - unsigned long *data, *tmp; - MetaRectangle area; - - num_workspaces = meta_screen_get_n_workspaces (screen); - data = g_new (unsigned long, num_workspaces * 4); - tmp_list = screen->workspaces; - tmp = data; - - while (tmp_list != NULL) - { - MetaWorkspace *workspace = tmp_list->data; - - if (workspace->screen == screen) - { - meta_workspace_get_work_area_all_xineramas (workspace, &area); - tmp[0] = area.x; - tmp[1] = area.y; - tmp[2] = area.width; - tmp[3] = area.height; - - tmp += 4; - } - - tmp_list = tmp_list->next; - } - - meta_error_trap_push (screen->display); - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom__NET_WORKAREA, - XA_CARDINAL, 32, PropModeReplace, - (guchar*) data, num_workspaces*4); - g_free (data); - meta_error_trap_pop (screen->display, FALSE); -} - -static gboolean -set_work_area_idle_func (MetaScreen *screen) -{ - meta_topic (META_DEBUG_WORKAREA, - "Running work area idle function\n"); - - screen->work_area_idle = 0; - - set_work_area_hint (screen); - - return FALSE; -} - -void -meta_screen_queue_workarea_recalc (MetaScreen *screen) -{ - /* Recompute work area in an idle */ - if (screen->work_area_idle == 0) - { - meta_topic (META_DEBUG_WORKAREA, - "Adding work area hint idle function\n"); - screen->work_area_idle = - g_idle_add_full (META_PRIORITY_WORK_AREA_HINT, - (GSourceFunc) set_work_area_idle_func, - screen, - NULL); - } -} - - -#ifdef WITH_VERBOSE_MODE -static char * -meta_screen_corner_to_string (MetaScreenCorner corner) -{ - switch (corner) - { - case META_SCREEN_TOPLEFT: - return "TopLeft"; - case META_SCREEN_TOPRIGHT: - return "TopRight"; - case META_SCREEN_BOTTOMLEFT: - return "BottomLeft"; - case META_SCREEN_BOTTOMRIGHT: - return "BottomRight"; - } - - return "Unknown"; -} -#endif /* WITH_VERBOSE_MODE */ - -void -meta_screen_calc_workspace_layout (MetaScreen *screen, - int num_workspaces, - int current_space, - MetaWorkspaceLayout *layout) -{ - int rows, cols; - int grid_area; - int *grid; - int i, r, c; - int current_row, current_col; - - rows = screen->rows_of_workspaces; - cols = screen->columns_of_workspaces; - if (rows <= 0 && cols <= 0) - cols = num_workspaces; - - if (rows <= 0) - rows = num_workspaces / cols + ((num_workspaces % cols) > 0 ? 1 : 0); - if (cols <= 0) - cols = num_workspaces / rows + ((num_workspaces % rows) > 0 ? 1 : 0); - - /* paranoia */ - if (rows < 1) - rows = 1; - if (cols < 1) - cols = 1; - - g_assert (rows != 0 && cols != 0); - - grid_area = rows * cols; - - meta_verbose ("Getting layout rows = %d cols = %d current = %d " - "num_spaces = %d vertical = %s corner = %s\n", - rows, cols, current_space, num_workspaces, - screen->vertical_workspaces ? "(true)" : "(false)", - meta_screen_corner_to_string (screen->starting_corner)); - - /* ok, we want to setup the distances in the workspace array to go - * in each direction. Remember, there are many ways that a workspace - * array can be setup. - * see http://www.freedesktop.org/standards/wm-spec/1.2/html/x109.html - * and look at the _NET_DESKTOP_LAYOUT section for details. - * For instance: - */ - /* starting_corner = META_SCREEN_TOPLEFT - * vertical_workspaces = 0 vertical_workspaces=1 - * 1234 1357 - * 5678 2468 - * - * starting_corner = META_SCREEN_TOPRIGHT - * vertical_workspaces = 0 vertical_workspaces=1 - * 4321 7531 - * 8765 8642 - * - * starting_corner = META_SCREEN_BOTTOMLEFT - * vertical_workspaces = 0 vertical_workspaces=1 - * 5678 2468 - * 1234 1357 - * - * starting_corner = META_SCREEN_BOTTOMRIGHT - * vertical_workspaces = 0 vertical_workspaces=1 - * 8765 8642 - * 4321 7531 - * - */ - /* keep in mind that we could have a ragged layout, e.g. the "8" - * in the above grids could be missing - */ - - - grid = g_new (int, grid_area); - - current_row = -1; - current_col = -1; - i = 0; - - switch (screen->starting_corner) - { - case META_SCREEN_TOPLEFT: - if (screen->vertical_workspaces) - { - c = 0; - while (c < cols) - { - r = 0; - while (r < rows) - { - grid[r*cols+c] = i; - ++i; - ++r; - } - ++c; - } - } - else - { - r = 0; - while (r < rows) - { - c = 0; - while (c < cols) - { - grid[r*cols+c] = i; - ++i; - ++c; - } - ++r; - } - } - break; - case META_SCREEN_TOPRIGHT: - if (screen->vertical_workspaces) - { - c = cols - 1; - while (c >= 0) - { - r = 0; - while (r < rows) - { - grid[r*cols+c] = i; - ++i; - ++r; - } - --c; - } - } - else - { - r = 0; - while (r < rows) - { - c = cols - 1; - while (c >= 0) - { - grid[r*cols+c] = i; - ++i; - --c; - } - ++r; - } - } - break; - case META_SCREEN_BOTTOMLEFT: - if (screen->vertical_workspaces) - { - c = 0; - while (c < cols) - { - r = rows - 1; - while (r >= 0) - { - grid[r*cols+c] = i; - ++i; - --r; - } - ++c; - } - } - else - { - r = rows - 1; - while (r >= 0) - { - c = 0; - while (c < cols) - { - grid[r*cols+c] = i; - ++i; - ++c; - } - --r; - } - } - break; - case META_SCREEN_BOTTOMRIGHT: - if (screen->vertical_workspaces) - { - c = cols - 1; - while (c >= 0) - { - r = rows - 1; - while (r >= 0) - { - grid[r*cols+c] = i; - ++i; - --r; - } - --c; - } - } - else - { - r = rows - 1; - while (r >= 0) - { - c = cols - 1; - while (c >= 0) - { - grid[r*cols+c] = i; - ++i; - --c; - } - --r; - } - } - break; - } - - if (i != grid_area) - meta_bug ("did not fill in the whole workspace grid in %s (%d filled)\n", - G_STRFUNC, i); - - current_row = 0; - current_col = 0; - r = 0; - while (r < rows) - { - c = 0; - while (c < cols) - { - if (grid[r*cols+c] == current_space) - { - current_row = r; - current_col = c; - } - else if (grid[r*cols+c] >= num_workspaces) - { - /* flag nonexistent spaces with -1 */ - grid[r*cols+c] = -1; - } - ++c; - } - ++r; - } - - layout->rows = rows; - layout->cols = cols; - layout->grid = grid; - layout->grid_area = grid_area; - layout->current_row = current_row; - layout->current_col = current_col; - -#ifdef WITH_VERBOSE_MODE - if (meta_is_verbose ()) - { - r = 0; - while (r < layout->rows) - { - meta_verbose (" "); - meta_push_no_msg_prefix (); - c = 0; - while (c < layout->cols) - { - if (r == layout->current_row && - c == layout->current_col) - meta_verbose ("*%2d ", layout->grid[r*layout->cols+c]); - else - meta_verbose ("%3d ", layout->grid[r*layout->cols+c]); - ++c; - } - meta_verbose ("\n"); - meta_pop_no_msg_prefix (); - ++r; - } - } -#endif /* WITH_VERBOSE_MODE */ -} - -void -meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout) -{ - g_free (layout->grid); -} - -static void -meta_screen_resize_func (MetaScreen *screen, - MetaWindow *window, - void *user_data) -{ - if (window->struts) - { - meta_window_update_struts (window); - } - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - - meta_window_recalc_features (window); -} - -void -meta_screen_resize (MetaScreen *screen, - int width, - int height) -{ - screen->rect.width = width; - screen->rect.height = height; - - reload_xinerama_infos (screen); - set_desktop_geometry_hint (screen); - - /* Queue a resize on all the windows */ - meta_screen_foreach_window (screen, meta_screen_resize_func, 0); -} - -void -meta_screen_update_showing_desktop_hint (MetaScreen *screen) -{ - unsigned long data[1]; - - data[0] = screen->active_workspace->showing_desktop ? 1 : 0; - - meta_error_trap_push (screen->display); - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom__NET_SHOWING_DESKTOP, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - meta_error_trap_pop (screen->display, FALSE); -} - -static void -queue_windows_showing (MetaScreen *screen) -{ - GSList *windows; - GSList *tmp; - - /* Must operate on all windows on display instead of just on the - * active_workspace's window list, because the active_workspace's - * window list may not contain the on_all_workspace windows. - */ - windows = meta_display_list_windows (screen->display); - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->screen == screen) - meta_window_queue (w, META_QUEUE_CALC_SHOWING); - - tmp = tmp->next; - } - - g_slist_free (windows); -} - -void -meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen, - MetaWindow *keep) -{ - GList *windows; - GList *tmp; - - windows = screen->active_workspace->windows; - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->screen == screen && - w->has_minimize_func && - w != keep) - meta_window_minimize (w); - - tmp = tmp->next; - } -} - -void -meta_screen_show_desktop (MetaScreen *screen, - guint32 timestamp) -{ - GList *windows; - - if (screen->active_workspace->showing_desktop) - return; - - screen->active_workspace->showing_desktop = TRUE; - - queue_windows_showing (screen); - - /* Focus the most recently used META_WINDOW_DESKTOP window, if there is one; - * see bug 159257. - */ - windows = screen->active_workspace->mru_list; - while (windows != NULL) - { - MetaWindow *w = windows->data; - - if (w->screen == screen && - w->type == META_WINDOW_DESKTOP) - { - meta_window_focus (w, timestamp); - break; - } - - windows = windows->next; - } - - - meta_screen_update_showing_desktop_hint (screen); -} - -void -meta_screen_unshow_desktop (MetaScreen *screen) -{ - if (!screen->active_workspace->showing_desktop) - return; - - screen->active_workspace->showing_desktop = FALSE; - - queue_windows_showing (screen); - - meta_screen_update_showing_desktop_hint (screen); -} - - -#ifdef HAVE_STARTUP_NOTIFICATION -static gboolean startup_sequence_timeout (void *data); - -static void -update_startup_feedback (MetaScreen *screen) -{ - if (screen->startup_sequences != NULL) - { - meta_topic (META_DEBUG_STARTUP, - "Setting busy cursor\n"); - meta_screen_set_cursor (screen, META_CURSOR_BUSY); - } - else - { - meta_topic (META_DEBUG_STARTUP, - "Setting default cursor\n"); - meta_screen_set_cursor (screen, META_CURSOR_DEFAULT); - } -} - -static void -add_sequence (MetaScreen *screen, - SnStartupSequence *sequence) -{ - meta_topic (META_DEBUG_STARTUP, - "Adding sequence %s\n", - sn_startup_sequence_get_id (sequence)); - sn_startup_sequence_ref (sequence); - screen->startup_sequences = g_slist_prepend (screen->startup_sequences, - sequence); - - /* our timeout just polls every second, instead of bothering - * to compute exactly when we may next time out - */ - if (screen->startup_sequence_timeout == 0) - screen->startup_sequence_timeout = g_timeout_add (1000, - startup_sequence_timeout, - screen); - - update_startup_feedback (screen); -} - -static void -remove_sequence (MetaScreen *screen, - SnStartupSequence *sequence) -{ - meta_topic (META_DEBUG_STARTUP, - "Removing sequence %s\n", - sn_startup_sequence_get_id (sequence)); - - screen->startup_sequences = g_slist_remove (screen->startup_sequences, - sequence); - sn_startup_sequence_unref (sequence); - - if (screen->startup_sequences == NULL && - screen->startup_sequence_timeout != 0) - { - g_source_remove (screen->startup_sequence_timeout); - screen->startup_sequence_timeout = 0; - } - - update_startup_feedback (screen); -} - -typedef struct -{ - GSList *list; - GTimeVal now; -} CollectTimedOutData; - -/* This should be fairly long, as it should never be required unless - * apps or .desktop files are buggy, and it's confusing if - * OpenOffice or whatever seems to stop launching - people - * might decide they need to launch it again. - */ -#define STARTUP_TIMEOUT 15000 - -static void -collect_timed_out_foreach (void *element, - void *data) -{ - CollectTimedOutData *ctod = data; - SnStartupSequence *sequence = element; - long tv_sec, tv_usec; - double elapsed; - - sn_startup_sequence_get_last_active_time (sequence, &tv_sec, &tv_usec); - - elapsed = - ((((double)ctod->now.tv_sec - tv_sec) * G_USEC_PER_SEC + - (ctod->now.tv_usec - tv_usec))) / 1000.0; - - meta_topic (META_DEBUG_STARTUP, - "Sequence used %g seconds vs. %g max: %s\n", - elapsed, (double) STARTUP_TIMEOUT, - sn_startup_sequence_get_id (sequence)); - - if (elapsed > STARTUP_TIMEOUT) - ctod->list = g_slist_prepend (ctod->list, sequence); -} - -static gboolean -startup_sequence_timeout (void *data) -{ - MetaScreen *screen = data; - CollectTimedOutData ctod; - GSList *tmp; - - ctod.list = NULL; - g_get_current_time (&ctod.now); - g_slist_foreach (screen->startup_sequences, - collect_timed_out_foreach, - &ctod); - - tmp = ctod.list; - while (tmp != NULL) - { - SnStartupSequence *sequence = tmp->data; - - meta_topic (META_DEBUG_STARTUP, - "Timed out sequence %s\n", - sn_startup_sequence_get_id (sequence)); - - sn_startup_sequence_complete (sequence); - - tmp = tmp->next; - } - - g_slist_free (ctod.list); - - if (screen->startup_sequences != NULL) - { - return TRUE; - } - else - { - /* remove */ - screen->startup_sequence_timeout = 0; - return FALSE; - } -} - -static void -meta_screen_sn_event (SnMonitorEvent *event, - void *user_data) -{ - MetaScreen *screen; - SnStartupSequence *sequence; - - screen = user_data; - - sequence = sn_monitor_event_get_startup_sequence (event); - - switch (sn_monitor_event_get_type (event)) - { - case SN_MONITOR_EVENT_INITIATED: - { - const char *wmclass; - - wmclass = sn_startup_sequence_get_wmclass (sequence); - - meta_topic (META_DEBUG_STARTUP, - "Received startup initiated for %s wmclass %s\n", - sn_startup_sequence_get_id (sequence), - wmclass ? wmclass : "(unset)"); - add_sequence (screen, sequence); - } - break; - - case SN_MONITOR_EVENT_COMPLETED: - { - meta_topic (META_DEBUG_STARTUP, - "Received startup completed for %s\n", - sn_startup_sequence_get_id (sequence)); - remove_sequence (screen, - sn_monitor_event_get_startup_sequence (event)); - } - break; - - case SN_MONITOR_EVENT_CHANGED: - meta_topic (META_DEBUG_STARTUP, - "Received startup changed for %s\n", - sn_startup_sequence_get_id (sequence)); - break; - - case SN_MONITOR_EVENT_CANCELED: - meta_topic (META_DEBUG_STARTUP, - "Received startup canceled for %s\n", - sn_startup_sequence_get_id (sequence)); - break; - } -} -#endif - -/* Sets the initial_timestamp and initial_workspace properties - * of a window according to information given us by the - * startup-notification library. - * - * Returns TRUE if startup properties have been applied, and - * FALSE if they have not (for example, if they had already - * been applied.) - */ -gboolean -meta_screen_apply_startup_properties (MetaScreen *screen, - MetaWindow *window) -{ -#ifdef HAVE_STARTUP_NOTIFICATION - const char *startup_id; - GSList *tmp; - SnStartupSequence *sequence; - - /* Does the window have a startup ID stored? */ - startup_id = meta_window_get_startup_id (window); - - meta_topic (META_DEBUG_STARTUP, - "Applying startup props to %s id \"%s\"\n", - window->desc, - startup_id ? startup_id : "(none)"); - - sequence = NULL; - if (startup_id == NULL) - { - /* No startup ID stored for the window. Let's ask the - * startup-notification library whether there's anything - * stored for the resource name or resource class hints. - */ - tmp = screen->startup_sequences; - while (tmp != NULL) - { - const char *wmclass; - - wmclass = sn_startup_sequence_get_wmclass (tmp->data); - - if (wmclass != NULL && - ((window->res_class && - strcmp (wmclass, window->res_class) == 0) || - (window->res_name && - strcmp (wmclass, window->res_name) == 0))) - { - sequence = tmp->data; - - g_assert (window->startup_id == NULL); - window->startup_id = g_strdup (sn_startup_sequence_get_id (sequence)); - startup_id = window->startup_id; - - meta_topic (META_DEBUG_STARTUP, - "Ending legacy sequence %s due to window %s\n", - sn_startup_sequence_get_id (sequence), - window->desc); - - sn_startup_sequence_complete (sequence); - break; - } - - tmp = tmp->next; - } - } - - /* Still no startup ID? Bail. */ - if (startup_id == NULL) - return FALSE; - - /* We might get this far and not know the sequence ID (if the window - * already had a startup ID stored), so let's look for one if we don't - * already know it. - */ - if (sequence == NULL) - { - tmp = screen->startup_sequences; - while (tmp != NULL) - { - const char *id; - - id = sn_startup_sequence_get_id (tmp->data); - - if (strcmp (id, startup_id) == 0) - { - sequence = tmp->data; - break; - } - - tmp = tmp->next; - } - } - - if (sequence != NULL) - { - gboolean changed_something = FALSE; - - meta_topic (META_DEBUG_STARTUP, - "Found startup sequence for window %s ID \"%s\"\n", - window->desc, startup_id); - - if (!window->initial_workspace_set) - { - int space = sn_startup_sequence_get_workspace (sequence); - if (space >= 0) - { - meta_topic (META_DEBUG_STARTUP, - "Setting initial window workspace to %d based on startup info\n", - space); - - window->initial_workspace_set = TRUE; - window->initial_workspace = space; - changed_something = TRUE; - } - } - - if (!window->initial_timestamp_set) - { - guint32 timestamp = sn_startup_sequence_get_timestamp (sequence); - meta_topic (META_DEBUG_STARTUP, - "Setting initial window timestamp to %u based on startup info\n", - timestamp); - - window->initial_timestamp_set = TRUE; - window->initial_timestamp = timestamp; - changed_something = TRUE; - } - - return changed_something; - } - else - { - meta_topic (META_DEBUG_STARTUP, - "Did not find startup sequence for window %s ID \"%s\"\n", - window->desc, startup_id); - } - -#endif /* HAVE_STARTUP_NOTIFICATION */ - - return FALSE; -} - -int -meta_screen_get_screen_number (MetaScreen *screen) -{ - return screen->number; -} - -MetaDisplay * -meta_screen_get_display (MetaScreen *screen) -{ - return screen->display; -} - -Window -meta_screen_get_xroot (MetaScreen *screen) -{ - return screen->xroot; -} - -void -meta_screen_get_size (MetaScreen *screen, - int *width, - int *height) -{ - *width = screen->rect.width; - *height = screen->rect.height; -} - -gpointer -meta_screen_get_compositor_data (MetaScreen *screen) -{ - return screen->compositor_data; -} - -void -meta_screen_set_compositor_data (MetaScreen *screen, - gpointer compositor) -{ - screen->compositor_data = compositor; -} - -#ifdef HAVE_COMPOSITE_EXTENSIONS -void -meta_screen_set_cm_selection (MetaScreen *screen) -{ - char selection[32]; - Atom a; - - g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number); - meta_verbose ("Setting selection: %s\n", selection); - a = XInternAtom (screen->display->xdisplay, selection, FALSE); - XSetSelectionOwner (screen->display->xdisplay, a, - screen->wm_cm_selection_window, CurrentTime); -} - -void -meta_screen_unset_cm_selection (MetaScreen *screen) -{ - char selection[32]; - Atom a; - - g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number); - a = XInternAtom (screen->display->xdisplay, selection, FALSE); - XSetSelectionOwner (screen->display->xdisplay, a, None, CurrentTime); -} -#endif /* HAVE_COMPOSITE_EXTENSIONS */ diff --git a/src/core/session.c b/src/core/session.c deleted file mode 100644 index fc29e13d..00000000 --- a/src/core/session.c +++ /dev/null @@ -1,1900 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity Session Management */ - -/* - * Copyright (C) 2001 Havoc Pennington (some code in here from - * libgnomeui, (C) Tom Tromey, Carsten Schaar) - * Copyright (C) 2004, 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> - -#include "session.h" -#include <X11/Xatom.h> - -#include <time.h> - -#ifndef HAVE_SM -void -meta_session_init (const char *client_id, - const char *save_file) -{ - meta_topic (META_DEBUG_SM, "Compiled without session management support\n"); -} - -void -meta_session_shutdown (void) -{ - /* nothing */ -} - -const MetaWindowSessionInfo* -meta_window_lookup_saved_state (MetaWindow *window) -{ - return NULL; -} - -void -meta_window_release_saved_state (const MetaWindowSessionInfo *info) -{ - ; -} -#else /* HAVE_SM */ - -#include <X11/ICE/ICElib.h> -#include <X11/SM/SMlib.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <fcntl.h> -#include <errno.h> -#include <glib.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include "main.h" -#include "util.h" -#include "display-private.h" -#include "workspace.h" - -static void ice_io_error_handler (IceConn connection); - -static void new_ice_connection (IceConn connection, IcePointer client_data, - Bool opening, IcePointer *watch_data); - -static void save_state (void); -static char* load_state (const char *previous_save_file); -static void regenerate_save_file (void); -static const char* full_save_file (void); -static void warn_about_lame_clients_and_finish_interact (gboolean shutdown); - -/* This is called when data is available on an ICE connection. */ -static gboolean -process_ice_messages (GIOChannel *channel, - GIOCondition condition, - gpointer client_data) -{ - IceConn connection = (IceConn) client_data; - IceProcessMessagesStatus status; - - /* This blocks infinitely sometimes. I don't know what - * to do about it. Checking "condition" just breaks - * session management. - */ - status = IceProcessMessages (connection, NULL, NULL); - - if (status == IceProcessMessagesIOError) - { -#if 0 - IcePointer context = IceGetConnectionContext (connection); -#endif - - /* We were disconnected */ - IceSetShutdownNegotiation (connection, False); - IceCloseConnection (connection); - - return FALSE; - } - - return TRUE; -} - -/* This is called when a new ICE connection is made. It arranges for - the ICE connection to be handled via the event loop. */ -static void -new_ice_connection (IceConn connection, IcePointer client_data, Bool opening, - IcePointer *watch_data) -{ - guint input_id; - - if (opening) - { - /* Make sure we don't pass on these file descriptors to any - * exec'ed children - */ - GIOChannel *channel; - - fcntl (IceConnectionNumber (connection), F_SETFD, - fcntl (IceConnectionNumber (connection), F_GETFD, 0) | FD_CLOEXEC); - - channel = g_io_channel_unix_new (IceConnectionNumber (connection)); - - input_id = g_io_add_watch (channel, - G_IO_IN | G_IO_ERR, - process_ice_messages, - connection); - - g_io_channel_unref (channel); - - *watch_data = (IcePointer) GUINT_TO_POINTER (input_id); - } - else - { - input_id = GPOINTER_TO_UINT ((gpointer) *watch_data); - - g_source_remove (input_id); - } -} - -static IceIOErrorHandler ice_installed_handler; - -/* We call any handler installed before (or after) gnome_ice_init but - avoid calling the default libICE handler which does an exit() */ -static void -ice_io_error_handler (IceConn connection) -{ - if (ice_installed_handler) - (*ice_installed_handler) (connection); -} - -static void -ice_init (void) -{ - static gboolean ice_initted = FALSE; - - if (! ice_initted) - { - IceIOErrorHandler default_handler; - - ice_installed_handler = IceSetIOErrorHandler (NULL); - default_handler = IceSetIOErrorHandler (ice_io_error_handler); - - if (ice_installed_handler == default_handler) - ice_installed_handler = NULL; - - IceAddConnectionWatch (new_ice_connection, NULL); - - ice_initted = TRUE; - } -} - -typedef enum -{ - STATE_DISCONNECTED, - STATE_IDLE, - STATE_SAVING_PHASE_1, - STATE_WAITING_FOR_PHASE_2, - STATE_SAVING_PHASE_2, - STATE_WAITING_FOR_INTERACT, - STATE_DONE_WITH_INTERACT, - STATE_SKIPPING_GLOBAL_SAVE, - STATE_FROZEN, - STATE_REGISTERING -} ClientState; - -static void save_phase_2_callback (SmcConn smc_conn, - SmPointer client_data); -static void interact_callback (SmcConn smc_conn, - SmPointer client_data); -static void shutdown_cancelled_callback (SmcConn smc_conn, - SmPointer client_data); -static void save_complete_callback (SmcConn smc_conn, - SmPointer client_data); -static void die_callback (SmcConn smc_conn, - SmPointer client_data); -static void save_yourself_callback (SmcConn smc_conn, - SmPointer client_data, - int save_style, - Bool shutdown, - int interact_style, - Bool fast); -static void set_clone_restart_commands (void); - -static char *client_id = NULL; -static gpointer session_connection = NULL; -static ClientState current_state = STATE_DISCONNECTED; -static gboolean interaction_allowed = FALSE; - -void -meta_session_init (const char *previous_client_id, - const char *previous_save_file) -{ - /* Some code here from twm */ - char buf[256]; - unsigned long mask; - SmcCallbacks callbacks; - char *saved_client_id; - - meta_topic (META_DEBUG_SM, "Initializing session with save file '%s'\n", - previous_save_file ? previous_save_file : "(none)"); - - if (previous_save_file) - { - saved_client_id = load_state (previous_save_file); - previous_client_id = saved_client_id; - } - else if (previous_client_id) - { - char *save_file = g_strconcat (previous_client_id, ".ms", NULL); - saved_client_id = load_state (save_file); - g_free (save_file); - } - else - { - saved_client_id = NULL; - } - - ice_init (); - - mask = SmcSaveYourselfProcMask | SmcDieProcMask | - SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; - - callbacks.save_yourself.callback = save_yourself_callback; - callbacks.save_yourself.client_data = NULL; - - callbacks.die.callback = die_callback; - callbacks.die.client_data = NULL; - - callbacks.save_complete.callback = save_complete_callback; - callbacks.save_complete.client_data = NULL; - - callbacks.shutdown_cancelled.callback = shutdown_cancelled_callback; - callbacks.shutdown_cancelled.client_data = NULL; - - session_connection = - SmcOpenConnection (NULL, /* use SESSION_MANAGER env */ - NULL, /* means use existing ICE connection */ - SmProtoMajor, - SmProtoMinor, - mask, - &callbacks, - (char*) previous_client_id, - &client_id, - 255, buf); - - if (session_connection == NULL) - { - meta_topic (META_DEBUG_SM, - "Failed to a open connection to a session manager, so window positions will not be saved: %s\n", - buf); - - goto out; - } - else - { - if (client_id == NULL) - meta_bug ("Session manager gave us a NULL client ID?"); - meta_topic (META_DEBUG_SM, "Obtained session ID '%s'\n", client_id); - } - - if (previous_client_id && strcmp (previous_client_id, client_id) == 0) - current_state = STATE_IDLE; - else - current_state = STATE_REGISTERING; - - { - SmProp prop1, prop2, prop3, prop4, prop5, prop6, *props[6]; - SmPropValue prop1val, prop2val, prop3val, prop4val, prop5val, prop6val; - char pid[32]; - char hint = SmRestartImmediately; - char priority = 20; /* low to run before other apps */ - - prop1.name = SmProgram; - prop1.type = SmARRAY8; - prop1.num_vals = 1; - prop1.vals = &prop1val; - prop1val.value = "metacity"; - prop1val.length = strlen ("metacity"); - - /* twm sets getuid() for this, but the SM spec plainly - * says pw_name, twm is on crack - */ - prop2.name = SmUserID; - prop2.type = SmARRAY8; - prop2.num_vals = 1; - prop2.vals = &prop2val; - prop2val.value = (char*) g_get_user_name (); - prop2val.length = strlen (prop2val.value); - - prop3.name = SmRestartStyleHint; - prop3.type = SmCARD8; - prop3.num_vals = 1; - prop3.vals = &prop3val; - prop3val.value = &hint; - prop3val.length = 1; - - sprintf (pid, "%d", getpid ()); - prop4.name = SmProcessID; - prop4.type = SmARRAY8; - prop4.num_vals = 1; - prop4.vals = &prop4val; - prop4val.value = pid; - prop4val.length = strlen (prop4val.value); - - /* Always start in home directory */ - prop5.name = SmCurrentDirectory; - prop5.type = SmARRAY8; - prop5.num_vals = 1; - prop5.vals = &prop5val; - prop5val.value = (char*) g_get_home_dir (); - prop5val.length = strlen (prop5val.value); - - prop6.name = "_GSM_Priority"; - prop6.type = SmCARD8; - prop6.num_vals = 1; - prop6.vals = &prop6val; - prop6val.value = &priority; - prop6val.length = 1; - - props[0] = &prop1; - props[1] = &prop2; - props[2] = &prop3; - props[3] = &prop4; - props[4] = &prop5; - props[5] = &prop6; - - SmcSetProperties (session_connection, 6, props); - } - - out: - g_free (saved_client_id); -} - -void -meta_session_shutdown (void) -{ - /* Change our restart mode to IfRunning */ - - SmProp prop1; - SmPropValue prop1val; - SmProp *props[1]; - char hint = SmRestartIfRunning; - - if (session_connection == NULL) - return; - - prop1.name = SmRestartStyleHint; - prop1.type = SmCARD8; - prop1.num_vals = 1; - prop1.vals = &prop1val; - prop1val.value = &hint; - prop1val.length = 1; - - props[0] = &prop1; - - SmcSetProperties (session_connection, 1, props); -} - -static void -disconnect (void) -{ - SmcCloseConnection (session_connection, 0, NULL); - session_connection = NULL; - current_state = STATE_DISCONNECTED; -} - -static void -save_yourself_possibly_done (gboolean shutdown, - gboolean successful) -{ - meta_topic (META_DEBUG_SM, - "save possibly done shutdown = %d success = %d\n", - shutdown, successful); - - if (current_state == STATE_SAVING_PHASE_1) - { - Status status; - - status = SmcRequestSaveYourselfPhase2 (session_connection, - save_phase_2_callback, - GINT_TO_POINTER (shutdown)); - - if (status) - current_state = STATE_WAITING_FOR_PHASE_2; - - meta_topic (META_DEBUG_SM, - "Requested phase 2, status = %d\n", status); - } - - if (current_state == STATE_SAVING_PHASE_2 && - interaction_allowed) - { - Status status; - - status = SmcInteractRequest (session_connection, - /* ignore this feature of the protocol by always - * claiming normal - */ - SmDialogNormal, - interact_callback, - GINT_TO_POINTER (shutdown)); - - if (status) - current_state = STATE_WAITING_FOR_INTERACT; - - meta_topic (META_DEBUG_SM, - "Requested interact, status = %d\n", status); - } - - if (current_state == STATE_SAVING_PHASE_1 || - current_state == STATE_SAVING_PHASE_2 || - current_state == STATE_DONE_WITH_INTERACT || - current_state == STATE_SKIPPING_GLOBAL_SAVE) - { - meta_topic (META_DEBUG_SM, "Sending SaveYourselfDone\n"); - - SmcSaveYourselfDone (session_connection, - successful); - - if (shutdown) - current_state = STATE_FROZEN; - else - current_state = STATE_IDLE; - } -} - -static void -save_phase_2_callback (SmcConn smc_conn, SmPointer client_data) -{ - gboolean shutdown; - - meta_topic (META_DEBUG_SM, "Phase 2 save"); - - shutdown = GPOINTER_TO_INT (client_data); - - current_state = STATE_SAVING_PHASE_2; - - save_state (); - - save_yourself_possibly_done (shutdown, TRUE); -} - -static void -save_yourself_callback (SmcConn smc_conn, - SmPointer client_data, - int save_style, - Bool shutdown, - int interact_style, - Bool fast) -{ - gboolean successful; - - meta_topic (META_DEBUG_SM, "SaveYourself received"); - - successful = TRUE; - - /* The first SaveYourself after registering for the first time - * is a special case (SM specs 7.2). - */ - -#if 0 /* I think the GnomeClient rationale for this doesn't apply */ - if (current_state == STATE_REGISTERING) - { - current_state = STATE_IDLE; - /* Double check that this is a section 7.2 SaveYourself: */ - - if (save_style == SmSaveLocal && - interact_style == SmInteractStyleNone && - !shutdown && !fast) - { - /* The protocol requires this even if xsm ignores it. */ - SmcSaveYourselfDone (session_connection, successful); - return; - } - } -#endif - - /* ignore Global style saves - * - * This interpretaion of the Local/Global/Both styles - * was discussed extensively on the xdg-list. See: - * - * https://listman.redhat.com/pipermail/xdg-list/2002-July/000615.html - */ - if (save_style == SmSaveGlobal) - { - current_state = STATE_SKIPPING_GLOBAL_SAVE; - save_yourself_possibly_done (shutdown, successful); - return; - } - - interaction_allowed = interact_style != SmInteractStyleNone; - - current_state = STATE_SAVING_PHASE_1; - - regenerate_save_file (); - - set_clone_restart_commands (); - - save_yourself_possibly_done (shutdown, successful); -} - - -static void -die_callback (SmcConn smc_conn, SmPointer client_data) -{ - meta_topic (META_DEBUG_SM, "Exiting at request of session manager\n"); - disconnect (); - meta_quit (META_EXIT_SUCCESS); -} - -static void -save_complete_callback (SmcConn smc_conn, SmPointer client_data) -{ - /* nothing */ - meta_topic (META_DEBUG_SM, "SaveComplete received\n"); -} - -static void -shutdown_cancelled_callback (SmcConn smc_conn, SmPointer client_data) -{ - meta_topic (META_DEBUG_SM, "Shutdown cancelled received\n"); - - if (session_connection != NULL && - (current_state != STATE_IDLE && current_state != STATE_FROZEN)) - { - SmcSaveYourselfDone (session_connection, True); - current_state = STATE_IDLE; - } -} - -static void -interact_callback (SmcConn smc_conn, SmPointer client_data) -{ - /* nothing */ - gboolean shutdown; - - meta_topic (META_DEBUG_SM, "Interaction permission received\n"); - - shutdown = GPOINTER_TO_INT (client_data); - - current_state = STATE_DONE_WITH_INTERACT; - - warn_about_lame_clients_and_finish_interact (shutdown); -} - -static void -set_clone_restart_commands (void) -{ - char *restartv[10]; - char *clonev[10]; - char *discardv[10]; - int i; - SmProp prop1, prop2, prop3, *props[3]; - - /* Restart (use same client ID) */ - - prop1.name = SmRestartCommand; - prop1.type = SmLISTofARRAY8; - - g_return_if_fail (client_id); - - i = 0; - restartv[i] = "metacity"; - ++i; - restartv[i] = "--sm-client-id"; - ++i; - restartv[i] = client_id; - ++i; - restartv[i] = NULL; - - prop1.vals = g_new (SmPropValue, i); - i = 0; - while (restartv[i]) - { - prop1.vals[i].value = restartv[i]; - prop1.vals[i].length = strlen (restartv[i]); - ++i; - } - prop1.num_vals = i; - - /* Clone (no client ID) */ - - i = 0; - clonev[i] = "metacity"; - ++i; - clonev[i] = NULL; - - prop2.name = SmCloneCommand; - prop2.type = SmLISTofARRAY8; - - prop2.vals = g_new (SmPropValue, i); - i = 0; - while (clonev[i]) - { - prop2.vals[i].value = clonev[i]; - prop2.vals[i].length = strlen (clonev[i]); - ++i; - } - prop2.num_vals = i; - - /* Discard */ - - i = 0; - discardv[i] = "rm"; - ++i; - discardv[i] = "-f"; - ++i; - discardv[i] = (char*) full_save_file (); - ++i; - discardv[i] = NULL; - - prop3.name = SmDiscardCommand; - prop3.type = SmLISTofARRAY8; - - prop3.vals = g_new (SmPropValue, i); - i = 0; - while (discardv[i]) - { - prop3.vals[i].value = discardv[i]; - prop3.vals[i].length = strlen (discardv[i]); - ++i; - } - prop3.num_vals = i; - - - props[0] = &prop1; - props[1] = &prop2; - props[2] = &prop3; - - SmcSetProperties (session_connection, 3, props); - - g_free (prop1.vals); - g_free (prop2.vals); - g_free (prop3.vals); -} - -/* The remaining code in this file actually loads/saves the session, - * while the code above this comment handles chatting with the - * session manager. - */ - -static const char* -window_type_to_string (MetaWindowType type) -{ - switch (type) - { - case META_WINDOW_NORMAL: - return "normal"; - case META_WINDOW_DESKTOP: - return "desktop"; - case META_WINDOW_DOCK: - return "dock"; - case META_WINDOW_DIALOG: - return "dialog"; - case META_WINDOW_MODAL_DIALOG: - return "modal_dialog"; - case META_WINDOW_TOOLBAR: - return "toolbar"; - case META_WINDOW_MENU: - return "menu"; - case META_WINDOW_SPLASHSCREEN: - return "splashscreen"; - case META_WINDOW_UTILITY: - return "utility"; - } - - return ""; -} - -static MetaWindowType -window_type_from_string (const char *str) -{ - if (strcmp (str, "normal") == 0) - return META_WINDOW_NORMAL; - else if (strcmp (str, "desktop") == 0) - return META_WINDOW_DESKTOP; - else if (strcmp (str, "dock") == 0) - return META_WINDOW_DOCK; - else if (strcmp (str, "dialog") == 0) - return META_WINDOW_DIALOG; - else if (strcmp (str, "modal_dialog") == 0) - return META_WINDOW_MODAL_DIALOG; - else if (strcmp (str, "toolbar") == 0) - return META_WINDOW_TOOLBAR; - else if (strcmp (str, "menu") == 0) - return META_WINDOW_MENU; - else if (strcmp (str, "utility") == 0) - return META_WINDOW_UTILITY; - else if (strcmp (str, "splashscreen") == 0) - return META_WINDOW_SPLASHSCREEN; - else - return META_WINDOW_NORMAL; -} - -static int -window_gravity_from_string (const char *str) -{ - if (strcmp (str, "NorthWestGravity") == 0) - return NorthWestGravity; - else if (strcmp (str, "NorthGravity") == 0) - return NorthGravity; - else if (strcmp (str, "NorthEastGravity") == 0) - return NorthEastGravity; - else if (strcmp (str, "WestGravity") == 0) - return WestGravity; - else if (strcmp (str, "CenterGravity") == 0) - return CenterGravity; - else if (strcmp (str, "EastGravity") == 0) - return EastGravity; - else if (strcmp (str, "SouthWestGravity") == 0) - return SouthWestGravity; - else if (strcmp (str, "SouthGravity") == 0) - return SouthGravity; - else if (strcmp (str, "SouthEastGravity") == 0) - return SouthEastGravity; - else if (strcmp (str, "StaticGravity") == 0) - return StaticGravity; - else - return NorthWestGravity; -} - -static char* -encode_text_as_utf8_markup (const char *text) -{ - /* text can be any encoding, and is nul-terminated. - * we pretend it's Latin-1 and encode as UTF-8 - */ - GString *str; - const char *p; - char *escaped; - - str = g_string_new (""); - - p = text; - while (*p) - { - g_string_append_unichar (str, *p); - ++p; - } - - escaped = g_markup_escape_text (str->str, str->len); - g_string_free (str, TRUE); - - return escaped; -} - -static char* -decode_text_from_utf8 (const char *text) -{ - /* Convert back from the encoded (but not escaped) UTF-8 */ - GString *str; - const char *p; - - str = g_string_new (""); - - p = text; - while (*p) - { - /* obviously this barfs if the UTF-8 contains chars > 255 */ - g_string_append_c (str, g_utf8_get_char (p)); - - p = g_utf8_next_char (p); - } - - return g_string_free (str, FALSE); -} - -static void -save_state (void) -{ - char *metacity_dir; - char *session_dir; - FILE *outfile; - GSList *windows; - GSList *tmp; - int stack_position; - - g_assert (client_id); - - outfile = NULL; - - /* - * g_get_user_config_dir() is guaranteed to return an existing directory. - * Eventually, if SM stays with the WM, I'd like to make this - * something like <config>/window_placement in a standard format. - * Future optimisers should note also that by the time we get here - * we probably already have full_save_path figured out and therefore - * can just use the directory name from that. - */ - metacity_dir = g_strconcat (g_get_user_config_dir (), - G_DIR_SEPARATOR_S "metacity", - NULL); - - session_dir = g_strconcat (metacity_dir, - G_DIR_SEPARATOR_S "sessions", - NULL); - - if (mkdir (metacity_dir, 0700) < 0 && - errno != EEXIST) - { - meta_warning (_("Could not create directory '%s': %s\n"), - metacity_dir, g_strerror (errno)); - } - - if (mkdir (session_dir, 0700) < 0 && - errno != EEXIST) - { - meta_warning (_("Could not create directory '%s': %s\n"), - session_dir, g_strerror (errno)); - } - - meta_topic (META_DEBUG_SM, "Saving session to '%s'\n", full_save_file ()); - - outfile = fopen (full_save_file (), "w"); - - if (outfile == NULL) - { - meta_warning (_("Could not open session file '%s' for writing: %s\n"), - full_save_file (), g_strerror (errno)); - goto out; - } - - /* The file format is: - * <metacity_session id="foo"> - * <window id="bar" class="XTerm" name="xterm" title="/foo/bar" role="blah" type="normal" stacking="5"> - * <workspace index="2"/> - * <workspace index="4"/> - * <sticky/> <minimized/> <maximized/> - * <geometry x="100" y="100" width="200" height="200" gravity="northwest"/> - * </window> - * </metacity_session> - * - * Note that attributes on <window> are the match info we use to - * see if the saved state applies to a restored window, and - * child elements are the saved state to be applied. - * - */ - - fprintf (outfile, "<metacity_session id=\"%s\">\n", - client_id); - - windows = meta_display_list_windows (meta_get_display ()); - stack_position = 0; - - windows = g_slist_sort (windows, meta_display_stack_cmp); - tmp = windows; - stack_position = 0; - - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - if (window->sm_client_id) - { - char *sm_client_id; - char *res_class; - char *res_name; - char *role; - char *title; - - /* client id, class, name, role are not expected to be - * in UTF-8 (I think they are in XPCS which is Latin-1? - * in practice they are always ascii though.) - */ - - sm_client_id = encode_text_as_utf8_markup (window->sm_client_id); - res_class = window->res_class ? - encode_text_as_utf8_markup (window->res_class) : NULL; - res_name = window->res_name ? - encode_text_as_utf8_markup (window->res_name) : NULL; - role = window->role ? - encode_text_as_utf8_markup (window->role) : NULL; - if (window->title) - title = g_markup_escape_text (window->title, -1); - else - title = NULL; - - meta_topic (META_DEBUG_SM, "Saving session managed window %s, client ID '%s'\n", - window->desc, window->sm_client_id); - - fprintf (outfile, - " <window id=\"%s\" class=\"%s\" name=\"%s\" title=\"%s\" role=\"%s\" type=\"%s\" stacking=\"%d\">\n", - sm_client_id, - res_class ? res_class : "", - res_name ? res_name : "", - title ? title : "", - role ? role : "", - window_type_to_string (window->type), - stack_position); - - g_free (sm_client_id); - g_free (res_class); - g_free (res_name); - g_free (role); - g_free (title); - - /* Sticky */ - if (window->on_all_workspaces) - fputs (" <sticky/>\n", outfile); - - /* Minimized */ - if (window->minimized) - fputs (" <minimized/>\n", outfile); - - /* Maximized */ - if (META_WINDOW_MAXIMIZED (window)) - { - fprintf (outfile, - " <maximized saved_x=\"%d\" saved_y=\"%d\" saved_width=\"%d\" saved_height=\"%d\"/>\n", - window->saved_rect.x, - window->saved_rect.y, - window->saved_rect.width, - window->saved_rect.height); - } - - /* Workspaces we're on */ - { - int n; - n = meta_workspace_index (window->workspace); - fprintf (outfile, - " <workspace index=\"%d\"/>\n", n); - } - - /* Gravity */ - { - int x, y, w, h; - meta_window_get_geometry (window, &x, &y, &w, &h); - - fprintf (outfile, - " <geometry x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" gravity=\"%s\"/>\n", - x, y, w, h, - meta_gravity_to_string (window->size_hints.win_gravity)); - } - - fputs (" </window>\n", outfile); - } - else - { - meta_topic (META_DEBUG_SM, "Not saving window '%s', not session managed\n", - window->desc); - } - - tmp = tmp->next; - ++stack_position; - } - - g_slist_free (windows); - - fputs ("</metacity_session>\n", outfile); - - out: - if (outfile) - { - /* FIXME need a dialog for this */ - if (ferror (outfile)) - { - meta_warning (_("Error writing session file '%s': %s\n"), - full_save_file (), g_strerror (errno)); - } - if (fclose (outfile)) - { - meta_warning (_("Error closing session file '%s': %s\n"), - full_save_file (), g_strerror (errno)); - } - } - - g_free (metacity_dir); - g_free (session_dir); -} - -typedef enum -{ - WINDOW_TAG_NONE, - WINDOW_TAG_DESKTOP, - WINDOW_TAG_STICKY, - WINDOW_TAG_MINIMIZED, - WINDOW_TAG_MAXIMIZED, - WINDOW_TAG_GEOMETRY -} WindowTag; - -typedef struct -{ - MetaWindowSessionInfo *info; - char *previous_id; -} ParseData; - -static void session_info_free (MetaWindowSessionInfo *info); -static MetaWindowSessionInfo* session_info_new (void); - -static void start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); - -static GMarkupParser metacity_session_parser = { - start_element_handler, - end_element_handler, - text_handler, - NULL, - NULL -}; - -static GSList *window_info_list = NULL; - -static char* -load_state (const char *previous_save_file) -{ - GMarkupParseContext *context; - GError *error; - ParseData parse_data; - char *text; - gsize length; - char *session_file; - - session_file = g_strconcat (g_get_user_config_dir (), - G_DIR_SEPARATOR_S "metacity" - G_DIR_SEPARATOR_S "sessions" G_DIR_SEPARATOR_S, - previous_save_file, - NULL); - - error = NULL; - if (!g_file_get_contents (session_file, - &text, - &length, - &error)) - { - char *canonical_session_file = session_file; - - /* Maybe they were doing it the old way, with ~/.metacity */ - session_file = g_strconcat (g_get_home_dir (), - G_DIR_SEPARATOR_S ".metacity" - G_DIR_SEPARATOR_S "sessions" - G_DIR_SEPARATOR_S, - previous_save_file, - NULL); - - if (!g_file_get_contents (session_file, - &text, - &length, - NULL)) - { - /* oh, just give up */ - - meta_warning (_("Failed to read saved session file %s: %s\n"), - canonical_session_file, error->message); - g_error_free (error); - g_free (session_file); - g_free (canonical_session_file); - return NULL; - } - - g_free (canonical_session_file); - } - - meta_topic (META_DEBUG_SM, "Parsing saved session file %s\n", session_file); - g_free (session_file); - session_file = NULL; - - parse_data.info = NULL; - parse_data.previous_id = NULL; - - context = g_markup_parse_context_new (&metacity_session_parser, - 0, &parse_data, NULL); - - error = NULL; - if (!g_markup_parse_context_parse (context, - text, - length, - &error)) - goto error; - - - error = NULL; - if (!g_markup_parse_context_end_parse (context, &error)) - goto error; - - g_markup_parse_context_free (context); - - goto out; - - error: - - meta_warning (_("Failed to parse saved session file: %s\n"), - error->message); - g_error_free (error); - - if (parse_data.info) - session_info_free (parse_data.info); - - g_free (parse_data.previous_id); - parse_data.previous_id = NULL; - - out: - - g_free (text); - - return parse_data.previous_id; -} - -/* FIXME this isn't very robust against bogus session files */ -static void -start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ParseData *pd; - - pd = user_data; - - if (strcmp (element_name, "metacity_session") == 0) - { - /* Get previous ID */ - int i; - - i = 0; - while (attribute_names[i]) - { - const char *name; - const char *val; - - name = attribute_names[i]; - val = attribute_values[i]; - - if (pd->previous_id) - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("<metacity_session> attribute seen but we already have the session ID")); - return; - } - - if (strcmp (name, "id") == 0) - { - pd->previous_id = decode_text_from_utf8 (val); - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - _("Unknown attribute %s on <%s> element"), - name, "metacity_session"); - return; - } - - ++i; - } - } - else if (strcmp (element_name, "window") == 0) - { - int i; - - if (pd->info) - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("nested <window> tag")); - return; - } - - pd->info = session_info_new (); - - i = 0; - while (attribute_names[i]) - { - const char *name; - const char *val; - - name = attribute_names[i]; - val = attribute_values[i]; - - if (strcmp (name, "id") == 0) - { - if (*val) - pd->info->id = decode_text_from_utf8 (val); - } - else if (strcmp (name, "class") == 0) - { - if (*val) - pd->info->res_class = decode_text_from_utf8 (val); - } - else if (strcmp (name, "name") == 0) - { - if (*val) - pd->info->res_name = decode_text_from_utf8 (val); - } - else if (strcmp (name, "title") == 0) - { - if (*val) - pd->info->title = g_strdup (val); - } - else if (strcmp (name, "role") == 0) - { - if (*val) - pd->info->role = decode_text_from_utf8 (val); - } - else if (strcmp (name, "type") == 0) - { - if (*val) - pd->info->type = window_type_from_string (val); - } - else if (strcmp (name, "stacking") == 0) - { - if (*val) - { - pd->info->stack_position = atoi (val); - pd->info->stack_position_set = TRUE; - } - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - _("Unknown attribute %s on <%s> element"), - name, "window"); - session_info_free (pd->info); - pd->info = NULL; - return; - } - - ++i; - } - } - else if (strcmp (element_name, "workspace") == 0) - { - int i; - - i = 0; - while (attribute_names[i]) - { - const char *name; - - name = attribute_names[i]; - - if (strcmp (name, "index") == 0) - { - pd->info->workspace_indices = - g_slist_prepend (pd->info->workspace_indices, - GINT_TO_POINTER (atoi (attribute_values[i]))); - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - _("Unknown attribute %s on <%s> element"), - name, "window"); - session_info_free (pd->info); - pd->info = NULL; - return; - } - - ++i; - } - } - else if (strcmp (element_name, "sticky") == 0) - { - pd->info->on_all_workspaces = TRUE; - pd->info->on_all_workspaces_set = TRUE; - } - else if (strcmp (element_name, "minimized") == 0) - { - pd->info->minimized = TRUE; - pd->info->minimized_set = TRUE; - } - else if (strcmp (element_name, "maximized") == 0) - { - int i; - - i = 0; - pd->info->maximized = TRUE; - pd->info->maximized_set = TRUE; - while (attribute_names[i]) - { - const char *name; - const char *val; - - name = attribute_names[i]; - val = attribute_values[i]; - - if (strcmp (name, "saved_x") == 0) - { - if (*val) - { - pd->info->saved_rect.x = atoi (val); - pd->info->saved_rect_set = TRUE; - } - } - else if (strcmp (name, "saved_y") == 0) - { - if (*val) - { - pd->info->saved_rect.y = atoi (val); - pd->info->saved_rect_set = TRUE; - } - } - else if (strcmp (name, "saved_width") == 0) - { - if (*val) - { - pd->info->saved_rect.width = atoi (val); - pd->info->saved_rect_set = TRUE; - } - } - else if (strcmp (name, "saved_height") == 0) - { - if (*val) - { - pd->info->saved_rect.height = atoi (val); - pd->info->saved_rect_set = TRUE; - } - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - _("Unknown attribute %s on <%s> element"), - name, "maximized"); - return; - } - - ++i; - } - - if (pd->info->saved_rect_set) - meta_topic (META_DEBUG_SM, "Saved unmaximized size %d,%d %dx%d \n", - pd->info->saved_rect.x, - pd->info->saved_rect.y, - pd->info->saved_rect.width, - pd->info->saved_rect.height); - } - else if (strcmp (element_name, "geometry") == 0) - { - int i; - - pd->info->geometry_set = TRUE; - - i = 0; - while (attribute_names[i]) - { - const char *name; - const char *val; - - name = attribute_names[i]; - val = attribute_values[i]; - - if (strcmp (name, "x") == 0) - { - if (*val) - pd->info->rect.x = atoi (val); - } - else if (strcmp (name, "y") == 0) - { - if (*val) - pd->info->rect.y = atoi (val); - } - else if (strcmp (name, "width") == 0) - { - if (*val) - pd->info->rect.width = atoi (val); - } - else if (strcmp (name, "height") == 0) - { - if (*val) - pd->info->rect.height = atoi (val); - } - else if (strcmp (name, "gravity") == 0) - { - if (*val) - pd->info->gravity = window_gravity_from_string (val); - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - _("Unknown attribute %s on <%s> element"), - name, "geometry"); - return; - } - - ++i; - } - - meta_topic (META_DEBUG_SM, "Loaded geometry %d,%d %dx%d gravity %s\n", - pd->info->rect.x, - pd->info->rect.y, - pd->info->rect.width, - pd->info->rect.height, - meta_gravity_to_string (pd->info->gravity)); - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ELEMENT, - _("Unknown element %s"), - element_name); - return; - } -} - -static void -end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ParseData *pd; - - pd = user_data; - - if (strcmp (element_name, "window") == 0) - { - g_assert (pd->info); - - window_info_list = g_slist_prepend (window_info_list, - pd->info); - - meta_topic (META_DEBUG_SM, "Loaded window info from session with class: %s name: %s role: %s\n", - pd->info->res_class ? pd->info->res_class : "(none)", - pd->info->res_name ? pd->info->res_name : "(none)", - pd->info->role ? pd->info->role : "(none)"); - - pd->info = NULL; - } -} - -static void -text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - /* Right now we don't have any elements where we care about their - * content - */ -} - -static gboolean -both_null_or_matching (const char *a, - const char *b) -{ - if (a == NULL && b == NULL) - return TRUE; - else if (a && b && strcmp (a, b) == 0) - return TRUE; - else - return FALSE; -} - -static GSList* -get_possible_matches (MetaWindow *window) -{ - /* Get all windows with this client ID */ - GSList *retval; - GSList *tmp; - gboolean ignore_client_id; - - retval = NULL; - - ignore_client_id = g_getenv ("METACITY_DEBUG_SM") != NULL; - - tmp = window_info_list; - while (tmp != NULL) - { - MetaWindowSessionInfo *info; - - info = tmp->data; - - if ((ignore_client_id || - both_null_or_matching (info->id, window->sm_client_id)) && - both_null_or_matching (info->res_class, window->res_class) && - both_null_or_matching (info->res_name, window->res_name) && - both_null_or_matching (info->role, window->role)) - { - meta_topic (META_DEBUG_SM, "Window %s may match saved window with class: %s name: %s role: %s\n", - window->desc, - info->res_class ? info->res_class : "(none)", - info->res_name ? info->res_name : "(none)", - info->role ? info->role : "(none)"); - - retval = g_slist_prepend (retval, info); - } - else - { - if (meta_is_verbose ()) - { - if (!both_null_or_matching (info->id, window->sm_client_id)) - meta_topic (META_DEBUG_SM, "Window %s has SM client ID %s, saved state has %s, no match\n", - window->desc, - window->sm_client_id ? window->sm_client_id : "(none)", - info->id ? info->id : "(none)"); - else if (!both_null_or_matching (info->res_class, window->res_class)) - meta_topic (META_DEBUG_SM, "Window %s has class %s doesn't match saved class %s, no match\n", - window->desc, - window->res_class ? window->res_class : "(none)", - info->res_class ? info->res_class : "(none)"); - - else if (!both_null_or_matching (info->res_name, window->res_name)) - meta_topic (META_DEBUG_SM, "Window %s has name %s doesn't match saved name %s, no match\n", - window->desc, - window->res_name ? window->res_name : "(none)", - info->res_name ? info->res_name : "(none)"); - else if (!both_null_or_matching (info->role, window->role)) - meta_topic (META_DEBUG_SM, "Window %s has role %s doesn't match saved role %s, no match\n", - window->desc, - window->role ? window->role : "(none)", - info->role ? info->role : "(none)"); - else - meta_topic (META_DEBUG_SM, "???? should not happen - window %s doesn't match saved state %s for no good reason\n", - window->desc, info->id); - } - } - - tmp = tmp->next; - } - - return retval; -} - -static const MetaWindowSessionInfo* -find_best_match (GSList *infos, - MetaWindow *window) -{ - GSList *tmp; - const MetaWindowSessionInfo *matching_title; - const MetaWindowSessionInfo *matching_type; - - matching_title = NULL; - matching_type = NULL; - - tmp = infos; - while (tmp != NULL) - { - MetaWindowSessionInfo *info; - - info = tmp->data; - - if (matching_title == NULL && - both_null_or_matching (info->title, window->title)) - matching_title = info; - - if (matching_type == NULL && - info->type == window->type) - matching_type = info; - - tmp = tmp->next; - } - - /* Prefer same title, then same type of window, then - * just pick something. Eventually we could enhance this - * to e.g. break ties by geometry hint similarity, - * or other window features. - */ - - if (matching_title) - return matching_title; - else if (matching_type) - return matching_type; - else - return infos->data; -} - -const MetaWindowSessionInfo* -meta_window_lookup_saved_state (MetaWindow *window) -{ - GSList *possibles; - const MetaWindowSessionInfo *info; - - /* Window is not session managed. - * I haven't yet figured out how to deal with these - * in a way that doesn't cause broken side effects in - * situations other than on session restore. - */ - if (window->sm_client_id == NULL) - { - meta_topic (META_DEBUG_SM, - "Window %s is not session managed, not checking for saved state\n", - window->desc); - return NULL; - } - - possibles = get_possible_matches (window); - - if (possibles == NULL) - { - meta_topic (META_DEBUG_SM, "Window %s has no possible matches in the list of saved window states\n", - window->desc); - return NULL; - } - - info = find_best_match (possibles, window); - - g_slist_free (possibles); - - return info; -} - -void -meta_window_release_saved_state (const MetaWindowSessionInfo *info) -{ - /* We don't want to use the same saved state again for another - * window. - */ - window_info_list = g_slist_remove (window_info_list, info); - - session_info_free ((MetaWindowSessionInfo*) info); -} - -static void -session_info_free (MetaWindowSessionInfo *info) -{ - g_free (info->id); - g_free (info->res_class); - g_free (info->res_name); - g_free (info->title); - g_free (info->role); - - g_slist_free (info->workspace_indices); - - g_free (info); -} - -static MetaWindowSessionInfo* -session_info_new (void) -{ - MetaWindowSessionInfo *info; - - info = g_new0 (MetaWindowSessionInfo, 1); - - info->type = META_WINDOW_NORMAL; - info->gravity = NorthWestGravity; - - return info; -} - -static char* full_save_path = NULL; - -static void -regenerate_save_file (void) -{ - g_free (full_save_path); - - if (client_id) - full_save_path = g_strconcat (g_get_user_config_dir (), - G_DIR_SEPARATOR_S "metacity" - G_DIR_SEPARATOR_S "sessions" G_DIR_SEPARATOR_S, - client_id, - ".ms", - NULL); - else - full_save_path = NULL; -} - -static const char* -full_save_file (void) -{ - return full_save_path; -} - -static int -windows_cmp_by_title (MetaWindow *a, - MetaWindow *b) -{ - return g_utf8_collate (a->title, b->title); -} - -typedef struct -{ - int child_pid; - int child_pipe; - gboolean shutdown; -} LameClientsDialogData; - -static void -finish_interact (gboolean shutdown) -{ - if (current_state == STATE_DONE_WITH_INTERACT) /* paranoia */ - { - SmcInteractDone (session_connection, False /* don't cancel logout */); - - save_yourself_possibly_done (shutdown, TRUE); - } -} - -static gboolean -io_from_warning_dialog (GIOChannel *channel, - GIOCondition condition, - gpointer data) -{ - LameClientsDialogData *d; - - d = data; - - meta_topic (META_DEBUG_PING, - "IO handler from lame clients dialog, condition = %x\n", - condition); - - if (condition & (G_IO_HUP | G_IO_NVAL | G_IO_ERR)) - { - finish_interact (d->shutdown); - - /* Remove the callback, freeing data */ - return FALSE; - } - else if (condition & G_IO_IN) - { - /* Check for EOF */ - - char buf[16]; - int ret; - - ret = read (d->child_pipe, buf, sizeof (buf)); - if (ret == 0) - { - finish_interact (d->shutdown); - return FALSE; - } - } - - /* Keep callback installed */ - return TRUE; -} - -static void -warn_about_lame_clients_and_finish_interact (gboolean shutdown) -{ - GSList *lame; - GSList *windows; - char **argv; - int i; - GSList *tmp; - int len; - int child_pid; - int child_pipe; - GError *err; - GIOChannel *channel; - LameClientsDialogData *d; - guint32 timestamp; - char timestampbuf[32]; - - lame = NULL; - windows = meta_display_list_windows (meta_get_display ()); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - /* only complain about normal windows, the others - * are kind of dumb to worry about - */ - if (window->sm_client_id == NULL && - window->type == META_WINDOW_NORMAL) - lame = g_slist_prepend (lame, window); - - tmp = tmp->next; - } - - g_slist_free (windows); - - if (lame == NULL) - { - /* No lame apps. */ - finish_interact (shutdown); - return; - } - - lame = g_slist_sort (lame, (GCompareFunc) windows_cmp_by_title); - - timestamp = meta_display_get_current_time_roundtrip (meta_get_display ()); - sprintf (timestampbuf, "%u", timestamp); - - len = g_slist_length (lame); - len *= 2; /* titles and also classes */ - len += 2; /* --timestamp flag and actual timestamp */ - len += 1; /* NULL term */ - len += 2; /* metacity-dialog command and option */ - - argv = g_new0 (char*, len); - - i = 0; - - argv[i] = METACITY_LIBEXECDIR"/metacity-dialog"; - ++i; - argv[i] = "--timestamp"; - ++i; - argv[i] = timestampbuf; - ++i; - argv[i] = "--warn-about-no-sm-support"; - ++i; - - tmp = lame; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - argv[i] = w->title; - ++i; - argv[i] = w->res_class ? w->res_class : ""; - ++i; - - tmp = tmp->next; - } - - child_pipe = -1; - child_pid = -1; - err = NULL; - if (!g_spawn_async_with_pipes ("/", - argv, - NULL, - 0, - NULL, NULL, - &child_pid, - NULL, - &child_pipe, - NULL, - &err)) - { - meta_warning (_("Error launching metacity-dialog to warn about apps that don't support session management: %s\n"), - err->message); - g_error_free (err); - } - - g_free (argv); - g_slist_free (lame); - - d = g_new0 (LameClientsDialogData, 1); - d->child_pipe = child_pipe; - d->child_pid = child_pid; - d->shutdown = shutdown; - - channel = g_io_channel_unix_new (d->child_pipe); - g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - io_from_warning_dialog, - d, g_free); - g_io_channel_unref (channel); -} - -#endif /* HAVE_SM */ diff --git a/src/core/session.h b/src/core/session.h deleted file mode 100644 index 62a9370d..00000000 --- a/src/core/session.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file session.h Session management - * - * Maps windows to information about their placing and state on startup. - * This is window matching, which we have a policy of leaving in general - * to programs such as Devil's Pie, but the session manager specification - * requires us to do it here. - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_SESSION_H -#define META_SESSION_H - -#include "window-private.h" - -typedef struct _MetaWindowSessionInfo MetaWindowSessionInfo; - -struct _MetaWindowSessionInfo -{ - /* Fields we use to match against */ - - char *id; - char *res_class; - char *res_name; - char *title; - char *role; - MetaWindowType type; - - /* Information we restore */ - - GSList *workspace_indices; - - int stack_position; - - /* width/height should be multiplied by resize inc and - * added to base size; position should be interpreted in - * light of gravity. This preserves semantics of the - * window size/pos, even if fonts/themes change, etc. - */ - int gravity; - MetaRectangle rect; - MetaRectangle saved_rect; - guint on_all_workspaces : 1; - guint minimized : 1; - guint maximized : 1; - - guint stack_position_set : 1; - guint geometry_set : 1; - guint on_all_workspaces_set : 1; - guint minimized_set : 1; - guint maximized_set : 1; - guint saved_rect_set : 1; -}; - -/* If lookup_saved_state returns something, it should be used, - * and then released when you're done with it. - */ -const MetaWindowSessionInfo* meta_window_lookup_saved_state (MetaWindow *window); -void meta_window_release_saved_state (const MetaWindowSessionInfo *info); - -void meta_session_init (const char *client_id, - const char *save_file); - - -void meta_session_shutdown (void); - -#endif - - - - diff --git a/src/core/stack.c b/src/core/stack.c deleted file mode 100644 index cf770bca..00000000 --- a/src/core/stack.c +++ /dev/null @@ -1,1661 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file stack.c Which windows cover which other windows - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2004 Rob Adams - * Copyright (C) 2004, 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "stack.h" -#include "window-private.h" -#include "errors.h" -#include "frame-private.h" -#include "group.h" -#include "prefs.h" -#include "workspace.h" - -#include <X11/Xatom.h> - -#define WINDOW_HAS_TRANSIENT_TYPE(w) \ - (w->type == META_WINDOW_DIALOG || \ - w->type == META_WINDOW_MODAL_DIALOG || \ - w->type == META_WINDOW_TOOLBAR || \ - w->type == META_WINDOW_MENU || \ - w->type == META_WINDOW_UTILITY) - -#define WINDOW_TRANSIENT_FOR_WHOLE_GROUP(w) \ - ((w->xtransient_for == None || \ - w->transient_parent_is_root_window) && \ - WINDOW_HAS_TRANSIENT_TYPE (w)) - -#define WINDOW_IN_STACK(w) (w->stack_position >= 0) - -static void stack_sync_to_server (MetaStack *stack); -static void meta_window_set_stack_position_no_sync (MetaWindow *window, - int position); -static void stack_do_window_deletions (MetaStack *stack); -static void stack_do_window_additions (MetaStack *stack); -static void stack_do_relayer (MetaStack *stack); -static void stack_do_constrain (MetaStack *stack); -static void stack_do_resort (MetaStack *stack); - -static void stack_ensure_sorted (MetaStack *stack); - -MetaStack* -meta_stack_new (MetaScreen *screen) -{ - MetaStack *stack; - - stack = g_new (MetaStack, 1); - - stack->screen = screen; - stack->windows = g_array_new (FALSE, FALSE, sizeof (Window)); - - stack->sorted = NULL; - stack->added = NULL; - stack->removed = NULL; - - stack->freeze_count = 0; - stack->last_root_children_stacked = NULL; - - stack->n_positions = 0; - - stack->need_resort = FALSE; - stack->need_relayer = FALSE; - stack->need_constrain = FALSE; - - return stack; -} - -void -meta_stack_free (MetaStack *stack) -{ - g_array_free (stack->windows, TRUE); - - g_list_free (stack->sorted); - g_list_free (stack->added); - g_list_free (stack->removed); - - if (stack->last_root_children_stacked) - g_array_free (stack->last_root_children_stacked, TRUE); - - g_free (stack); -} - -void -meta_stack_add (MetaStack *stack, - MetaWindow *window) -{ - meta_topic (META_DEBUG_STACK, "Adding window %s to the stack\n", window->desc); - - if (window->stack_position >= 0) - meta_bug ("Window %s had stack position already\n", window->desc); - - stack->added = g_list_prepend (stack->added, window); - - window->stack_position = stack->n_positions; - stack->n_positions += 1; - meta_topic (META_DEBUG_STACK, - "Window %s has stack_position initialized to %d\n", - window->desc, window->stack_position); - - stack_sync_to_server (stack); -} - -void -meta_stack_remove (MetaStack *stack, - MetaWindow *window) -{ - meta_topic (META_DEBUG_STACK, "Removing window %s from the stack\n", window->desc); - - if (window->stack_position < 0) - meta_bug ("Window %s removed from stack but had no stack position\n", - window->desc); - - /* Set window to top position, so removing it will not leave gaps - * in the set of positions - */ - meta_window_set_stack_position_no_sync (window, - stack->n_positions - 1); - window->stack_position = -1; - stack->n_positions -= 1; - - /* We don't know if it's been moved from "added" to "stack" yet */ - stack->added = g_list_remove (stack->added, window); - stack->sorted = g_list_remove (stack->sorted, window); - - /* Remember the window ID to remove it from the stack array. - * The macro is safe to use: Window is guaranteed to be 32 bits, and - * GUINT_TO_POINTER says it only works on 32 bits. - */ - stack->removed = g_list_prepend (stack->removed, - GUINT_TO_POINTER (window->xwindow)); - if (window->frame) - stack->removed = g_list_prepend (stack->removed, - GUINT_TO_POINTER (window->frame->xwindow)); - - stack_sync_to_server (stack); -} - -void -meta_stack_update_layer (MetaStack *stack, - MetaWindow *window) -{ - stack->need_relayer = TRUE; - - stack_sync_to_server (stack); -} - -void -meta_stack_update_transient (MetaStack *stack, - MetaWindow *window) -{ - stack->need_constrain = TRUE; - - stack_sync_to_server (stack); -} - -/* raise/lower within a layer */ -void -meta_stack_raise (MetaStack *stack, - MetaWindow *window) -{ - meta_window_set_stack_position_no_sync (window, - stack->n_positions - 1); - - stack_sync_to_server (stack); -} - -void -meta_stack_lower (MetaStack *stack, - MetaWindow *window) -{ - meta_window_set_stack_position_no_sync (window, 0); - - stack_sync_to_server (stack); -} - -void -meta_stack_freeze (MetaStack *stack) -{ - stack->freeze_count += 1; -} - -void -meta_stack_thaw (MetaStack *stack) -{ - g_return_if_fail (stack->freeze_count > 0); - - stack->freeze_count -= 1; - stack_sync_to_server (stack); -} - -static gboolean -is_focused_foreach (MetaWindow *window, - void *data) -{ - if (window == window->display->expected_focus_window) - { - *((gboolean*) data) = TRUE; - return FALSE; - } - return TRUE; -} - -static gboolean -windows_on_different_xinerama (MetaWindow *a, - MetaWindow *b) -{ - if (a->screen != b->screen) - return TRUE; - - return meta_screen_get_xinerama_for_window (a->screen, a) != - meta_screen_get_xinerama_for_window (b->screen, b); -} - -/* Get layer ignoring any transient or group relationships */ -static MetaStackLayer -get_standalone_layer (MetaWindow *window) -{ - MetaStackLayer layer; - gboolean focused_transient = FALSE; - - switch (window->type) - { - case META_WINDOW_DESKTOP: - layer = META_LAYER_DESKTOP; - break; - - case META_WINDOW_DOCK: - /* still experimenting here */ - if (window->wm_state_below) - layer = META_LAYER_BOTTOM; - else - layer = META_LAYER_DOCK; - break; - - default: - meta_window_foreach_transient (window, - is_focused_foreach, - &focused_transient); - - if (window->wm_state_below) - layer = META_LAYER_BOTTOM; - else if (window->fullscreen && - (focused_transient || - window == window->display->expected_focus_window || - window->display->expected_focus_window == NULL || - (window->display->expected_focus_window != NULL && - windows_on_different_xinerama (window, - window->display->expected_focus_window)))) - layer = META_LAYER_FULLSCREEN; - else if (window->wm_state_above) - layer = META_LAYER_TOP; - else - layer = META_LAYER_NORMAL; - break; - } - - return layer; -} - -/* Note that this function can never use window->layer only - * get_standalone_layer, or we'd have issues. - */ -static MetaStackLayer -get_maximum_layer_in_group (MetaWindow *window) -{ - GSList *members; - MetaGroup *group; - GSList *tmp; - MetaStackLayer max; - MetaStackLayer layer; - - max = META_LAYER_DESKTOP; - - group = meta_window_get_group (window); - - if (group != NULL) - members = meta_group_list_windows (group); - else - members = NULL; - - tmp = members; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - layer = get_standalone_layer (w); - if (layer > max) - max = layer; - - tmp = tmp->next; - } - - g_slist_free (members); - - return max; -} - -static void -compute_layer (MetaWindow *window) -{ - window->layer = get_standalone_layer (window); - - /* We can only do promotion-due-to-group for dialogs and other - * transients, or weird stuff happens like the desktop window and - * nautilus windows getting in the same layer, or all gnome-terminal - * windows getting in fullscreen layer if any terminal is - * fullscreen. - */ - if (WINDOW_HAS_TRANSIENT_TYPE(window) && - (window->xtransient_for == None || - window->transient_parent_is_root_window)) - { - /* We only do the group thing if the dialog is NOT transient for - * a particular window. Imagine a group with a normal window, a dock, - * and a dialog transient for the normal window; you don't want the dialog - * above the dock if it wouldn't normally be. - */ - - MetaStackLayer group_max; - - group_max = get_maximum_layer_in_group (window); - - if (group_max > window->layer) - { - meta_topic (META_DEBUG_STACK, - "Promoting window %s from layer %u to %u due to group membership\n", - window->desc, window->layer, group_max); - window->layer = group_max; - } - } - - meta_topic (META_DEBUG_STACK, "Window %s on layer %u type = %u has_focus = %d\n", - window->desc, window->layer, - window->type, window->has_focus); -} - -/* Front of the layer list is the topmost window, - * so the lower stack position is later in the list - */ -static int -compare_window_position (void *a, - void *b) -{ - MetaWindow *window_a = a; - MetaWindow *window_b = b; - - /* Go by layer, then stack_position */ - if (window_a->layer < window_b->layer) - return 1; /* move window_a later in list */ - else if (window_a->layer > window_b->layer) - return -1; - else if (window_a->stack_position < window_b->stack_position) - return 1; /* move window_a later in list */ - else if (window_a->stack_position > window_b->stack_position) - return -1; - else - return 0; /* not reached */ -} - -/* - * Stacking constraints - * - * Assume constraints of the form "AB" meaning "window A must be - * below window B" - * - * If we have windows stacked from bottom to top - * "ABC" then raise A we get "BCA". Say C is - * transient for B is transient for A. So - * we have constraints AB and BC. - * - * After raising A, we need to reapply the constraints. - * If we do this by raising one window at a time - - * - * start: BCA - * apply AB: CAB - * apply BC: ABC - * - * but apply constraints in the wrong order and it breaks: - * - * start: BCA - * apply BC: BCA - * apply AB: CAB - * - * We make a directed graph of the constraints by linking - * from "above windows" to "below windows as follows: - * - * AB -> BC -> CD - * \ - * CE - * - * If we then walk that graph and apply the constraints in the order - * that they appear, we will apply them correctly. Note that the - * graph MAY have cycles, so we have to guard against that. - * - */ - -typedef struct Constraint Constraint; - -struct Constraint -{ - MetaWindow *above; - MetaWindow *below; - - /* used to keep the constraint in the - * list of constraints for window "below" - */ - Constraint *next; - - /* used to create the graph. */ - GSList *next_nodes; - - /* constraint has been applied, used - * to detect cycles. - */ - unsigned int applied : 1; - - /* constraint has a previous node in the graph, - * used to find places to start in the graph. - * (I think this also has the side effect - * of preventing cycles, since cycles will - * have no starting point - so maybe - * the "applied" flag isn't needed.) - */ - unsigned int has_prev : 1; -}; - -/* We index the array of constraints by window - * stack positions, just because the stack - * positions are a convenient index. - */ -static void -add_constraint (Constraint **constraints, - MetaWindow *above, - MetaWindow *below) -{ - Constraint *c; - - g_assert (above->screen == below->screen); - - /* check if constraint is a duplicate */ - c = constraints[below->stack_position]; - while (c != NULL) - { - if (c->above == above) - return; - c = c->next; - } - - /* if not, add the constraint */ - c = g_new (Constraint, 1); - c->above = above; - c->below = below; - c->next = constraints[below->stack_position]; - c->next_nodes = NULL; - c->applied = FALSE; - c->has_prev = FALSE; - - constraints[below->stack_position] = c; -} - -static void -create_constraints (Constraint **constraints, - GList *windows) -{ - GList *tmp; - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (!WINDOW_IN_STACK (w)) - { - meta_topic (META_DEBUG_STACK, "Window %s not in the stack, not constraining it\n", - w->desc); - tmp = tmp->next; - continue; - } - - if (WINDOW_TRANSIENT_FOR_WHOLE_GROUP (w)) - { - GSList *group_windows; - GSList *tmp2; - MetaGroup *group; - - group = meta_window_get_group (w); - - if (group != NULL) - group_windows = meta_group_list_windows (group); - else - group_windows = NULL; - - tmp2 = group_windows; - - while (tmp2 != NULL) - { - MetaWindow *group_window = tmp2->data; - - if (!WINDOW_IN_STACK (group_window) || - w->screen != group_window->screen) - { - tmp2 = tmp2->next; - continue; - } - -#if 0 - /* old way of doing it */ - if (!(meta_window_is_ancestor_of_transient (w, group_window)) && - !WINDOW_TRANSIENT_FOR_WHOLE_GROUP (group_window)) /* note */;/*note*/ -#else - /* better way I think, so transient-for-group are constrained - * only above non-transient-type windows in their group - */ - if (!WINDOW_HAS_TRANSIENT_TYPE (group_window)) -#endif - { - meta_topic (META_DEBUG_STACK, "Constraining %s above %s as it's transient for its group\n", - w->desc, group_window->desc); - add_constraint (constraints, w, group_window); - } - - tmp2 = tmp2->next; - } - - g_slist_free (group_windows); - } - else if (w->xtransient_for != None && - !w->transient_parent_is_root_window) - { - MetaWindow *parent; - - parent = - meta_display_lookup_x_window (w->display, w->xtransient_for); - - if (parent && WINDOW_IN_STACK (parent) && - parent->screen == w->screen) - { - meta_topic (META_DEBUG_STACK, "Constraining %s above %s due to transiency\n", - w->desc, parent->desc); - add_constraint (constraints, w, parent); - } - } - - tmp = tmp->next; - } -} - -static void -graph_constraints (Constraint **constraints, - int n_constraints) -{ - int i; - - i = 0; - while (i < n_constraints) - { - Constraint *c; - - /* If we have "A below B" and "B below C" then AB -> BC so we - * add BC to next_nodes in AB. - */ - - c = constraints[i]; - while (c != NULL) - { - Constraint *n; - - g_assert (c->below->stack_position == i); - - /* Constraints where ->above is below are our - * next_nodes and we are their previous - */ - n = constraints[c->above->stack_position]; - while (n != NULL) - { - c->next_nodes = g_slist_prepend (c->next_nodes, - n); - /* c is a previous node of n */ - n->has_prev = TRUE; - - n = n->next; - } - - c = c->next; - } - - ++i; - } -} - -static void -free_constraints (Constraint **constraints, - int n_constraints) -{ - int i; - - i = 0; - while (i < n_constraints) - { - Constraint *c; - - c = constraints[i]; - while (c != NULL) - { - Constraint *next = c->next; - - g_slist_free (c->next_nodes); - - g_free (c); - - c = next; - } - - ++i; - } -} - -static void -ensure_above (MetaWindow *above, - MetaWindow *below) -{ - if (WINDOW_HAS_TRANSIENT_TYPE(above) && - above->layer < below->layer) - { - meta_topic (META_DEBUG_STACK, - "Promoting window %s from layer %u to %u due to contraint\n", - above->desc, above->layer, below->layer); - above->layer = below->layer; - } - - if (above->stack_position < below->stack_position) - { - /* move above to below->stack_position bumping below down the stack */ - meta_window_set_stack_position_no_sync (above, below->stack_position); - g_assert (below->stack_position + 1 == above->stack_position); - } - meta_topic (META_DEBUG_STACK, "%s above at %d > %s below at %d\n", - above->desc, above->stack_position, - below->desc, below->stack_position); -} - -static void -traverse_constraint (Constraint *c) -{ - GSList *tmp; - - if (c->applied) - return; - - ensure_above (c->above, c->below); - c->applied = TRUE; - - tmp = c->next_nodes; - while (tmp != NULL) - { - traverse_constraint (tmp->data); - - tmp = tmp->next; - } -} - -static void -apply_constraints (Constraint **constraints, - int n_constraints) -{ - GSList *heads; - GSList *tmp; - int i; - - /* List all heads in an ordered constraint chain */ - heads = NULL; - i = 0; - while (i < n_constraints) - { - Constraint *c; - - c = constraints[i]; - while (c != NULL) - { - if (!c->has_prev) - heads = g_slist_prepend (heads, c); - - c = c->next; - } - - ++i; - } - - /* Now traverse the chain and apply constraints */ - tmp = heads; - while (tmp != NULL) - { - Constraint *c = tmp->data; - - traverse_constraint (c); - - tmp = tmp->next; - } - - g_slist_free (heads); -} - -/** - * Go through "deleted" and take the matching windows - * out of "windows". - */ -static void -stack_do_window_deletions (MetaStack *stack) -{ - /* Do removals before adds, with paranoid idea that we might re-add - * the same window IDs. - */ - GList *tmp; - int i; - - tmp = stack->removed; - while (tmp != NULL) - { - Window xwindow; - xwindow = GPOINTER_TO_UINT (tmp->data); - - /* We go from the end figuring removals are more - * likely to be recent. - */ - i = stack->windows->len; - while (i > 0) - { - --i; - - /* there's no guarantee we'll actually find windows to - * remove, e.g. the same xwindow could have been - * added/removed before we ever synced, and we put - * both the window->xwindow and window->frame->xwindow - * in the removal list. - */ - if (xwindow == g_array_index (stack->windows, Window, i)) - { - g_array_remove_index (stack->windows, i); - goto next; - } - } - - next: - tmp = tmp->next; - } - - g_list_free (stack->removed); - stack->removed = NULL; -} - -static void -stack_do_window_additions (MetaStack *stack) -{ - GList *tmp; - gint i, n_added; - - n_added = g_list_length (stack->added); - if (n_added > 0) - { - Window *end; - int old_size; - - meta_topic (META_DEBUG_STACK, - "Adding %d windows to sorted list\n", - n_added); - - old_size = stack->windows->len; - g_array_set_size (stack->windows, old_size + n_added); - - end = &g_array_index (stack->windows, Window, old_size); - - /* stack->added has the most recent additions at the - * front of the list, so we need to reverse it - */ - stack->added = g_list_reverse (stack->added); - - i = 0; - tmp = stack->added; - while (tmp != NULL) - { - MetaWindow *w; - - w = tmp->data; - - end[i] = w->xwindow; - - /* add to the main list */ - stack->sorted = g_list_prepend (stack->sorted, w); - - ++i; - tmp = tmp->next; - } - - stack->need_resort = TRUE; /* may not be needed as we add to top */ - stack->need_constrain = TRUE; - stack->need_relayer = TRUE; - } - - g_list_free (stack->added); - stack->added = NULL; -} - -/** - * Update the layers that windows are in - */ -static void -stack_do_relayer (MetaStack *stack) -{ - GList *tmp; - - if (!stack->need_relayer) - return; - - meta_topic (META_DEBUG_STACK, - "Recomputing layers\n"); - - tmp = stack->sorted; - - while (tmp != NULL) - { - MetaWindow *w; - MetaStackLayer old_layer; - - w = tmp->data; - old_layer = w->layer; - - compute_layer (w); - - if (w->layer != old_layer) - { - meta_topic (META_DEBUG_STACK, - "Window %s moved from layer %u to %u\n", - w->desc, old_layer, w->layer); - - stack->need_resort = TRUE; - stack->need_constrain = TRUE; - /* don't need to constrain as constraining - * purely operates in terms of stack_position - * not layer - */ - } - - tmp = tmp->next; - } - - stack->need_relayer = FALSE; -} - -/** - * Update stack_position and layer to reflect transiency - * constraints - */ -static void -stack_do_constrain (MetaStack *stack) -{ - Constraint **constraints; - - /* It'd be nice if this were all faster, probably */ - - if (!stack->need_constrain) - return; - - meta_topic (META_DEBUG_STACK, - "Reapplying constraints\n"); - - constraints = g_new0 (Constraint*, - stack->n_positions); - - create_constraints (constraints, stack->sorted); - - graph_constraints (constraints, stack->n_positions); - - apply_constraints (constraints, stack->n_positions); - - free_constraints (constraints, stack->n_positions); - g_free (constraints); - - stack->need_constrain = FALSE; -} - -/** - * Sort stack->sorted with layers having priority over stack_position. - */ -static void -stack_do_resort (MetaStack *stack) -{ - if (!stack->need_resort) - return; - - meta_topic (META_DEBUG_STACK, - "Sorting stack list\n"); - - stack->sorted = g_list_sort (stack->sorted, - (GCompareFunc) compare_window_position); - - stack->need_resort = FALSE; -} - -/** - * Puts the stack into canonical form. - * - * Honour the removed and added lists of the stack, and then recalculate - * all the layers (if the flag is set), re-run all the constraint calculations - * (if the flag is set), and finally re-sort the stack (if the flag is set, - * and if it wasn't already it might have become so during all the previous - * activity). - */ -static void -stack_ensure_sorted (MetaStack *stack) -{ - stack_do_window_deletions (stack); - stack_do_window_additions (stack); - stack_do_relayer (stack); - stack_do_constrain (stack); - stack_do_resort (stack); -} - -/** - * This function is used to avoid raising a window above popup - * menus and other such things. - * - * FIXME This is sort of an expensive function, should probably - * do something to avoid it. One approach would be to reverse - * the stacking algorithm to work by placing each window above - * the others, and start by lowering a window to the bottom - * (instead of the current way, which works by placing each - * window below another and starting with a raise) - */ -static void -raise_window_relative_to_managed_windows (MetaScreen *screen, - Window xwindow) -{ - - Window ignored1, ignored2; - Window *children; - unsigned int n_children; - int i; - - /* Normally XQueryTree() means "must grab server" but here - * we don't, since we know we won't manage any new windows - * or restack any windows before using the XQueryTree results. - */ - - meta_error_trap_push_with_return (screen->display); - - XQueryTree (screen->display->xdisplay, - screen->xroot, - &ignored1, &ignored2, &children, &n_children); - - if (meta_error_trap_pop_with_return (screen->display, TRUE) != Success) - { - meta_topic (META_DEBUG_STACK, - "Error querying root children to raise window 0x%lx\n", - xwindow); - return; - } - - /* Children are in order from bottom to top. We want to - * find the topmost managed child, then configure - * our window to be above it. - */ - i = n_children - 1; - while (i >= 0) - { - if (children[i] == xwindow) - { - /* Do nothing. This means we're already the topmost managed - * window, but it DOES NOT mean we are already just above - * the topmost managed window. This is important because if - * an override redirect window is up, and we map a new - * managed window, the new window is probably above the old - * popup by default, and we want to push it below that - * popup. So keep looking for a sibling managed window - * to be moved below. - */ - } - else if (meta_display_lookup_x_window (screen->display, - children[i]) != NULL) - { - XWindowChanges changes; - - /* children[i] is the topmost managed child */ - meta_topic (META_DEBUG_STACK, - "Moving 0x%lx above topmost managed child window 0x%lx\n", - xwindow, children[i]); - - changes.sibling = children[i]; - changes.stack_mode = Above; - - meta_error_trap_push (screen->display); - XConfigureWindow (screen->display->xdisplay, - xwindow, - CWSibling | CWStackMode, - &changes); - meta_error_trap_pop (screen->display, FALSE); - - break; - } - - --i; - } - - if (i < 0) - { - /* No sibling to use, just lower ourselves to the bottom - * to be sure we're below any override redirect windows. - */ - meta_error_trap_push (screen->display); - XLowerWindow (screen->display->xdisplay, - xwindow); - meta_error_trap_pop (screen->display, FALSE); - } - - if (children) - XFree (children); -} - -/** - * Order the windows on the X server to be the same as in our structure. - * We do this using XRestackWindows if we don't know the previous order, - * or XConfigureWindow on a few particular windows if we do and can figure - * out the minimum set of changes. After that, we set __NET_CLIENT_LIST - * and __NET_CLIENT_LIST_STACKING. - */ -static void -stack_sync_to_server (MetaStack *stack) -{ - GArray *stacked; - GArray *root_children_stacked; - GList *tmp; - - /* Bail out if frozen */ - if (stack->freeze_count > 0) - return; - - meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n"); - - stack_ensure_sorted (stack); - - /* Create stacked xwindow arrays. - * Painfully, "stacked" is in bottom-to-top order for the - * _NET hints, and "root_children_stacked" is in top-to-bottom - * order for XRestackWindows() - */ - stacked = g_array_new (FALSE, FALSE, sizeof (Window)); - root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window)); - - meta_topic (META_DEBUG_STACK, "Top to bottom: "); - meta_push_no_msg_prefix (); - - tmp = stack->sorted; - while (tmp != NULL) - { - MetaWindow *w; - - w = tmp->data; - - /* remember, stacked is in reverse order (bottom to top) */ - g_array_prepend_val (stacked, w->xwindow); - - /* build XRestackWindows() array from top to bottom */ - if (w->frame) - g_array_append_val (root_children_stacked, w->frame->xwindow); - else - g_array_append_val (root_children_stacked, w->xwindow); - - meta_topic (META_DEBUG_STACK, "%u:%d - %s ", w->layer, w->stack_position, w->desc); - - tmp = tmp->next; - } - - meta_topic (META_DEBUG_STACK, "\n"); - meta_pop_no_msg_prefix (); - - /* All windows should be in some stacking order */ - if (stacked->len != stack->windows->len) - meta_bug ("%u windows stacked, %u windows exist in stack\n", - stacked->len, stack->windows->len); - - /* Sync to server */ - - meta_topic (META_DEBUG_STACK, "Restacking %u windows\n", - root_children_stacked->len); - - meta_error_trap_push (stack->screen->display); - - if (stack->last_root_children_stacked == NULL) - { - /* Just impose our stack, we don't know the previous state. - * This involves a ton of circulate requests and may flicker. - */ - meta_topic (META_DEBUG_STACK, "Don't know last stack state, restacking everything\n"); - - if (root_children_stacked->len > 0) - XRestackWindows (stack->screen->display->xdisplay, - (Window *) root_children_stacked->data, - root_children_stacked->len); - } - else if (root_children_stacked->len > 0) - { - /* Try to do minimal window moves to get the stack in order */ - /* A point of note: these arrays include frames not client windows, - * so if a client window has changed frame since last_root_children_stacked - * was saved, then we may have inefficiency, but I don't think things - * break... - */ - const Window *old_stack = (Window *) stack->last_root_children_stacked->data; - const Window *new_stack = (Window *) root_children_stacked->data; - const int old_len = stack->last_root_children_stacked->len; - const int new_len = root_children_stacked->len; - const Window *oldp = old_stack; - const Window *newp = new_stack; - const Window *old_end = old_stack + old_len; - const Window *new_end = new_stack + new_len; - Window last_window = None; - - while (oldp != old_end && - newp != new_end) - { - if (*oldp == *newp) - { - /* Stacks are the same here, move on */ - ++oldp; - last_window = *newp; - ++newp; - } - else if (meta_display_lookup_x_window (stack->screen->display, - *oldp) == NULL) - { - /* *oldp is no longer known to us (probably destroyed), - * so we can just skip it - */ - ++oldp; - } - else - { - /* Move *newp below last_window */ - if (last_window == None) - { - meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n", *newp); - - raise_window_relative_to_managed_windows (stack->screen, - *newp); - } - else - { - /* This means that if last_window is dead, but not - * *newp, then we fail to restack *newp; but on - * unmanaging last_window, we'll fix it up. - */ - - XWindowChanges changes; - - changes.sibling = last_window; - changes.stack_mode = Below; - - meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n", - *newp, last_window); - - XConfigureWindow (stack->screen->display->xdisplay, - *newp, - CWSibling | CWStackMode, - &changes); - } - - last_window = *newp; - ++newp; - } - } - - if (newp != new_end) - { - /* Restack remaining windows */ - meta_topic (META_DEBUG_STACK, "Restacking remaining %d windows\n", - (int) (new_end - newp)); - /* We need to include an already-stacked window - * in the restack call, so we get in the proper position - * with respect to it. - */ - if (newp != new_stack) - --newp; - XRestackWindows (stack->screen->display->xdisplay, - (Window *) newp, new_end - newp); - } - } - - meta_error_trap_pop (stack->screen->display, FALSE); - /* on error, a window was destroyed; it should eventually - * get removed from the stacking list when we unmanage it - * and we'll fix stacking at that time. - */ - - /* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */ - - XChangeProperty (stack->screen->display->xdisplay, - stack->screen->xroot, - stack->screen->display->atom__NET_CLIENT_LIST, - XA_WINDOW, - 32, PropModeReplace, - (unsigned char *)stack->windows->data, - stack->windows->len); - XChangeProperty (stack->screen->display->xdisplay, - stack->screen->xroot, - stack->screen->display->atom__NET_CLIENT_LIST_STACKING, - XA_WINDOW, - 32, PropModeReplace, - (unsigned char *)stacked->data, - stacked->len); - - g_array_free (stacked, TRUE); - - if (stack->last_root_children_stacked) - g_array_free (stack->last_root_children_stacked, TRUE); - stack->last_root_children_stacked = root_children_stacked; - - /* That was scary... */ -} - -MetaWindow* -meta_stack_get_top (MetaStack *stack) -{ - stack_ensure_sorted (stack); - - if (stack->sorted) - return stack->sorted->data; - else - return NULL; -} - -MetaWindow* -meta_stack_get_bottom (MetaStack *stack) -{ - GList *link; - - stack_ensure_sorted (stack); - - link = g_list_last (stack->sorted); - if (link != NULL) - return link->data; - else - return NULL; -} - -MetaWindow* -meta_stack_get_above (MetaStack *stack, - MetaWindow *window, - gboolean only_within_layer) -{ - GList *link; - MetaWindow *above; - - stack_ensure_sorted (stack); - - link = g_list_find (stack->sorted, window); - if (link == NULL) - return NULL; - if (link->prev == NULL) - return NULL; - - above = link->prev->data; - - if (only_within_layer && - above->layer != window->layer) - return NULL; - else - return above; -} - -MetaWindow* -meta_stack_get_below (MetaStack *stack, - MetaWindow *window, - gboolean only_within_layer) -{ - GList *link; - MetaWindow *below; - - stack_ensure_sorted (stack); - - link = g_list_find (stack->sorted, window); - - if (link == NULL) - return NULL; - if (link->next == NULL) - return NULL; - - below = link->next->data; - - if (only_within_layer && - below->layer != window->layer) - return NULL; - else - return below; -} - -static gboolean -window_contains_point (MetaWindow *window, - int root_x, - int root_y) -{ - MetaRectangle rect; - - meta_window_get_outer_rect (window, &rect); - - return POINT_IN_RECT (root_x, root_y, rect); -} - -static MetaWindow* -get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - gboolean must_be_at_point, - int root_x, - int root_y) -{ - /* Find the topmost, focusable, mapped, window. - * not_this_one is being unfocused or going away, so exclude it. - * Also, prefer to focus transient parent of not_this_one, - * or top window in same group as not_this_one. - */ - - MetaWindow *topmost_dock; - MetaWindow *transient_parent; - MetaWindow *topmost_in_group; - MetaWindow *topmost_overall; - MetaGroup *not_this_one_group; - GList *link; - - topmost_dock = NULL; - transient_parent = NULL; - topmost_in_group = NULL; - topmost_overall = NULL; - if (not_this_one) - not_this_one_group = meta_window_get_group (not_this_one); - else - not_this_one_group = NULL; - - stack_ensure_sorted (stack); - - /* top of this layer is at the front of the list */ - link = stack->sorted; - - while (link) - { - MetaWindow *window = link->data; - - if (window && - window != not_this_one && - (window->unmaps_pending == 0) && - !window->minimized && - (window->input || window->take_focus) && - (workspace == NULL || - meta_window_located_on_workspace (window, workspace))) - { - if (topmost_dock == NULL && - window->type == META_WINDOW_DOCK) - topmost_dock = window; - - if (not_this_one != NULL) - { - if (transient_parent == NULL && - not_this_one->xtransient_for != None && - not_this_one->xtransient_for == window->xwindow && - (!must_be_at_point || - window_contains_point (window, root_x, root_y))) - transient_parent = window; - - if (topmost_in_group == NULL && - not_this_one_group != NULL && - not_this_one_group == meta_window_get_group (window) && - (!must_be_at_point || - window_contains_point (window, root_x, root_y))) - topmost_in_group = window; - } - - /* Note that DESKTOP windows can be topmost_overall so - * we prefer focusing desktop or other windows over - * focusing dock, even though docks are stacked higher. - */ - if (topmost_overall == NULL && - window->type != META_WINDOW_DOCK && - (!must_be_at_point || - window_contains_point (window, root_x, root_y))) - topmost_overall = window; - - /* We could try to bail out early here for efficiency in - * some cases, but it's just not worth the code. - */ - } - - link = link->next; - } - - if (transient_parent) - return transient_parent; - else if (topmost_in_group) - return topmost_in_group; - else if (topmost_overall) - return topmost_overall; - else - return topmost_dock; -} - -MetaWindow* -meta_stack_get_default_focus_window_at_point (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - int root_x, - int root_y) -{ - return get_default_focus_window (stack, workspace, not_this_one, - TRUE, root_x, root_y); -} - -MetaWindow* -meta_stack_get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one) -{ - return get_default_focus_window (stack, workspace, not_this_one, - FALSE, 0, 0); -} - -GList* -meta_stack_list_windows (MetaStack *stack, - MetaWorkspace *workspace) -{ - GList *workspace_windows = NULL; - GList *link; - - stack_ensure_sorted (stack); /* do adds/removes */ - - link = stack->sorted; - - while (link) - { - MetaWindow *window = link->data; - - if (window && - (workspace == NULL || meta_window_located_on_workspace (window, workspace))) - { - workspace_windows = g_list_prepend (workspace_windows, - window); - } - - link = link->next; - } - - return workspace_windows; -} - -int -meta_stack_windows_cmp (MetaStack *stack, - MetaWindow *window_a, - MetaWindow *window_b) -{ - g_return_val_if_fail (window_a->screen == window_b->screen, 0); - - /* -1 means a below b */ - - stack_ensure_sorted (stack); /* update constraints, layers */ - - if (window_a->layer < window_b->layer) - return -1; - else if (window_a->layer > window_b->layer) - return 1; - else if (window_a->stack_position < window_b->stack_position) - return -1; - else if (window_a->stack_position > window_b->stack_position) - return 1; - else - return 0; /* not reached */ -} - -static int -compare_just_window_stack_position (void *a, - void *b) -{ - MetaWindow *window_a = a; - MetaWindow *window_b = b; - - if (window_a->stack_position < window_b->stack_position) - return -1; /* move window_a earlier in list */ - else if (window_a->stack_position > window_b->stack_position) - return 1; - else - return 0; /* not reached */ -} - -GList* -meta_stack_get_positions (MetaStack *stack) -{ - GList *tmp; - - /* Make sure to handle any adds or removes */ - stack_ensure_sorted (stack); - - tmp = g_list_copy (stack->sorted); - tmp = g_list_sort (tmp, (GCompareFunc) compare_just_window_stack_position); - - return tmp; -} - -static gint -compare_pointers (gconstpointer a, - gconstpointer b) -{ - if (a > b) - return 1; - else if (a < b) - return -1; - else - return 0; -} - -static gboolean -lists_contain_same_windows (GList *a, - GList *b) -{ - GList *copy1, *copy2; - GList *tmp1, *tmp2; - - if (g_list_length (a) != g_list_length (b)) - return FALSE; - - tmp1 = copy1 = g_list_sort (g_list_copy (a), compare_pointers); - tmp2 = copy2 = g_list_sort (g_list_copy (b), compare_pointers); - - while (tmp1 && tmp1->data == tmp2->data) /* tmp2 is non-NULL if tmp1 is */ - { - tmp1 = tmp1->next; - tmp2 = tmp2->next; - } - - g_list_free (copy1); - g_list_free (copy2); - - return (tmp1 == NULL); /* tmp2 is non-NULL if tmp1 is */ -} - -void -meta_stack_set_positions (MetaStack *stack, - GList *windows) -{ - int i; - GList *tmp; - - /* Make sure any adds or removes aren't in limbo -- is this needed? */ - stack_ensure_sorted (stack); - - if (!lists_contain_same_windows (windows, stack->sorted)) - { - meta_warning ("This list of windows has somehow changed; not resetting " - "positions of the windows.\n"); - return; - } - - g_list_free (stack->sorted); - stack->sorted = g_list_copy (windows); - - stack->need_resort = TRUE; - stack->need_constrain = TRUE; - - i = 0; - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - w->stack_position = i++; - tmp = tmp->next; - } - - meta_topic (META_DEBUG_STACK, - "Reset the stack positions of (nearly) all windows\n"); - - stack_sync_to_server (stack); -} - -void -meta_window_set_stack_position_no_sync (MetaWindow *window, - int position) -{ - int low, high, delta; - GList *tmp; - - g_return_if_fail (window->screen->stack != NULL); - g_return_if_fail (window->stack_position >= 0); - g_return_if_fail (position >= 0); - g_return_if_fail (position < window->screen->stack->n_positions); - - if (position == window->stack_position) - { - meta_topic (META_DEBUG_STACK, "Window %s already has position %d\n", - window->desc, position); - return; - } - - window->screen->stack->need_resort = TRUE; - window->screen->stack->need_constrain = TRUE; - - if (position < window->stack_position) - { - low = position; - high = window->stack_position - 1; - delta = 1; - } - else - { - low = window->stack_position + 1; - high = position; - delta = -1; - } - - tmp = window->screen->stack->sorted; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->stack_position >= low && - w->stack_position <= high) - w->stack_position += delta; - - tmp = tmp->next; - } - - window->stack_position = position; - - meta_topic (META_DEBUG_STACK, - "Window %s had stack_position set to %d\n", - window->desc, window->stack_position); -} - -void -meta_window_set_stack_position (MetaWindow *window, - int position) -{ - meta_window_set_stack_position_no_sync (window, position); - stack_sync_to_server (window->screen->stack); -} diff --git a/src/core/stack.h b/src/core/stack.h deleted file mode 100644 index f9693897..00000000 --- a/src/core/stack.h +++ /dev/null @@ -1,402 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file stack.h Which windows cover which other windows - * - * There are two factors that determine window position. - * - * One is window->stack_position, which is a unique integer - * indicating how windows are ordered with respect to one - * another. The ordering here transcends layers; it isn't changed - * as the window is moved among layers. This allows us to move several - * windows from one layer to another, while preserving the relative - * order of the moved windows. Also, it allows us to restore - * the stacking order from a saved session. - * - * However when actually stacking windows on the screen, the - * layer overrides the stack_position; windows are first sorted - * by layer, then by stack_position within each layer. - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_STACK_H -#define META_STACK_H - -#include "screen-private.h" - -/** - * Layers a window can be in. - * These MUST be in the order of stacking. - */ -typedef enum -{ - META_LAYER_DESKTOP = 0, - META_LAYER_BOTTOM = 1, - META_LAYER_NORMAL = 2, - META_LAYER_TOP = 4, /* Same as DOCK; see EWMH and bug 330717 */ - META_LAYER_DOCK = 4, - META_LAYER_FULLSCREEN = 5, - META_LAYER_FOCUSED_WINDOW = 6, - META_LAYER_LAST = 7 -} MetaStackLayer; - -/** - * A sorted list of windows bearing some level of resemblance to the stack of - * windows on the X server. - * - * (This is only used as a field within a MetaScreen; we treat it as a separate - * class for simplicity.) - */ -struct _MetaStack -{ - /** The MetaScreen containing this stack. */ - MetaScreen *screen; - - /** - * A sequence of all the Windows (X handles, not MetaWindows) of the windows - * we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST. - */ - GArray *windows; - - /** The MetaWindows of the windows we manage, sorted in order. */ - GList *sorted; - - /** - * MetaWindows waiting to be added to the "sorted" and "windows" list, after - * being added by meta_stack_add() and before being assimilated by - * stack_ensure_sorted(). - * - * The order of the elements in this list is not important; what is important - * is the stack_position element of each window. - */ - GList *added; - - /** - * Windows (X handles, not MetaWindows) waiting to be removed from the - * "windows" list, after being removed by meta_stack_remove() and before - * being assimilated by stack_ensure_sorted(). (We already removed them - * from the "sorted" list.) - * - * The order of the elements in this list is not important. - */ - GList *removed; - - /** - * If this is zero, the local stack oughtn't to be brought up to date with - * the X server's stack, because it is in the middle of being updated. - * If it is positive, the local stack is said to be "frozen", and will need - * to be thawed that many times before the stack can be brought up to date - * again. You may freeze the stack with meta_stack_freeze() and thaw it - * with meta_stack_thaw(). - */ - int freeze_count; - - /** - * The last-known stack of all windows, bottom to top. We cache it here - * so that subsequent times we'll be able to do incremental moves. - */ - GArray *last_root_children_stacked; - - /** - * Number of stack positions; same as the length of added, but - * kept for quick reference. - */ - gint n_positions; - - /** Is the stack in need of re-sorting? */ - unsigned int need_resort : 1; - - /** - * Are the windows in the stack in need of having their - * layers recalculated? - */ - unsigned int need_relayer : 1; - - /** - * Are the windows in the stack in need of having their positions - * recalculated with respect to transiency (parent and child windows)? - */ - unsigned int need_constrain : 1; -}; - -/** - * Creates and initialises a MetaStack. - * - * \param screen The MetaScreen which will be the parent of this stack. - * \return The new screen. - */ -MetaStack *meta_stack_new (MetaScreen *screen); - -/** - * Destroys and frees a MetaStack. - * - * \param stack The stack to destroy. - */ -void meta_stack_free (MetaStack *stack); - -/** - * Adds a window to the local stack. It is a fatal error to call this - * function on a window which already exists on the stack of any screen. - * - * \param window The window to add - * \param stack The stack to add it to - */ -void meta_stack_add (MetaStack *stack, - MetaWindow *window); - -/** - * Removes a window from the local stack. It is a fatal error to call this - * function on a window which exists on the stack of any screen. - * - * \param window The window to remove - * \param stack The stack to remove it from - */ -void meta_stack_remove (MetaStack *stack, - MetaWindow *window); -/** - * Recalculates the correct layer for all windows in the stack, - * and moves them about accordingly. - * - * \param window Dummy parameter - * \param stack The stack to recalculate - * \bug What's with the dummy parameter? - */ -void meta_stack_update_layer (MetaStack *stack, - MetaWindow *window); - -/** - * Recalculates the correct stacking order for all windows in the stack - * according to their transience, and moves them about accordingly. - * - * \param window Dummy parameter - * \param stack The stack to recalculate - * \bug What's with the dummy parameter? - */ -void meta_stack_update_transient (MetaStack *stack, - MetaWindow *window); - -/** - * Move a window to the top of its layer. - * - * \param stack The stack to modify. - * \param window The window that's making an ascension. - * (Amulet of Yendor not required.) - */ -void meta_stack_raise (MetaStack *stack, - MetaWindow *window); -/** - * Move a window to the bottom of its layer. - * - * \param stack The stack to modify. - * \param window The window that's on the way downwards. - */ -void meta_stack_lower (MetaStack *stack, - MetaWindow *window); - -/** - * Prevent syncing to server until the next call of meta_stack_thaw(), - * so that we can carry out multiple operations in one go without having - * everything halfway reflected on the X server. - * - * (Calls to meta_stack_freeze() nest, so that multiple calls to - * meta_stack_freeze will require multiple calls to meta_stack_thaw().) - * - * \param stack The stack to freeze. - */ -void meta_stack_freeze (MetaStack *stack); - -/** - * Undoes a meta_stack_freeze(), and processes anything which has become - * necessary during the freeze. It is an error to call this function if - * the stack has not been frozen. - * - * \param stack The stack to thaw. - */ -void meta_stack_thaw (MetaStack *stack); - -/** - * Finds the top window on the stack. - * - * \param stack The stack to examine. - * \return The top window on the stack, or NULL in the vanishingly unlikely - * event that you have no windows on your screen whatsoever. - */ -MetaWindow* meta_stack_get_top (MetaStack *stack); - -/** - * Finds the window at the bottom of the stack. Since that's pretty much - * always the desktop, this isn't the most useful of functions, and nobody - * actually calls it. We should probably get rid of it. - * - * \param stack The stack to search - */ -MetaWindow* meta_stack_get_bottom (MetaStack *stack); - -/** - * Finds the window above a given window in the stack. - * It is not an error to pass in a window which does not exist in - * the stack; the function will merely return NULL. - * - * \param stack The stack to search. - * \param window The window to look above. - * \param only_within_layer If true, will return NULL if "window" is the - * top window in its layer. - * \return NULL if there is no such window; - * the window above "window" otherwise. - */ -MetaWindow* meta_stack_get_above (MetaStack *stack, - MetaWindow *window, - gboolean only_within_layer); - -/** - * Finds the window below a given window in the stack. - * It is not an error to pass in a window which does not exist in - * the stack; the function will merely return NULL. - * - * \param stack The stack to search. - * \param window The window to look below. - * \param only_within_layer If true, will return NULL if "window" is the - * bottom window in its layer. - * \return NULL if there is no such window; - * the window below "window" otherwise. - */ -MetaWindow* meta_stack_get_below (MetaStack *stack, - MetaWindow *window, - gboolean only_within_layer); - -/** - * Find the topmost, focusable, mapped, window in a stack. If you supply - * a window as "not_this_one", we won't return that one (presumably - * because it's going to be going away). But if you do supply "not_this_one" - * and we find its parent, we'll return that; and if "not_this_one" is in - * a group, we'll return the top window of that group. - * - * Also, we are prejudiced against dock windows. Every kind of window, even - * the desktop, will be returned in preference to a dock window. - * - * \param stack The stack to search. - * \param workspace NULL to search all workspaces; otherwise only windows - * from that workspace will be returned. - * \param not_this_one Window to ignore because it's being unfocussed or - * going away. - * \return The window matching all these constraints or NULL if none does. - * - * \bug Never called! - */ -MetaWindow* meta_stack_get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one); - -/** - * Find the topmost, focusable, mapped, window in a stack. If you supply - * a window as "not_this_one", we won't return that one (presumably - * because it's going to be going away). But if you do supply "not_this_one" - * and we find its parent, we'll return that; and if "not_this_one" is in - * a group, we'll return the top window of that group. - * - * Also, we are prejudiced against dock windows. Every kind of window, even - * the desktop, will be returned in preference to a dock window. - * - * \param stack The stack to search. - * \param workspace NULL to search all workspaces; otherwise only windows - * from that workspace will be returned. - * \param not_this_one Window to ignore because it's being unfocussed or - * going away. - * \param root_x The returned window must contain this point, - * unless it's a dock. - * \param root_y See root_x. - * \return The window matching all these constraints or NULL if none does. - */ -MetaWindow* meta_stack_get_default_focus_window_at_point (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - int root_x, - int root_y); - -/** - * Finds all the windows in the stack, in order. - * - * \param stack The stack to examine. - * \param workspace If non-NULL, only windows on this workspace will be - * returned; otherwise all windows in the stack will be - * returned. - * \return A list of windows, in stacking order, honouring layers. - */ -GList* meta_stack_list_windows (MetaStack *stack, - MetaWorkspace *workspace); - -/** - * Comparison function for windows within a stack. This is not directly - * suitable for use within a standard comparison routine, because it takes - * an extra parameter; you will need to wrap it. - * - * (FIXME: We could remove the stack parameter and use the stack of - * the screen of window A, and complain if the stack of the screen of - * window B differed; then this would be a usable general comparison function.) - * - * (FIXME: Apparently identical to compare_window_position(). Merge them.) - * - * \param stack A stack containing both window_a and window_b - * \param window_a A window - * \param window_b Another window - * \return -1 if window_a is below window_b, honouring layers; 1 if it's - * above it; 0 if you passed in the same window twice! - */ -int meta_stack_windows_cmp (MetaStack *stack, - MetaWindow *window_a, - MetaWindow *window_b); - -/** - * Sets the position of a window within the stack. This will only move it - * up or down within its layer. It is an error to attempt to move this - * below position zero or above the last position in the stack (however, since - * we don't provide a simple way to tell the number of windows in the stack, - * this requirement may not be easy to fulfil). - * - * \param window The window which is moving. - * \param position Where it should move to (0 is the bottom). - */ -void meta_window_set_stack_position (MetaWindow *window, - int position); - -/** - * Returns the current stack state, allowing rudimentary transactions. - * - * \param stack The stack to examine. - * \return An opaque GList representing the current stack sort order; - * it is the caller's responsibility to free it. - * Pass this to meta_stack_set_positions() later if you want to restore - * the state to where it was when you called this function. - */ -GList* meta_stack_get_positions (MetaStack *stack); - -/** - * Rolls back a transaction, given the list returned from - * meta_stack_get_positions(). - * - * \param stack The stack to roll back. - * \param windows The list returned from meta_stack_get_positions(). - */ -void meta_stack_set_positions (MetaStack *stack, - GList *windows); - -#endif diff --git a/src/core/testasyncgetprop.c b/src/core/testasyncgetprop.c deleted file mode 100644 index 03182680..00000000 --- a/src/core/testasyncgetprop.c +++ /dev/null @@ -1,497 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation. - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of The Open Group shall not be - * used in advertising or otherwise to promote the sale, use or other dealings - * in this Software without prior written authorization from The Open Group. - */ - -#include "async-getprop.h" - -#include <time.h> -#include <sys/time.h> -#include <sys/types.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <signal.h> -#include <assert.h> - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef NULL -#define NULL ((void*) 0) -#endif - -#ifdef HAVE_BACKTRACE -#include <execinfo.h> -static void -print_backtrace (void) -{ - void *bt[500]; - int bt_size; - int i; - char **syms; - - bt_size = backtrace (bt, 500); - - syms = backtrace_symbols (bt, bt_size); - - i = 0; - while (i < bt_size) - { - fprintf (stderr, " %s\n", syms[i]); - ++i; - } - - free (syms); -} -#else -static void -print_backtrace (void) -{ - fprintf (stderr, "Not compiled with backtrace support\n"); -} -#endif - -static int error_trap_depth = 0; - -static int -x_error_handler (Display *xdisplay, - XErrorEvent *error) -{ - char buf[64]; - - XGetErrorText (xdisplay, error->error_code, buf, 63); - - if (error_trap_depth == 0) - { - print_backtrace (); - - fprintf (stderr, "Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n", - buf, - error->serial, - error->error_code, - error->request_code, - error->minor_code); - - exit (1); - } - - return 1; /* return value is meaningless */ -} - -static void -error_trap_push (Display *xdisplay) -{ - ++error_trap_depth; -} - -static void -error_trap_pop (Display *xdisplay) -{ - if (error_trap_depth == 0) - { - fprintf (stderr, "Error trap underflow!\n"); - exit (1); - } - - XSync (xdisplay, False); /* get all errors out of the queue */ - --error_trap_depth; -} - -static char* -my_strdup (const char *str) -{ - char *s; - - s = malloc (strlen (str) + 1); - if (s == NULL) - { - fprintf (stderr, "malloc failed\n"); - exit (1); - } - strcpy (s, str); - - return s; -} - -static char* -atom_name (Display *display, - Atom atom) -{ - if (atom == None) - { - return my_strdup ("None"); - } - else - { - char *xname; - char *ret; - - error_trap_push (display); - xname = XGetAtomName (display, atom); - error_trap_pop (display); - if (xname == NULL) - return my_strdup ("[unknown atom]"); - - ret = my_strdup (xname); - XFree (xname); - - return ret; - } -} - - -#define ELAPSED(start_time, current_time) \ - (((((double)current_time.tv_sec - start_time.tv_sec) * 1000000 + \ - (current_time.tv_usec - start_time.tv_usec))) / 1000.0) - -static struct timeval program_start_time; - -static Bool -try_get_reply (Display *xdisplay, - AgGetPropertyTask *task) -{ - if (ag_task_have_reply (task)) - { - int result; - Atom actual_type; - int actual_format; - unsigned long n_items; - unsigned long bytes_after; - unsigned char *data; - char *name; - struct timeval current_time; - - gettimeofday (¤t_time, NULL); - - printf (" %gms (we have a reply for property %ld)\n", - ELAPSED (program_start_time, current_time), - ag_task_get_property (task)); - - data = NULL; - - name = atom_name (xdisplay, - ag_task_get_property (task)); - printf (" %s on 0x%lx:\n", name, - ag_task_get_window (task)); - free (name); - - result = ag_task_get_reply_and_free (task, - &actual_type, - &actual_format, - &n_items, - &bytes_after, - &data); - task = NULL; - - if (result != Success) - { - fprintf (stderr, " error code %d getting reply\n", result); - } - else - { - name = atom_name (xdisplay, actual_type); - printf (" actual_type = %s\n", name); - free (name); - - printf (" actual_format = %d\n", actual_format); - - printf (" n_items = %lu\n", n_items); - printf (" bytes_after = %lu\n", bytes_after); - - printf (" data = \"%s\"\n", data ? (char*) data : "NULL"); - } - - return True; - } - - return False; -} - -static void run_speed_comparison (Display *xdisplay, - Window window); - -int -main (int argc, char **argv) -{ - Display *xdisplay; - int i; - int n_left; - int n_props; - Window window; - const char *window_str; - char *end; - Atom *props; - struct timeval current_time; - - if (argc < 2) - { - fprintf (stderr, "specify window ID\n"); - return 1; - } - - window_str = argv[1]; - - end = NULL; - window = strtoul (window_str, &end, 0); - if (end == NULL || *end != '\0') - { - fprintf (stderr, "\"%s\" does not parse as a window ID\n", window_str); - return 1; - } - - xdisplay = XOpenDisplay (NULL); - if (xdisplay == NULL) - { - fprintf (stderr, "Could not open display\n"); - return 1; - } - - if (getenv ("METACITY_SYNC") != NULL) - XSynchronize (xdisplay, True); - - XSetErrorHandler (x_error_handler); - - n_props = 0; - props = XListProperties (xdisplay, window, &n_props); - if (n_props == 0 || props == NULL) - { - fprintf (stderr, "Window has no properties\n"); - return 1; - } - - gettimeofday (&program_start_time, NULL); - - i = 0; - while (i < n_props) - { - gettimeofday (¤t_time, NULL); - printf (" %gms (sending request for property %ld)\n", - ELAPSED (program_start_time, current_time), - props[i]); - if (ag_task_create (xdisplay, - window, props[i], - 0, 0xffffffff, - False, - AnyPropertyType) == NULL) - { - fprintf (stderr, "Failed to send request\n"); - return 1; - } - - ++i; - } - - XFree (props); - props = NULL; - - n_left = n_props; - - while (TRUE) - { - XEvent xevent; - int connection; - fd_set set; - AgGetPropertyTask *task; - - /* Mop up event queue */ - while (XPending (xdisplay) > 0) - { - XNextEvent (xdisplay, &xevent); - gettimeofday (¤t_time, NULL); - printf (" %gms (processing event type %d)\n", - ELAPSED (program_start_time, current_time), - xevent.xany.type); - } - - while ((task = ag_get_next_completed_task (xdisplay))) - { - try_get_reply (xdisplay, task); - n_left -= 1; - } - - if (n_left == 0) - { - printf ("All %d replies received.\n", n_props); - break; - } - - /* Wake up if we may have a reply */ - connection = ConnectionNumber (xdisplay); - - FD_ZERO (&set); - FD_SET (connection, &set); - - gettimeofday (¤t_time, NULL); - printf (" %gms (blocking for data %d left)\n", - ELAPSED (program_start_time, current_time), n_left); - select (connection + 1, &set, NULL, NULL, NULL); - } - - run_speed_comparison (xdisplay, window); - - return 0; -} - -/* This function doesn't have all the printf's - * and other noise, it just compares async to sync - */ -static void -run_speed_comparison (Display *xdisplay, - Window window) -{ - int i; - int n_props; - struct timeval start, end; - int n_left; - - /* We just use atom values (0 to n_props) % 200, many are probably - * BadAtom, that's fine, but the %200 keeps most of them valid. The - * async case is about twice as advantageous when using valid atoms - * (or the issue may be that it's more advantageous when the - * properties are present and data is transmitted). - */ - n_props = 4000; - printf ("Timing with %d property requests\n", n_props); - - gettimeofday (&start, NULL); - - i = 0; - while (i < n_props) - { - if (ag_task_create (xdisplay, - window, (Atom) i % 200, - 0, 0xffffffff, - False, - AnyPropertyType) == NULL) - { - fprintf (stderr, "Failed to send request\n"); - exit (1); - } - - ++i; - } - - n_left = n_props; - - while (TRUE) - { - int connection; - fd_set set; - XEvent xevent; - AgGetPropertyTask *task; - - /* Mop up event queue */ - while (XPending (xdisplay) > 0) - XNextEvent (xdisplay, &xevent); - - while ((task = ag_get_next_completed_task (xdisplay))) - { - int result; - Atom actual_type; - int actual_format; - unsigned long n_items; - unsigned long bytes_after; - unsigned char *data; - - assert (ag_task_have_reply (task)); - - data = NULL; - result = ag_task_get_reply_and_free (task, - &actual_type, - &actual_format, - &n_items, - &bytes_after, - &data); - - if (data) - XFree (data); - - n_left -= 1; - } - - if (n_left == 0) - break; - - /* Wake up if we may have a reply */ - connection = ConnectionNumber (xdisplay); - - FD_ZERO (&set); - FD_SET (connection, &set); - - select (connection + 1, &set, NULL, NULL, NULL); - } - - gettimeofday (&end, NULL); - - printf ("Async time: %gms\n", - ELAPSED (start, end)); - - gettimeofday (&start, NULL); - - error_trap_push (xdisplay); - - i = 0; - while (i < n_props) - { - Atom actual_type; - int actual_format; - unsigned long n_items; - unsigned long bytes_after; - unsigned char *data; - - data = NULL; - if (XGetWindowProperty (xdisplay, window, - (Atom) i % 200, - 0, 0xffffffff, - False, - AnyPropertyType, - &actual_type, - &actual_format, - &n_items, - &bytes_after, - &data) == Success) - { - if (data) - XFree (data); - } - - ++i; - } - - error_trap_pop (xdisplay); - - gettimeofday (&end, NULL); - - printf ("Sync time: %gms\n", - ELAPSED (start, end)); -} diff --git a/src/core/testboxes.c b/src/core/testboxes.c deleted file mode 100644 index 91ac2f87..00000000 --- a/src/core/testboxes.c +++ /dev/null @@ -1,1416 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity box operation testing program */ - -/* - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "boxes.h" -#include <glib.h> -#include <stdlib.h> -#include <stdio.h> -#include <X11/Xutil.h> /* Just for the definition of the various gravities */ -#include <time.h> /* To initialize random seed */ - -#define NUM_RANDOM_RUNS 10000 - -static void -init_random_ness () -{ - srand(time(NULL)); -} - -static void -get_random_rect (MetaRectangle *rect) -{ - rect->x = rand () % 1600; - rect->y = rand () % 1200; - rect->width = rand () % 1600 + 1; - rect->height = rand () % 1200 + 1; -} - -static MetaRectangle* -new_meta_rect (int x, int y, int width, int height) -{ - MetaRectangle* temporary; - temporary = g_new (MetaRectangle, 1); - temporary->x = x; - temporary->y = y; - temporary->width = width; - temporary->height = height; - - return temporary; -} - -static MetaStrut* -new_meta_strut (int x, int y, int width, int height, int side) -{ - MetaStrut* temporary; - temporary = g_new (MetaStrut, 1); - temporary->rect = meta_rect(x, y, width, height); - temporary->side = side; - - return temporary; -} - -static MetaEdge* -new_screen_edge (int x, int y, int width, int height, int side_type) -{ - MetaEdge* temporary; - temporary = g_new (MetaEdge, 1); - temporary->rect.x = x; - temporary->rect.y = y; - temporary->rect.width = width; - temporary->rect.height = height; - temporary->side_type = side_type; - temporary->edge_type = META_EDGE_SCREEN; - - return temporary; -} - -static MetaEdge* -new_xinerama_edge (int x, int y, int width, int height, int side_type) -{ - MetaEdge* temporary; - temporary = g_new (MetaEdge, 1); - temporary->rect.x = x; - temporary->rect.y = y; - temporary->rect.width = width; - temporary->rect.height = height; - temporary->side_type = side_type; - temporary->edge_type = META_EDGE_XINERAMA; - - return temporary; -} - -static void -test_area () -{ - MetaRectangle temp; - int i; - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&temp); - g_assert (meta_rectangle_area (&temp) == temp.width * temp.height); - } - - temp = meta_rect (0, 0, 5, 7); - g_assert (meta_rectangle_area (&temp) == 35); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_intersect () -{ - MetaRectangle a = {100, 200, 50, 40}; - MetaRectangle b = { 0, 50, 110, 152}; - MetaRectangle c = { 0, 0, 10, 10}; - MetaRectangle d = {100, 100, 50, 50}; - MetaRectangle b_intersect_d = {100, 100, 10, 50}; - MetaRectangle temp; - MetaRectangle temp2; - - meta_rectangle_intersect (&a, &b, &temp); - temp2 = meta_rect (100, 200, 10, 2); - g_assert (meta_rectangle_equal (&temp, &temp2)); - g_assert (meta_rectangle_area (&temp) == 20); - - meta_rectangle_intersect (&a, &c, &temp); - g_assert (meta_rectangle_area (&temp) == 0); - - meta_rectangle_intersect (&a, &d, &temp); - g_assert (meta_rectangle_area (&temp) == 0); - - meta_rectangle_intersect (&b, &d, &b); - g_assert (meta_rectangle_equal (&b, &b_intersect_d)); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_equal () -{ - MetaRectangle a = {10, 12, 4, 18}; - MetaRectangle b = a; - MetaRectangle c = {10, 12, 4, 19}; - MetaRectangle d = {10, 12, 7, 18}; - MetaRectangle e = {10, 62, 4, 18}; - MetaRectangle f = {27, 12, 4, 18}; - - g_assert ( meta_rectangle_equal (&a, &b)); - g_assert (!meta_rectangle_equal (&a, &c)); - g_assert (!meta_rectangle_equal (&a, &d)); - g_assert (!meta_rectangle_equal (&a, &e)); - g_assert (!meta_rectangle_equal (&a, &f)); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_overlap_funcs () -{ - MetaRectangle temp1, temp2; - int i; - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&temp1); - get_random_rect (&temp2); - g_assert (meta_rectangle_overlap (&temp1, &temp2) == - (meta_rectangle_horiz_overlap (&temp1, &temp2) && - meta_rectangle_vert_overlap (&temp1, &temp2))); - } - - temp1 = meta_rect ( 0, 0, 10, 10); - temp2 = meta_rect (20, 0, 10, 5); - g_assert (!meta_rectangle_overlap (&temp1, &temp2)); - g_assert (!meta_rectangle_horiz_overlap (&temp1, &temp2)); - g_assert ( meta_rectangle_vert_overlap (&temp1, &temp2)); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_basic_fitting () -{ - MetaRectangle temp1, temp2, temp3; - int i; - /* Four cases: - * case temp1 fits temp2 temp1 could fit temp2 - * 1 Y Y - * 2 N Y - * 3 Y N - * 4 N N - * Of the four cases, case 3 is impossible. An alternate way of looking - * at this table is that either the middle column must be no, or the last - * column must be yes. So we test that. Also, we can repeat the test - * reversing temp1 and temp2. - */ - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&temp1); - get_random_rect (&temp2); - g_assert (meta_rectangle_contains_rect (&temp1, &temp2) == FALSE || - meta_rectangle_could_fit_rect (&temp1, &temp2) == TRUE); - g_assert (meta_rectangle_contains_rect (&temp2, &temp1) == FALSE || - meta_rectangle_could_fit_rect (&temp2, &temp1) == TRUE); - } - - temp1 = meta_rect ( 0, 0, 10, 10); - temp2 = meta_rect ( 5, 5, 5, 5); - temp3 = meta_rect ( 8, 2, 3, 7); - g_assert ( meta_rectangle_contains_rect (&temp1, &temp2)); - g_assert (!meta_rectangle_contains_rect (&temp2, &temp1)); - g_assert (!meta_rectangle_contains_rect (&temp1, &temp3)); - g_assert ( meta_rectangle_could_fit_rect (&temp1, &temp3)); - g_assert (!meta_rectangle_could_fit_rect (&temp3, &temp2)); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -free_strut_list (GSList *struts) -{ - GSList *tmp = struts; - while (tmp) - { - g_free (tmp->data); - tmp = tmp->next; - } - g_slist_free (struts); -} - -static GSList* -get_strut_list (int which) -{ - GSList *ans; - MetaDirection wc = 0; /* wc == who cares? ;-) */ - - ans = NULL; - - g_assert (which >=0 && which <= 6); - switch (which) - { - case 0: - break; - case 1: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, wc)); - break; - case 2: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, wc)); - break; - case 3: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 700, 525, 200, 150, wc)); - break; - case 4: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc)); - break; - case 5: - ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, wc)); - break; - case 6: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, wc)); - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc)); - break; - } - - return ans; -} - -static GList* -get_screen_region (int which) -{ - GList *ret; - GSList *struts; - MetaRectangle basic_rect; - - basic_rect = meta_rect (0, 0, 1600, 1200); - ret = NULL; - - struts = get_strut_list (which); - ret = meta_rectangle_get_minimal_spanning_set_for_region (&basic_rect, struts); - free_strut_list (struts); - - return ret; -} - -static GList* -get_screen_edges (int which) -{ - GList *ret; - GSList *struts; - MetaRectangle basic_rect; - - basic_rect = meta_rect (0, 0, 1600, 1200); - ret = NULL; - - struts = get_strut_list (which); - ret = meta_rectangle_find_onscreen_edges (&basic_rect, struts); - free_strut_list (struts); - - return ret; -} - -static GList* -get_xinerama_edges (int which_xinerama_set, int which_strut_set) -{ - GList *ret; - GSList *struts; - GList *xins; - - xins = NULL; - g_assert (which_xinerama_set >=0 && which_xinerama_set <= 3); - switch (which_xinerama_set) - { - case 0: - xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 1200)); - break; - case 1: - xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 800, 1200)); - xins = g_list_prepend (xins, new_meta_rect (800, 0, 800, 1200)); - break; - case 2: - xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 600)); - xins = g_list_prepend (xins, new_meta_rect ( 0, 600, 1600, 600)); - break; - case 3: - xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 600)); - xins = g_list_prepend (xins, new_meta_rect ( 0, 600, 800, 600)); - xins = g_list_prepend (xins, new_meta_rect (800, 600, 800, 600)); - break; - } - - ret = NULL; - - struts = get_strut_list (which_strut_set); - ret = meta_rectangle_find_nonintersected_xinerama_edges (xins, struts); - - free_strut_list (struts); - meta_rectangle_free_list_and_elements (xins); - - return ret; -} - -#if 0 -static void -test_merge_regions () -{ - /* logarithmically distributed random number of struts (range?) - * logarithmically distributed random size of struts (up to screen size???) - * uniformly distributed location of center of struts (within screen) - * merge all regions that are possible - * print stats on problem setup - * number of (non-completely-occluded?) struts - * percentage of screen covered - * length of resulting non-minimal spanning set - * length of resulting minimal spanning set - * print stats on merged regions: - * number boxes merged - * number of those merges that were of the form A contains B - * number of those merges that were of the form A partially contains B - * number of those merges that were of the form A is adjacent to B - */ - - GList* region; - GList* compare; - int num_contains, num_merged, num_part_contains, num_adjacent; - - num_contains = num_merged = num_part_contains = num_adjacent = 0; - compare = region = get_screen_region (2); - g_assert (region); - - printf ("Merging stats:\n"); - printf (" Length of initial list: %d\n", g_list_length (region)); -#ifdef PRINT_DEBUG - char rect1[RECT_LENGTH], rect2[RECT_LENGTH]; - char region_list[(RECT_LENGTH + 2) * g_list_length (region)]; - meta_rectangle_region_to_string (region, ", ", region_list); - printf (" Initial rectangles: %s\n", region_list); -#endif - - while (compare && compare->next) - { - MetaRectangle *a = compare->data; - GList *other = compare->next; - - g_assert (a->width > 0 && a->height > 0); - - while (other) - { - MetaRectangle *b = other->data; - GList *delete_me = NULL; - - g_assert (b->width > 0 && b->height > 0); - -#ifdef PRINT_DEBUG - printf (" -- Comparing %s to %s --\n", - meta_rectangle_to_string (a, rect1), - meta_rectangle_to_string (b, rect2)); -#endif - - /* If a contains b, just remove b */ - if (meta_rectangle_contains_rect (a, b)) - { - delete_me = other; - num_contains++; - num_merged++; - } - /* If b contains a, just remove a */ - else if (meta_rectangle_contains_rect (a, b)) - { - delete_me = compare; - num_contains++; - num_merged++; - } - /* If a and b might be mergeable horizontally */ - else if (a->y == b->y && a->height == b->height) - { - /* If a and b overlap */ - if (meta_rectangle_overlap (a, b)) - { - int new_x = MIN (a->x, b->x); - a->width = MAX (a->x + a->width, b->x + b->width) - new_x; - a->x = new_x; - delete_me = other; - num_part_contains++; - num_merged++; - } - /* If a and b are adjacent */ - else if (a->x + a->width == b->x || a->x == b->x + b->width) - { - int new_x = MIN (a->x, b->x); - a->width = MAX (a->x + a->width, b->x + b->width) - new_x; - a->x = new_x; - delete_me = other; - num_adjacent++; - num_merged++; - } - } - /* If a and b might be mergeable vertically */ - else if (a->x == b->x && a->width == b->width) - { - /* If a and b overlap */ - if (meta_rectangle_overlap (a, b)) - { - int new_y = MIN (a->y, b->y); - a->height = MAX (a->y + a->height, b->y + b->height) - new_y; - a->y = new_y; - delete_me = other; - num_part_contains++; - num_merged++; - } - /* If a and b are adjacent */ - else if (a->y + a->height == b->y || a->y == b->y + b->height) - { - int new_y = MIN (a->y, b->y); - a->height = MAX (a->y + a->height, b->y + b->height) - new_y; - a->y = new_y; - delete_me = other; - num_adjacent++; - num_merged++; - } - } - - other = other->next; - - /* Delete any rectangle in the list that is no longer wanted */ - if (delete_me != NULL) - { -#ifdef PRINT_DEBUG - MetaRectangle *bla = delete_me->data; - printf (" Deleting rect %s\n", - meta_rectangle_to_string (bla, rect1)); -#endif - - /* Deleting the rect we're compare others to is a little tricker */ - if (compare == delete_me) - { - compare = compare->next; - other = compare->next; - a = compare->data; - } - - /* Okay, we can free it now */ - g_free (delete_me->data); - region = g_list_delete_link (region, delete_me); - } - -#ifdef PRINT_DEBUG - char region_list[(RECT_LENGTH + 2) * g_list_length (region)]; - meta_rectangle_region_to_string (region, ", ", region_list); - printf (" After comparison, new list is: %s\n", region_list); -#endif - } - - compare = compare->next; - } - - printf (" Num rectangles contained in others : %d\n", - num_contains); - printf (" Num rectangles partially contained in others: %d\n", - num_part_contains); - printf (" Num rectangles adjacent to others : %d\n", - num_adjacent); - printf (" Num rectangles merged with others : %d\n", - num_merged); -#ifdef PRINT_DEBUG - char region_list2[(RECT_LENGTH + 2) * g_list_length (region)]; - meta_rectangle_region_to_string (region, ", ", region_list2); - printf (" Final rectangles: %s\n", region_list2); -#endif - - meta_rectangle_free_spanning_set (region); - region = NULL; - - printf ("%s passed.\n", G_STRFUNC); -} -#endif - -static void -verify_lists_are_equal (GList *code, GList *answer) -{ - int which = 0; - - while (code && answer) - { - MetaRectangle *a = code->data; - MetaRectangle *b = answer->data; - - if (a->x != b->x || - a->y != b->y || - a->width != b->width || - a->height != b->height) - { - g_error ("%dth item in code answer answer lists do not match; " - "code rect: %d,%d + %d,%d; answer rect: %d,%d + %d,%d\n", - which, - a->x, a->y, a->width, a->height, - b->x, b->y, b->width, b->height); - } - - code = code->next; - answer = answer->next; - - which++; - } - - /* Ought to be at the end of both lists; check if we aren't */ - if (code) - { - MetaRectangle *tmp = code->data; - g_error ("code list longer than answer list by %d items; " - "first extra item: %d,%d +%d,%d\n", - g_list_length (code), - tmp->x, tmp->y, tmp->width, tmp->height); - } - - if (answer) - { - MetaRectangle *tmp = answer->data; - g_error ("answer list longer than code list by %d items; " - "first extra item: %d,%d +%d,%d\n", - g_list_length (answer), - tmp->x, tmp->y, tmp->width, tmp->height); - } -} - -static void -test_regions_okay () -{ - GList* region; - GList* tmp; - - /*************************************************************/ - /* Make sure test region 0 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (0); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect (0, 0, 1600, 1200)); - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 1 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (1); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect (0, 20, 400, 1180)); - tmp = g_list_prepend (tmp, new_meta_rect (0, 20, 1600, 1140)); - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 2 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (2); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 300, 1180)); - tmp = g_list_prepend (tmp, new_meta_rect ( 450, 20, 350, 1180)); - tmp = g_list_prepend (tmp, new_meta_rect (1200, 20, 400, 1180)); - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 800, 1130)); - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 1080)); - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 3 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (3); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect ( 380, 675, 420, 525)); /* 220500 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 300, 1180)); /* 354000 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 380, 20, 320, 1180)); /* 377600 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 675, 800, 475)); /* 380000 */ - tmp = g_list_prepend (tmp, new_meta_rect (1200, 20, 400, 1180)); /* 472000 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 675, 1600, 425)); /* 680000 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 900, 20, 700, 1080)); /* 756000 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 700, 1130)); /* 791000 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 505)); /* 808000 */ -#if 0 - printf ("Got to here...\n"); - char region_list[(RECT_LENGTH+2) * g_list_length (region)]; - char tmp_list[ (RECT_LENGTH+2) * g_list_length (tmp)]; - meta_rectangle_region_to_string (region, ", ", region_list); - meta_rectangle_region_to_string (region, ", ", tmp_list); - printf ("%s vs. %s\n", region_list, tmp_list); -#endif - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 4 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (4); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect ( 800, 20, 800, 1180)); - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 5 has the right spanning rectangles */ - /*************************************************************/ - printf ("The next test intentionally causes a warning, " - "but it can be ignored.\n"); - region = get_screen_region (5); - verify_lists_are_equal (region, NULL); - - /* FIXME: Still to do: - * - Create random struts and check the regions somehow - */ - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_region_fitting () -{ - GList* region; - MetaRectangle rect; - - /* See test_basic_fitting() for how/why these automated random tests work */ - int i; - region = get_screen_region (3); - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&rect); - g_assert (meta_rectangle_contained_in_region (region, &rect) == FALSE || - meta_rectangle_could_fit_in_region (region, &rect) == TRUE); - } - meta_rectangle_free_list_and_elements (region); - - /* Do some manual tests too */ - region = get_screen_region (1); - - rect = meta_rect (50, 50, 400, 400); - g_assert (meta_rectangle_could_fit_in_region (region, &rect)); - g_assert (meta_rectangle_contained_in_region (region, &rect)); - - rect = meta_rect (250, 0, 500, 1150); - g_assert (!meta_rectangle_could_fit_in_region (region, &rect)); - g_assert (!meta_rectangle_contained_in_region (region, &rect)); - - rect = meta_rect (250, 0, 400, 400); - g_assert (meta_rectangle_could_fit_in_region (region, &rect)); - g_assert (!meta_rectangle_contained_in_region (region, &rect)); - - meta_rectangle_free_list_and_elements (region); - - region = get_screen_region (2); - rect = meta_rect (1000, 50, 600, 1100); - g_assert (meta_rectangle_could_fit_in_region (region, &rect)); - g_assert (!meta_rectangle_contained_in_region (region, &rect)); - - meta_rectangle_free_list_and_elements (region); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_clamping_to_region () -{ - GList* region; - MetaRectangle rect; - MetaRectangle min_size; - FixedDirections fixed_directions; - int i; - - min_size.height = min_size.width = 1; - fixed_directions = 0; - - region = get_screen_region (3); - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - MetaRectangle temp; - get_random_rect (&rect); - temp = rect; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (meta_rectangle_could_fit_in_region (region, &rect) == TRUE); - g_assert (rect.x == temp.x && rect.y == temp.y); - } - meta_rectangle_free_list_and_elements (region); - - /* Do some manual tests too */ - region = get_screen_region (1); - - rect = meta_rect (50, 50, 10000, 10000); - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 1600 && rect.height == 1140); - - rect = meta_rect (275, -50, 410, 10000); - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 400 && rect.height == 1180); - - rect = meta_rect (50, 50, 10000, 10000); - min_size.height = 1170; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 400 && rect.height == 1180); - - printf ("The next test intentionally causes a warning, " - "but it can be ignored.\n"); - rect = meta_rect (50, 50, 10000, 10000); - min_size.width = 600; min_size.height = 1170; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 600 && rect.height == 1170); - - rect = meta_rect (350, 50, 100, 1100); - min_size.width = 1; min_size.height = 1; - fixed_directions = FIXED_DIRECTION_X; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 100 && rect.height == 1100); - - rect = meta_rect (300, 70, 500, 1100); - min_size.width = 1; min_size.height = 1; - fixed_directions = FIXED_DIRECTION_Y; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 400 && rect.height == 1100); - - printf ("The next test intentionally causes a warning, " - "but it can be ignored.\n"); - rect = meta_rect (300, 70, 999999, 999999); - min_size.width = 100; min_size.height = 200; - fixed_directions = FIXED_DIRECTION_Y; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 100 && rect.height == 999999); - - meta_rectangle_free_list_and_elements (region); - - printf ("%s passed.\n", G_STRFUNC); -} - -static gboolean -rect_overlaps_region (const GList *spanning_rects, - const MetaRectangle *rect) -{ - /* FIXME: Should I move this to boxes.[ch]? */ - const GList *temp; - gboolean overlaps; - - temp = spanning_rects; - overlaps = FALSE; - while (!overlaps && temp != NULL) - { - overlaps = overlaps || meta_rectangle_overlap (temp->data, rect); - temp = temp->next; - } - - return overlaps; -} - -gboolean time_to_print = FALSE; - -static void -test_clipping_to_region () -{ - GList* region; - MetaRectangle rect, temp; - FixedDirections fixed_directions = 0; - int i; - - region = get_screen_region (3); - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&rect); - if (rect_overlaps_region (region, &rect)) - { - meta_rectangle_clip_to_region (region, 0, &rect); - g_assert (meta_rectangle_contained_in_region (region, &rect) == TRUE); - } - } - meta_rectangle_free_list_and_elements (region); - - /* Do some manual tests too */ - region = get_screen_region (2); - - rect = meta_rect (-50, -10, 10000, 10000); - meta_rectangle_clip_to_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (region->data, &rect)); - - rect = meta_rect (300, 1000, 400, 200); - temp = meta_rect (300, 1000, 400, 150); - meta_rectangle_clip_to_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (400, 1000, 300, 200); - temp = meta_rect (450, 1000, 250, 200); - meta_rectangle_clip_to_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (400, 1000, 300, 200); - temp = meta_rect (400, 1000, 300, 150); - meta_rectangle_clip_to_region (region, - FIXED_DIRECTION_X, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (400, 1000, 300, 200); - temp = meta_rect (400, 1000, 300, 150); - meta_rectangle_clip_to_region (region, - FIXED_DIRECTION_X, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - meta_rectangle_free_list_and_elements (region); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_shoving_into_region () -{ - GList* region; - MetaRectangle rect, temp; - FixedDirections fixed_directions = 0; - int i; - - region = get_screen_region (3); - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&rect); - if (meta_rectangle_could_fit_in_region (region, &rect)) - { - meta_rectangle_shove_into_region (region, 0, &rect); - g_assert (meta_rectangle_contained_in_region (region, &rect)); - } - } - meta_rectangle_free_list_and_elements (region); - - /* Do some manual tests too */ - region = get_screen_region (2); - - rect = meta_rect (300, 1000, 400, 200); - temp = meta_rect (300, 950, 400, 200); - meta_rectangle_shove_into_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (425, 1000, 300, 200); - temp = meta_rect (450, 1000, 300, 200); - meta_rectangle_shove_into_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (425, 1000, 300, 200); - temp = meta_rect (425, 950, 300, 200); - meta_rectangle_shove_into_region (region, - FIXED_DIRECTION_X, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 300, 1000, 400, 200); - temp = meta_rect (1200, 1000, 400, 200); - meta_rectangle_shove_into_region (region, - FIXED_DIRECTION_Y, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 800, 1150, 400, 50); /* Completely "offscreen" :) */ - temp = meta_rect ( 800, 1050, 400, 50); - meta_rectangle_shove_into_region (region, - 0, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (-1000, 0, 400, 150); /* Offscreen in 2 directions */ - temp = meta_rect ( 0, 20, 400, 150); - meta_rectangle_shove_into_region (region, - 0, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - meta_rectangle_free_list_and_elements (region); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -verify_edge_lists_are_equal (GList *code, GList *answer) -{ - int which = 0; - - while (code && answer) - { - MetaEdge *a = code->data; - MetaEdge *b = answer->data; - - if (!meta_rectangle_equal (&a->rect, &b->rect) || - a->side_type != b->side_type || - a->edge_type != b->edge_type) - { - g_error ("%dth item in code answer answer lists do not match; " - "code rect: %d,%d + %d,%d; answer rect: %d,%d + %d,%d\n", - which, - a->rect.x, a->rect.y, a->rect.width, a->rect.height, - b->rect.x, b->rect.y, b->rect.width, b->rect.height); - } - - code = code->next; - answer = answer->next; - - which++; - } - - /* Ought to be at the end of both lists; check if we aren't */ - if (code) - { - MetaEdge *tmp = code->data; - g_error ("code list longer than answer list by %d items; " - "first extra item rect: %d,%d +%d,%d\n", - g_list_length (code), - tmp->rect.x, tmp->rect.y, tmp->rect.width, tmp->rect.height); - } - - if (answer) - { - MetaEdge *tmp = answer->data; - g_error ("answer list longer than code list by %d items; " - "first extra item rect: %d,%d +%d,%d\n", - g_list_length (answer), - tmp->rect.x, tmp->rect.y, tmp->rect.width, tmp->rect.height); - } -} - -static void -test_find_onscreen_edges () -{ - GList* edges; - GList* tmp; - - int left = META_DIRECTION_LEFT; - int right = META_DIRECTION_RIGHT; - int top = META_DIRECTION_TOP; - int bottom = META_DIRECTION_BOTTOM; - - /*************************************************/ - /* Make sure test region 0 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (0); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 1600, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 0, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 0, 0, 1200, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 0, 0, 1200, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 1 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (1); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 400, 1160, 1200, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 20, 0, 1140, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 400, 1160, 0, 40, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 0, 1180, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 2 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (2); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge (1200, 1200, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 450, 1200, 350, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 300, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 300, 1150, 150, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1100, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 20, 0, 1180, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1100, 0, 100, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 300, 1150, 0, 50, right)); - tmp = g_list_prepend (tmp, new_screen_edge (1200, 1100, 0, 100, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 450, 1150, 0, 50, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 0, 1180, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 3 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (3); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge (1200, 1200, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 380, 1200, 420, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 300, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 300, 1150, 80, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1100, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 700, 525, 200, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 700, 675, 200, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 20, 0, 1180, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1100, 0, 100, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 700, 525, 0, 150, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 300, 1150, 0, 50, right)); - tmp = g_list_prepend (tmp, new_screen_edge (1200, 1100, 0, 100, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 900, 525, 0, 150, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 380, 1150, 0, 50, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 0, 1180, left)); - -#if 0 - #define FUDGE 50 /* number of edges */ - char big_buffer1[(EDGE_LENGTH+2)*FUDGE], big_buffer2[(EDGE_LENGTH+2)*FUDGE]; - meta_rectangle_edge_list_to_string (edges, "\n ", big_buffer1); - meta_rectangle_edge_list_to_string (tmp, "\n ", big_buffer2); - printf("Generated edge list:\n %s\nComparison edges list:\n %s\n", - big_buffer1, big_buffer2); -#endif - - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 4 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (4); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1200, 800, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 20, 800, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 20, 0, 1180, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 20, 0, 1180, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 5 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (5); - tmp = NULL; - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 6 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (6); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 1600, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 40, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 40, 0, 1160, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 40, 0, 1160, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_find_nonintersected_xinerama_edges () -{ - GList* edges; - GList* tmp; - - int left = META_DIRECTION_LEFT; - int right = META_DIRECTION_RIGHT; - int top = META_DIRECTION_TOP; - int bottom = META_DIRECTION_BOTTOM; - - /*************************************************************************/ - /* Make sure test xinerama set 0 for with region 0 has the correct edges */ - /*************************************************************************/ - edges = get_xinerama_edges (0, 0); - tmp = NULL; - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test xinerama set 2 for with region 1 has the correct edges */ - /*************************************************************************/ - edges = get_xinerama_edges (2, 1); - tmp = NULL; - tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 1600, 0, bottom)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 1600, 0, top)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test xinerama set 1 for with region 2 has the correct edges */ - /*************************************************************************/ - edges = get_xinerama_edges (1, 2); - tmp = NULL; - tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 20, 0, 1080, right)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 20, 0, 1180, left)); -#if 0 - #define FUDGE 50 - char big_buffer1[(EDGE_LENGTH+2)*FUDGE], big_buffer2[(EDGE_LENGTH+2)*FUDGE]; - meta_rectangle_edge_list_to_string (edges, "\n ", big_buffer1); - meta_rectangle_edge_list_to_string (tmp, "\n ", big_buffer2); - printf("Generated edge list:\n %s\nComparison edges list:\n %s\n", - big_buffer1, big_buffer2); -#endif - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test xinerama set 3 for with region 3 has the correct edges */ - /*************************************************************************/ - edges = get_xinerama_edges (3, 3); - tmp = NULL; - tmp = g_list_prepend (tmp, new_xinerama_edge ( 900, 600, 700, 0, bottom)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 700, 0, bottom)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 900, 600, 700, 0, top)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 700, 0, top)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 675, 0, 425, right)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 675, 0, 525, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test xinerama set 3 for with region 4 has the correct edges */ - /*************************************************************************/ - edges = get_xinerama_edges (3, 4); - tmp = NULL; - tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 800, 0, bottom)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 800, 0, top)); - tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 0, 600, right)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test xinerama set 3 for with region 5has the correct edges */ - /*************************************************************************/ - edges = get_xinerama_edges (3, 5); - tmp = NULL; - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_gravity_resize () -{ - MetaRectangle oldrect, rect, temp; - - rect.x = -500; /* Some random amount not equal to oldrect.x to ensure that - * the resize is done with respect to oldrect instead of rect - */ - oldrect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect ( 50, 300, 20, 5); - meta_rectangle_resize_with_gravity (&oldrect, - &rect, - NorthWestGravity, - 20, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect (165, 300, 20, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - NorthGravity, - 20, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect (280, 300, 20, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - NorthEastGravity, - 20, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect ( 50, 695, 50, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - SouthWestGravity, - 50, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect (150, 695, 50, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - SouthGravity, - 50, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect (250, 695, 50, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - SouthEastGravity, - 50, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (167, 738, 237, 843); - temp = meta_rect (167, 1113, 832, 93); - meta_rectangle_resize_with_gravity (&rect, - &rect, - WestGravity, - 832, - 93); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 167, 738, 237, 843); - temp = meta_rect (-131, 1113, 833, 93); - meta_rectangle_resize_with_gravity (&rect, - &rect, - CenterGravity, - 832, - 93); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (300, 1000, 400, 200); - temp = meta_rect (270, 994, 430, 212); - meta_rectangle_resize_with_gravity (&rect, - &rect, - EastGravity, - 430, - 211); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (300, 1000, 400, 200); - temp = meta_rect (300, 1000, 430, 211); - meta_rectangle_resize_with_gravity (&rect, - &rect, - StaticGravity, - 430, - 211); - g_assert (meta_rectangle_equal (&rect, &temp)); - - printf ("%s passed.\n", G_STRFUNC); -} - -static void -test_find_closest_point_to_line () -{ - double x1, y1, x2, y2, px, py, rx, ry; - double answer_x, answer_y; - - x1 = 3.0; y1 = 49.0; - x2 = 2.0; y2 = - 1.0; - px = -2.6; py = 19.1; - answer_x = 2.4; answer_y = 19; - meta_rectangle_find_linepoint_closest_to_point (x1, y1, - x2, y2, - px, py, - &rx, &ry); - g_assert (rx == answer_x && ry == answer_y); - - /* Special test for x1 == x2, so that slop of line is infinite */ - x1 = 3.0; y1 = 49.0; - x2 = 3.0; y2 = - 1.0; - px = -2.6; py = 19.1; - answer_x = 3.0; answer_y = 19.1; - meta_rectangle_find_linepoint_closest_to_point (x1, y1, - x2, y2, - px, py, - &rx, &ry); - g_assert (rx == answer_x && ry == answer_y); - - /* Special test for y1 == y2, so perp line has slope of infinity */ - x1 = 3.14; y1 = 7.0; - x2 = 2.718; y2 = 7.0; - px = -2.6; py = 19.1; - answer_x = -2.6; answer_y = 7; - meta_rectangle_find_linepoint_closest_to_point (x1, y1, - x2, y2, - px, py, - &rx, &ry); - g_assert (rx == answer_x && ry == answer_y); - - /* Test when we the point we want to be closest to is actually on the line */ - x1 = 3.0; y1 = 49.0; - x2 = 2.0; y2 = - 1.0; - px = 2.4; py = 19.0; - answer_x = 2.4; answer_y = 19; - meta_rectangle_find_linepoint_closest_to_point (x1, y1, - x2, y2, - px, py, - &rx, &ry); - g_assert (rx == answer_x && ry == answer_y); - - printf ("%s passed.\n", G_STRFUNC); -} - -int -main() -{ - init_random_ness (); - test_area (); - test_intersect (); - test_equal (); - test_overlap_funcs (); - test_basic_fitting (); - - test_regions_okay (); - test_region_fitting (); - - test_clamping_to_region (); - test_clipping_to_region (); - test_shoving_into_region (); - - /* And now the functions dealing with edges more than boxes */ - test_find_onscreen_edges (); - test_find_nonintersected_xinerama_edges (); - - /* And now the misfit functions that don't quite fit in anywhere else... */ - test_gravity_resize (); - test_find_closest_point_to_line (); - - printf ("All tests passed.\n"); - return 0; -} diff --git a/src/core/util.c b/src/core/util.c deleted file mode 100644 index bcfcb7f4..00000000 --- a/src/core/util.c +++ /dev/null @@ -1,611 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity utilities */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#define _GNU_SOURCE -#define _POSIX_C_SOURCE 200112L /* for fdopen() */ - -#include <config.h> -#include "util.h" -#include "main.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <X11/Xlib.h> /* must explicitly be included for Solaris; #326746 */ -#include <X11/Xutil.h> /* Just for the definition of the various gravities */ - -#ifdef HAVE_BACKTRACE -#include <execinfo.h> -void -meta_print_backtrace (void) -{ - void *bt[500]; - int bt_size; - int i; - char **syms; - - bt_size = backtrace (bt, 500); - - syms = backtrace_symbols (bt, bt_size); - - i = 0; - while (i < bt_size) - { - meta_verbose (" %s\n", syms[i]); - ++i; - } - - free (syms); -} -#else -void -meta_print_backtrace (void) -{ - meta_verbose ("Not compiled with backtrace support\n"); -} -#endif - -static gboolean is_verbose = FALSE; -static gboolean is_debugging = FALSE; -static gboolean replace_current = FALSE; -static int no_prefix = 0; - -#ifdef WITH_VERBOSE_MODE -static FILE* logfile = NULL; - -static void -ensure_logfile (void) -{ - if (logfile == NULL && g_getenv ("METACITY_USE_LOGFILE")) - { - char *filename = NULL; - char *tmpl; - int fd; - GError *err; - - tmpl = g_strdup_printf ("metacity-%d-debug-log-XXXXXX", - (int) getpid ()); - - err = NULL; - fd = g_file_open_tmp (tmpl, - &filename, - &err); - - g_free (tmpl); - - if (err != NULL) - { - meta_warning (_("Failed to open debug log: %s\n"), - err->message); - g_error_free (err); - return; - } - - logfile = fdopen (fd, "w"); - - if (logfile == NULL) - { - meta_warning (_("Failed to fdopen() log file %s: %s\n"), - filename, strerror (errno)); - close (fd); - } - else - { - g_printerr (_("Opened log file %s\n"), filename); - } - - g_free (filename); - } -} -#endif - -gboolean -meta_is_verbose (void) -{ - return is_verbose; -} - -void -meta_set_verbose (gboolean setting) -{ -#ifndef WITH_VERBOSE_MODE - if (setting) - meta_fatal (_("Metacity was compiled without support for verbose mode\n")); -#else - if (setting) - ensure_logfile (); -#endif - - is_verbose = setting; -} - -gboolean -meta_is_debugging (void) -{ - return is_debugging; -} - -void -meta_set_debugging (gboolean setting) -{ -#ifdef WITH_VERBOSE_MODE - if (setting) - ensure_logfile (); -#endif - - is_debugging = setting; -} - -gboolean -meta_get_replace_current_wm (void) -{ - return replace_current; -} - -void -meta_set_replace_current_wm (gboolean setting) -{ - replace_current = setting; -} - -char * -meta_g_utf8_strndup (const gchar *src, - gsize n) -{ - const gchar *s = src; - while (n && *s) - { - s = g_utf8_next_char (s); - n--; - } - - return g_strndup (src, s - src); -} - -static int -utf8_fputs (const char *str, - FILE *f) -{ - char *l; - int retval; - - l = g_locale_from_utf8 (str, -1, NULL, NULL, NULL); - - if (l == NULL) - retval = fputs (str, f); /* just print it anyway, better than nothing */ - else - retval = fputs (l, f); - - g_free (l); - - return retval; -} - -void -meta_free_gslist_and_elements (GSList *list_to_deep_free) -{ - g_slist_foreach (list_to_deep_free, - (void (*)(gpointer,gpointer))&g_free, /* ew, for ugly */ - NULL); - g_slist_free (list_to_deep_free); -} - -#ifdef WITH_VERBOSE_MODE -void -meta_debug_spew_real (const char *format, ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - if (!is_debugging) - return; - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - - out = logfile ? logfile : stderr; - - if (no_prefix == 0) - utf8_fputs (_("Window manager: "), out); - utf8_fputs (str, out); - - fflush (out); - - g_free (str); -} -#endif /* WITH_VERBOSE_MODE */ - -#ifdef WITH_VERBOSE_MODE -void -meta_verbose_real (const char *format, ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - if (!is_verbose) - return; - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - - out = logfile ? logfile : stderr; - - if (no_prefix == 0) - utf8_fputs ("Window manager: ", out); - utf8_fputs (str, out); - - fflush (out); - - g_free (str); -} -#endif /* WITH_VERBOSE_MODE */ - -#ifdef WITH_VERBOSE_MODE -static const char* -topic_name (MetaDebugTopic topic) -{ - switch (topic) - { - case META_DEBUG_FOCUS: - return "FOCUS"; - case META_DEBUG_WORKAREA: - return "WORKAREA"; - case META_DEBUG_STACK: - return "STACK"; - case META_DEBUG_THEMES: - return "THEMES"; - case META_DEBUG_SM: - return "SM"; - case META_DEBUG_EVENTS: - return "EVENTS"; - case META_DEBUG_WINDOW_STATE: - return "WINDOW_STATE"; - case META_DEBUG_WINDOW_OPS: - return "WINDOW_OPS"; - case META_DEBUG_PLACEMENT: - return "PLACEMENT"; - case META_DEBUG_GEOMETRY: - return "GEOMETRY"; - case META_DEBUG_PING: - return "PING"; - case META_DEBUG_XINERAMA: - return "XINERAMA"; - case META_DEBUG_KEYBINDINGS: - return "KEYBINDINGS"; - case META_DEBUG_SYNC: - return "SYNC"; - case META_DEBUG_ERRORS: - return "ERRORS"; - case META_DEBUG_STARTUP: - return "STARTUP"; - case META_DEBUG_PREFS: - return "PREFS"; - case META_DEBUG_GROUPS: - return "GROUPS"; - case META_DEBUG_RESIZING: - return "RESIZING"; - case META_DEBUG_SHAPES: - return "SHAPES"; - case META_DEBUG_COMPOSITOR: - return "COMPOSITOR"; - case META_DEBUG_EDGE_RESISTANCE: - return "EDGE_RESISTANCE"; - } - - return "WM"; -} - -static int sync_count = 0; - -void -meta_topic_real (MetaDebugTopic topic, - const char *format, - ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - if (!is_verbose) - return; - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - - out = logfile ? logfile : stderr; - - if (no_prefix == 0) - fprintf (out, "%s: ", topic_name (topic)); - - if (topic == META_DEBUG_SYNC) - { - ++sync_count; - fprintf (out, "%d: ", sync_count); - } - - utf8_fputs (str, out); - - fflush (out); - - g_free (str); -} -#endif /* WITH_VERBOSE_MODE */ - -void -meta_bug (const char *format, ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - -#ifdef WITH_VERBOSE_MODE - out = logfile ? logfile : stderr; -#else - out = stderr; -#endif - - if (no_prefix == 0) - utf8_fputs (_("Bug in window manager: "), out); - utf8_fputs (str, out); - - fflush (out); - - g_free (str); - - meta_print_backtrace (); - - /* stop us in a debugger */ - abort (); -} - -void -meta_warning (const char *format, ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - -#ifdef WITH_VERBOSE_MODE - out = logfile ? logfile : stderr; -#else - out = stderr; -#endif - - if (no_prefix == 0) - utf8_fputs (_("Window manager warning: "), out); - utf8_fputs (str, out); - - fflush (out); - - g_free (str); -} - -void -meta_fatal (const char *format, ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - -#ifdef WITH_VERBOSE_MODE - out = logfile ? logfile : stderr; -#else - out = stderr; -#endif - - if (no_prefix == 0) - utf8_fputs (_("Window manager error: "), out); - utf8_fputs (str, out); - - fflush (out); - - g_free (str); - - meta_exit (META_EXIT_ERROR); -} - -void -meta_push_no_msg_prefix (void) -{ - ++no_prefix; -} - -void -meta_pop_no_msg_prefix (void) -{ - g_return_if_fail (no_prefix > 0); - - --no_prefix; -} - -void -meta_exit (MetaExitCode code) -{ - - exit (code); -} - -gint -meta_unsigned_long_equal (gconstpointer v1, - gconstpointer v2) -{ - return *((const gulong*) v1) == *((const gulong*) v2); -} - -guint -meta_unsigned_long_hash (gconstpointer v) -{ - gulong val = * (const gulong *) v; - - /* I'm not sure this works so well. */ -#if GLIB_SIZEOF_LONG > 4 - return (guint) (val ^ (val >> 32)); -#else - return val; -#endif -} - -const char* -meta_gravity_to_string (int gravity) -{ - switch (gravity) - { - case NorthWestGravity: - return "NorthWestGravity"; - break; - case NorthGravity: - return "NorthGravity"; - break; - case NorthEastGravity: - return "NorthEastGravity"; - break; - case WestGravity: - return "WestGravity"; - break; - case CenterGravity: - return "CenterGravity"; - break; - case EastGravity: - return "EastGravity"; - break; - case SouthWestGravity: - return "SouthWestGravity"; - break; - case SouthGravity: - return "SouthGravity"; - break; - case SouthEastGravity: - return "SouthEastGravity"; - break; - case StaticGravity: - return "StaticGravity"; - break; - default: - return "NorthWestGravity"; - break; - } -} - -void -meta_show_dialog (const char *type, - const char *message, - const char *timeout, - const gint screen_number, - const char **columns, - const char **entries) -{ - GError *error = NULL; - char *screen_number_text = g_strdup_printf("%d", screen_number); - - /* - We want: - -zenity --display X --screen S --title Metacity --error --text "There was an error running <tt>terminal</tt>:\n\nYour computer is on fire." - ** with no pipes - -zenity --display X --screen S --title Metacity --question --text "<big><b><tt>%s</tt> is not responding.</b></big>\n\n<i>You may choose to wait a short while for it to continue or force the application to quit entirely.</i>" - -zenity --display X --screen S --title Metacity --list --timeout 240 --text "These windows do not support \"save current setup\" and will have to be restarted manually next time you log in." --column "Window" --column "Class" "Firefox" "foo" "Duke Nukem Forever" "bar" - */ - - const char **argvl; - int i=0; - GPid child_pid; - - argvl = g_malloc(sizeof (char*) * - (9 + (timeout?2:0)) - ); - - argvl[i++] = "zenity"; - argvl[i++] = type; - argvl[i++] = "--screen"; - argvl[i++] = screen_number_text; - argvl[i++] = "--title"; - /* Translators: This is the title used on dialog boxes */ - argvl[i++] = _("Metacity"); - argvl[i++] = "--text"; - argvl[i++] = message; - - if (timeout) - { - argvl[i++] = "--timeout"; - argvl[i++] = timeout; - } - - argvl[i] = NULL; - - g_spawn_async_with_pipes ( - "/", - (char**) argvl, /* ugh */ - NULL, - G_SPAWN_SEARCH_PATH, - NULL, NULL, - &child_pid, - NULL, NULL, NULL, - &error - ); - - g_free (argvl); - g_free (screen_number_text); - - if (error) - { - meta_warning ("%s\n", error->message); - g_error_free (error); - } -} - -/* eof util.c */ - diff --git a/src/core/window-private.h b/src/core/window-private.h deleted file mode 100644 index f5547122..00000000 --- a/src/core/window-private.h +++ /dev/null @@ -1,632 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file window-private.h Windows which Metacity manages - * - * Managing X windows. - * This file contains methods on this class which are available to - * routines in core but not outside it. (See window.h for the routines - * which the rest of the world is allowed to use.) - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WINDOW_PRIVATE_H -#define META_WINDOW_PRIVATE_H - -#include <config.h> -#include "window.h" -#include "screen-private.h" -#include "util.h" -#include "stack.h" -#include "iconcache.h" -#include <X11/Xutil.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -typedef struct _MetaGroup MetaGroup; -typedef struct _MetaWindowQueue MetaWindowQueue; - -typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window, - void *data); - -typedef enum -{ - META_WINDOW_NORMAL, - META_WINDOW_DESKTOP, - META_WINDOW_DOCK, - META_WINDOW_DIALOG, - META_WINDOW_MODAL_DIALOG, - META_WINDOW_TOOLBAR, - META_WINDOW_MENU, - META_WINDOW_UTILITY, - META_WINDOW_SPLASHSCREEN -} MetaWindowType; - -typedef enum -{ - META_MAXIMIZE_HORIZONTAL = 1 << 0, - META_MAXIMIZE_VERTICAL = 1 << 1 -} MetaMaximizeFlags; - -typedef enum { - META_CLIENT_TYPE_UNKNOWN = 0, - META_CLIENT_TYPE_APPLICATION = 1, - META_CLIENT_TYPE_PAGER = 2, - META_CLIENT_TYPE_MAX_RECOGNIZED = 2 -} MetaClientType; - -typedef enum { - META_QUEUE_CALC_SHOWING = 1 << 0, - META_QUEUE_MOVE_RESIZE = 1 << 1, - META_QUEUE_UPDATE_ICON = 1 << 2, -} MetaQueueType; - -#define NUMBER_OF_QUEUES 3 - -struct _MetaWindow -{ - MetaDisplay *display; - MetaScreen *screen; - MetaWorkspace *workspace; - Window xwindow; - /* may be NULL! not all windows get decorated */ - MetaFrame *frame; - int depth; - Visual *xvisual; - Colormap colormap; - char *desc; /* used in debug spew */ - char *title; - - char *icon_name; - GdkPixbuf *icon; - GdkPixbuf *mini_icon; - MetaIconCache icon_cache; - Pixmap wm_hints_pixmap; - Pixmap wm_hints_mask; - - MetaWindowType type; - Atom type_atom; - - /* NOTE these five are not in UTF-8, we just treat them as random - * binary data - */ - char *res_class; - char *res_name; - char *role; - char *sm_client_id; - char *wm_client_machine; - char *startup_id; - - int net_wm_pid; - - Window xtransient_for; - Window xgroup_leader; - Window xclient_leader; - - /* Initial workspace property */ - int initial_workspace; - - /* Initial timestamp property */ - guint32 initial_timestamp; - - /* Whether we're maximized */ - guint maximized_horizontally : 1; - guint maximized_vertically : 1; - - /* Whether we have to maximize/minimize after placement */ - guint maximize_horizontally_after_placement : 1; - guint maximize_vertically_after_placement : 1; - guint minimize_after_placement : 1; - - /* Whether we're shaded */ - guint shaded : 1; - - /* Whether we're fullscreen */ - guint fullscreen : 1; - - /* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has - * been overridden (via a client message), the window will cover the union of - * these monitors. If not, this is the single monitor which the window's - * origin is on. */ - long fullscreen_monitors[4]; - - /* Whether we're trying to constrain the window to be fully onscreen */ - guint require_fully_onscreen : 1; - - /* Whether we're trying to constrain the window to be on a single xinerama */ - guint require_on_single_xinerama : 1; - - /* Whether we're trying to constrain the window's titlebar to be onscreen */ - guint require_titlebar_visible : 1; - - /* Whether we're sticky in the multi-workspace sense - * (vs. the not-scroll-with-viewport sense, we don't - * have no stupid viewports) - */ - guint on_all_workspaces : 1; - - /* Minimize is the state controlled by the minimize button */ - guint minimized : 1; - guint was_minimized : 1; - guint tab_unminimized : 1; - - /* Whether the window is mapped; actual server-side state - * see also unmaps_pending - */ - guint mapped : 1; - - /* Iconic is the state in WM_STATE; happens for workspaces/shading - * in addition to minimize - */ - guint iconic : 1; - /* initially_iconic is the WM_HINTS setting when we first manage - * the window. It's taken to mean initially minimized. - */ - guint initially_iconic : 1; - - /* whether an initial workspace was explicitly set */ - guint initial_workspace_set : 1; - - /* whether an initial timestamp was explicitly set */ - guint initial_timestamp_set : 1; - - /* whether net_wm_user_time has been set yet */ - guint net_wm_user_time_set : 1; - - /* These are the flags from WM_PROTOCOLS */ - guint take_focus : 1; - guint delete_window : 1; - guint net_wm_ping : 1; - /* Globally active / No input */ - guint input : 1; - - /* MWM hints about features of window */ - guint mwm_decorated : 1; - guint mwm_border_only : 1; - guint mwm_has_close_func : 1; - guint mwm_has_minimize_func : 1; - guint mwm_has_maximize_func : 1; - guint mwm_has_move_func : 1; - guint mwm_has_resize_func : 1; - - /* Computed features of window */ - guint decorated : 1; - guint border_only : 1; - guint always_sticky : 1; - guint has_close_func : 1; - guint has_minimize_func : 1; - guint has_maximize_func : 1; - guint has_shade_func : 1; - guint has_move_func : 1; - guint has_resize_func : 1; - guint has_fullscreen_func : 1; - - /* Weird "_NET_WM_STATE_MODAL" flag */ - guint wm_state_modal : 1; - - /* TRUE if the client forced these on */ - guint wm_state_skip_taskbar : 1; - guint wm_state_skip_pager : 1; - - /* Computed whether to skip taskbar or not */ - guint skip_taskbar : 1; - guint skip_pager : 1; - - /* TRUE if client set these */ - guint wm_state_above : 1; - guint wm_state_below : 1; - - /* EWHH demands attention flag */ - guint wm_state_demands_attention : 1; - - /* this flag tracks receipt of focus_in focus_out and - * determines whether we draw the focus - */ - guint has_focus : 1; - - /* Have we placed this window? */ - guint placed : 1; - - /* Is this not a transient of the focus window which is being denied focus? */ - guint denied_focus_and_not_transient : 1; - - /* Has this window not ever been shown yet? */ - guint showing_for_first_time : 1; - - /* Are we in meta_window_free()? */ - guint unmanaging : 1; - - /* Are we in meta_window_new()? */ - guint constructing : 1; - - /* Are we in the various queues? (Bitfield: see META_WINDOW_IS_IN_QUEUE) */ - guint is_in_queues : NUMBER_OF_QUEUES; - - /* Used by keybindings.c */ - guint keys_grabbed : 1; /* normal keybindings grabbed */ - guint grab_on_frame : 1; /* grabs are on the frame */ - guint all_keys_grabbed : 1; /* AnyKey grabbed */ - - /* Set if the reason for unmanaging the window is that - * it was withdrawn - */ - guint withdrawn : 1; - - /* TRUE if constrain_position should calc placement. - * only relevant if !window->placed - */ - guint calc_placement : 1; - - /* Transient parent is a root window */ - guint transient_parent_is_root_window : 1; - - /* Info on which props we got our attributes from */ - guint using_net_wm_name : 1; /* vs. plain wm_name */ - guint using_net_wm_visible_name : 1; /* tracked so we can clear it */ - guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */ - guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */ - - /* has a shape mask */ - guint has_shape : 1; - - /* icon props have changed */ - guint need_reread_icon : 1; - - /* if TRUE, window was maximized at start of current grab op */ - guint shaken_loose : 1; - - /* if TRUE we have a grab on the focus click buttons */ - guint have_focus_click_grab : 1; - - /* if TRUE, application is buggy and SYNC resizing is turned off */ - guint disable_sync : 1; - - /* Note: can be NULL */ - GSList *struts; - -#ifdef HAVE_XSYNC - /* XSync update counter */ - XSyncCounter sync_request_counter; - guint sync_request_serial; - GTimeVal sync_request_time; -#endif - - /* Number of UnmapNotify that are caused by us, if - * we get UnmapNotify with none pending then the client - * is withdrawing the window. - */ - int unmaps_pending; - - /* set to the most recent user-interaction event timestamp that we - know about for this window */ - guint32 net_wm_user_time; - - /* window that gets updated net_wm_user_time values */ - Window user_time_window; - - /* The size we set the window to last (i.e. what we believe - * to be its actual size on the server). The x, y are - * the actual server-side x,y so are relative to the frame - * (meaning that they just hold the frame width and height) - * or the root window (meaning they specify the location - * of the top left of the inner window) as appropriate. - */ - MetaRectangle rect; - - /* The geometry to restore when we unmaximize. The position is in - * root window coords, even if there's a frame, which contrasts with - * window->rect above. Note that this gives the position and size - * of the client window (i.e. ignoring the frame). - */ - MetaRectangle saved_rect; - - /* This is the geometry the window had after the last user-initiated - * move/resize operations. We use this whenever we are moving the - * implicitly (for example, if we move to avoid a panel, we can snap - * back to this position if the panel moves again). Note that this - * gives the position and size of the client window (i.e. ignoring - * the frame). - * - * Position valid if user_has_moved, size valid if user_has_resized - * - * Position always in root coords, unlike window->rect. - */ - MetaRectangle user_rect; - - /* Requested geometry */ - int border_width; - /* x/y/w/h here get filled with ConfigureRequest values */ - XSizeHints size_hints; - - /* Managed by stack.c */ - MetaStackLayer layer; - int stack_position; /* see comment in stack.h */ - - /* Current dialog open for this window */ - int dialog_pid; - int dialog_pipe; - - /* maintained by group.c */ - MetaGroup *group; -}; - -/* These differ from window->has_foo_func in that they consider - * the dynamic window state such as "maximized", not just the - * window's type - */ -#define META_WINDOW_MAXIMIZED(w) ((w)->maximized_horizontally && \ - (w)->maximized_vertically) -#define META_WINDOW_MAXIMIZED_VERTICALLY(w) ((w)->maximized_vertically) -#define META_WINDOW_MAXIMIZED_HORIZONTALLY(w) ((w)->maximized_horizontally) -#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen) -#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !(w)->fullscreen && !(w)->shaded) -#define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \ - (((w)->size_hints.min_width < (w)->size_hints.max_width) || \ - ((w)->size_hints.min_height < (w)->size_hints.max_height))) -#define META_WINDOW_ALLOWS_HORIZONTAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && (w)->size_hints.min_width < (w)->size_hints.max_width) -#define META_WINDOW_ALLOWS_VERTICAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && (w)->size_hints.min_height < (w)->size_hints.max_height) - -MetaWindow* meta_window_new (MetaDisplay *display, - Window xwindow, - gboolean must_be_viewable); -MetaWindow* meta_window_new_with_attrs (MetaDisplay *display, - Window xwindow, - gboolean must_be_viewable, - XWindowAttributes *attrs); -void meta_window_free (MetaWindow *window, - guint32 timestamp); -void meta_window_calc_showing (MetaWindow *window); -void meta_window_queue (MetaWindow *window, - guint queuebits); -void meta_window_minimize (MetaWindow *window); -void meta_window_unminimize (MetaWindow *window); -void meta_window_maximize (MetaWindow *window, - MetaMaximizeFlags directions); -void meta_window_maximize_internal (MetaWindow *window, - MetaMaximizeFlags directions, - MetaRectangle *saved_rect); -void meta_window_unmaximize (MetaWindow *window, - MetaMaximizeFlags directions); -void meta_window_make_above (MetaWindow *window); -void meta_window_unmake_above (MetaWindow *window); -void meta_window_shade (MetaWindow *window, - guint32 timestamp); -void meta_window_unshade (MetaWindow *window, - guint32 timestamp); -void meta_window_change_workspace (MetaWindow *window, - MetaWorkspace *workspace); -void meta_window_stick (MetaWindow *window); -void meta_window_unstick (MetaWindow *window); - -void meta_window_activate (MetaWindow *window, - guint32 current_time); -void meta_window_activate_with_workspace (MetaWindow *window, - guint32 current_time, - MetaWorkspace *workspace); -void meta_window_make_fullscreen_internal (MetaWindow *window); -void meta_window_make_fullscreen (MetaWindow *window); -void meta_window_unmake_fullscreen (MetaWindow *window); -void meta_window_update_fullscreen_monitors (MetaWindow *window, - unsigned long top, - unsigned long bottom, - unsigned long left, - unsigned long right); - -/* args to move are window pos, not frame pos */ -void meta_window_move (MetaWindow *window, - gboolean user_op, - int root_x_nw, - int root_y_nw); -void meta_window_resize (MetaWindow *window, - gboolean user_op, - int w, - int h); -void meta_window_move_resize (MetaWindow *window, - gboolean user_op, - int root_x_nw, - int root_y_nw, - int w, - int h); -void meta_window_resize_with_gravity (MetaWindow *window, - gboolean user_op, - int w, - int h, - int gravity); - - -/* Return whether the window would be showing if we were on its workspace */ -gboolean meta_window_showing_on_its_workspace (MetaWindow *window); - -/* Return whether the window should be currently mapped */ -gboolean meta_window_should_be_showing (MetaWindow *window); - -/* See warning in window.c about this function */ -gboolean __window_is_terminal (MetaWindow *window); - -void meta_window_update_struts (MetaWindow *window); - -/* this gets root coords */ -void meta_window_get_position (MetaWindow *window, - int *x, - int *y); - -/* Gets root coords for x, y, width & height of client window; uses - * meta_window_get_position for x & y. - */ -void meta_window_get_client_root_coords (MetaWindow *window, - MetaRectangle *rect); - -/* gets position we need to set to stay in current position, - * assuming position will be gravity-compensated. i.e. - * this is the position a client would send in a configure - * request. - */ -void meta_window_get_gravity_position (MetaWindow *window, - int gravity, - int *x, - int *y); -/* Get geometry for saving in the session; x/y are gravity - * position, and w/h are in resize inc above the base size. - */ -void meta_window_get_geometry (MetaWindow *window, - int *x, - int *y, - int *width, - int *height); -void meta_window_get_outer_rect (const MetaWindow *window, - MetaRectangle *rect); -void meta_window_get_xor_rect (MetaWindow *window, - const MetaRectangle *grab_wireframe_rect, - MetaRectangle *xor_rect); -void meta_window_begin_wireframe (MetaWindow *window); -void meta_window_update_wireframe (MetaWindow *window, - int x, - int y, - int width, - int height); -void meta_window_end_wireframe (MetaWindow *window); - -void meta_window_delete (MetaWindow *window, - guint32 timestamp); -void meta_window_kill (MetaWindow *window); -void meta_window_focus (MetaWindow *window, - guint32 timestamp); -void meta_window_raise (MetaWindow *window); -void meta_window_lower (MetaWindow *window); - -void meta_window_update_unfocused_button_grabs (MetaWindow *window); - -/* Sends a client message */ -void meta_window_send_icccm_message (MetaWindow *window, - Atom atom, - guint32 timestamp); - - -void meta_window_move_resize_request(MetaWindow *window, - guint value_mask, - int gravity, - int x, - int y, - int width, - int height); -gboolean meta_window_configure_request (MetaWindow *window, - XEvent *event); -gboolean meta_window_property_notify (MetaWindow *window, - XEvent *event); -gboolean meta_window_client_message (MetaWindow *window, - XEvent *event); -gboolean meta_window_notify_focus (MetaWindow *window, - XEvent *event); - -void meta_window_set_current_workspace_hint (MetaWindow *window); - -unsigned long meta_window_get_net_wm_desktop (MetaWindow *window); - -void meta_window_show_menu (MetaWindow *window, - int root_x, - int root_y, - int button, - guint32 timestamp); - -gboolean meta_window_titlebar_is_onscreen (MetaWindow *window); -void meta_window_shove_titlebar_onscreen (MetaWindow *window); - -void meta_window_set_gravity (MetaWindow *window, - int gravity); - -void meta_window_handle_mouse_grab_op_event (MetaWindow *window, - XEvent *event); - -GList* meta_window_get_workspaces (MetaWindow *window); - -gboolean meta_window_located_on_workspace (MetaWindow *window, - MetaWorkspace *workspace); - -void meta_window_get_work_area_current_xinerama (MetaWindow *window, - MetaRectangle *area); -void meta_window_get_work_area_for_xinerama (MetaWindow *window, - int which_xinerama, - MetaRectangle *area); -void meta_window_get_work_area_all_xineramas (MetaWindow *window, - MetaRectangle *area); - - -gboolean meta_window_same_application (MetaWindow *window, - MetaWindow *other_window); - -#define META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE(w) \ - ((w)->type != META_WINDOW_DOCK && (w)->type != META_WINDOW_DESKTOP) -#define META_WINDOW_IN_NORMAL_TAB_CHAIN(w) \ - (((w)->input || (w)->take_focus ) && META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w) && (!(w)->skip_taskbar)) -#define META_WINDOW_IN_DOCK_TAB_CHAIN(w) \ - (((w)->input || (w)->take_focus) && (! META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w) || (w)->skip_taskbar)) -#define META_WINDOW_IN_GROUP_TAB_CHAIN(w, g) \ - (((w)->input || (w)->take_focus) && (!g || meta_window_get_group(w)==g)) - -void meta_window_refresh_resize_popup (MetaWindow *window); - -void meta_window_free_delete_dialog (MetaWindow *window); - -void meta_window_foreach_transient (MetaWindow *window, - MetaWindowForeachFunc func, - void *data); -gboolean meta_window_is_ancestor_of_transient (MetaWindow *window, - MetaWindow *transient); -void meta_window_foreach_ancestor (MetaWindow *window, - MetaWindowForeachFunc func, - void *data); -MetaWindow* meta_window_find_root_ancestor (MetaWindow *window); - - -void meta_window_begin_grab_op (MetaWindow *window, - MetaGrabOp op, - gboolean frame_action, - guint32 timestamp); - -void meta_window_update_keyboard_resize (MetaWindow *window, - gboolean update_cursor); -void meta_window_update_keyboard_move (MetaWindow *window); - -void meta_window_update_layer (MetaWindow *window); - -gboolean meta_window_get_icon_geometry (MetaWindow *window, - MetaRectangle *rect); - -const char* meta_window_get_startup_id (MetaWindow *window); - -void meta_window_recalc_features (MetaWindow *window); -void meta_window_recalc_window_type (MetaWindow *window); - -void meta_window_stack_just_below (MetaWindow *window, - MetaWindow *below_this_one); - -void meta_window_set_user_time (MetaWindow *window, - guint32 timestamp); - -void meta_window_set_demands_attention (MetaWindow *window); - -void meta_window_unset_demands_attention (MetaWindow *window); - -void meta_window_update_icon_now (MetaWindow *window); - -#endif diff --git a/src/core/window-props.c b/src/core/window-props.c deleted file mode 100644 index 59feadf7..00000000 --- a/src/core/window-props.c +++ /dev/null @@ -1,1636 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file window-props.c MetaWindow property handling - * - * A system which can inspect sets of properties of given windows - * and take appropriate action given their values. - * - * Note that all the meta_window_reload_propert* functions require a - * round trip to the server. - * - * \bug Not all the properties have moved over from their original - * handler in window.c yet. - */ - -/* - * Copyright (C) 2001, 2002, 2003 Red Hat, Inc. - * Copyright (C) 2004, 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#define _GNU_SOURCE -#define _SVID_SOURCE /* for gethostname() */ - -#include <config.h> -#include "window-props.h" -#include "errors.h" -#include "xprops.h" -#include "frame-private.h" -#include "group.h" -#include <X11/Xatom.h> -#include <unistd.h> -#include <string.h> -#ifndef HOST_NAME_MAX -/* Solaris headers apparently don't define this so do so manually; #326745 */ -#define HOST_NAME_MAX 255 -#endif - -typedef void (* InitValueFunc) (MetaDisplay *display, - Atom property, - MetaPropValue *value); -typedef void (* ReloadValueFunc) (MetaWindow *window, - MetaPropValue *value); - -struct _MetaWindowPropHooks -{ - Atom property; - InitValueFunc init_func; - ReloadValueFunc reload_func; -}; - -static void init_prop_value (MetaDisplay *display, - Atom property, - MetaPropValue *value); -static void reload_prop_value (MetaWindow *window, - MetaPropValue *value); -static MetaWindowPropHooks* find_hooks (MetaDisplay *display, - Atom property); - - -void -meta_window_reload_property (MetaWindow *window, - Atom property) -{ - meta_window_reload_properties (window, &property, 1); -} - -void -meta_window_reload_properties (MetaWindow *window, - const Atom *properties, - int n_properties) -{ - meta_window_reload_properties_from_xwindow (window, - window->xwindow, - properties, - n_properties); -} - -void -meta_window_reload_property_from_xwindow (MetaWindow *window, - Window xwindow, - Atom property) -{ - meta_window_reload_properties_from_xwindow (window, xwindow, &property, 1); -} - -void -meta_window_reload_properties_from_xwindow (MetaWindow *window, - Window xwindow, - const Atom *properties, - int n_properties) -{ - int i; - MetaPropValue *values; - - g_return_if_fail (properties != NULL); - g_return_if_fail (n_properties > 0); - - values = g_new0 (MetaPropValue, n_properties); - - i = 0; - while (i < n_properties) - { - init_prop_value (window->display, properties[i], &values[i]); - ++i; - } - - meta_prop_get_values (window->display, xwindow, - values, n_properties); - - i = 0; - while (i < n_properties) - { - reload_prop_value (window, &values[i]); - - ++i; - } - - meta_prop_free_values (values, n_properties); - - g_free (values); -} - -/* Fill in the MetaPropValue used to get the value of "property" */ -static void -init_prop_value (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - MetaWindowPropHooks *hooks; - - value->type = META_PROP_VALUE_INVALID; - value->atom = None; - - hooks = find_hooks (display, property); - if (hooks && hooks->init_func != NULL) - (* hooks->init_func) (display, property, value); -} - -static void -reload_prop_value (MetaWindow *window, - MetaPropValue *value) -{ - MetaWindowPropHooks *hooks; - - hooks = find_hooks (window->display, value->atom); - if (hooks && hooks->reload_func != NULL) - (* hooks->reload_func) (window, value); -} - -static void -init_wm_client_machine (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_STRING; - value->atom = display->atom_WM_CLIENT_MACHINE; -} - -static void -reload_wm_client_machine (MetaWindow *window, - MetaPropValue *value) -{ - g_free (window->wm_client_machine); - window->wm_client_machine = NULL; - - if (value->type != META_PROP_VALUE_INVALID) - window->wm_client_machine = g_strdup (value->v.str); - - meta_verbose ("Window has client machine \"%s\"\n", - window->wm_client_machine ? window->wm_client_machine : "unset"); -} - -static void -init_net_wm_pid (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_CARDINAL; - value->atom = display->atom__NET_WM_PID; -} - -static void -reload_net_wm_pid (MetaWindow *window, - MetaPropValue *value) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - gulong cardinal = (int) value->v.cardinal; - - if (cardinal <= 0) - meta_warning (_("Application set a bogus _NET_WM_PID %lu\n"), - cardinal); - else - { - window->net_wm_pid = cardinal; - meta_verbose ("Window has _NET_WM_PID %d\n", - window->net_wm_pid); - } - } -} - -static void -init_net_wm_user_time (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_CARDINAL; - value->atom = display->atom__NET_WM_USER_TIME; -} - -static void -reload_net_wm_user_time (MetaWindow *window, - MetaPropValue *value) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - gulong cardinal = value->v.cardinal; - meta_window_set_user_time (window, cardinal); - } -} - -static void -init_net_wm_user_time_window (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_WINDOW; - value->atom = display->atom__NET_WM_USER_TIME_WINDOW; -} - -static void -reload_net_wm_user_time_window (MetaWindow *window, - MetaPropValue *value) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - /* Unregister old NET_WM_USER_TIME_WINDOW */ - if (window->user_time_window != None) - { - /* See the comment to the meta_display_register_x_window call below. */ - meta_display_unregister_x_window (window->display, - window->user_time_window); - /* Don't get events on not-managed windows */ - XSelectInput (window->display->xdisplay, - window->user_time_window, - NoEventMask); - } - - - /* Obtain the new NET_WM_USER_TIME_WINDOW and register it */ - window->user_time_window = value->v.xwindow; - if (window->user_time_window != None) - { - /* Kind of a hack; display.c:event_callback() ignores events - * for unknown windows. We make window->user_time_window - * known by registering it with window (despite the fact - * that window->xwindow is already registered with window). - * This basically means that property notifies to either the - * window->user_time_window or window->xwindow will be - * treated identically and will result in functions for - * window being called to update it. Maybe we should ignore - * any property notifies to window->user_time_window other - * than atom__NET_WM_USER_TIME ones, but I just don't care - * and it's not specified in the spec anyway. - */ - meta_display_register_x_window (window->display, - &window->user_time_window, - window); - /* Just listen for property notify events */ - XSelectInput (window->display->xdisplay, - window->user_time_window, - PropertyChangeMask); - - /* Manually load the _NET_WM_USER_TIME field from the given window - * at this time as well. If the user_time_window ever broadens in - * scope, we'll probably want to load all relevant properties here. - */ - meta_window_reload_property_from_xwindow ( - window, - window->user_time_window, - window->display->atom__NET_WM_USER_TIME); - } - } -} - -#define MAX_TITLE_LENGTH 512 - -/** - * Called by set_window_title and set_icon_title to set the value of - * *target to title. It required and atom is set, it will update the - * appropriate property. - * - * Returns TRUE if a new title was set. - */ -static gboolean -set_title_text (MetaWindow *window, - gboolean previous_was_modified, - const char *title, - Atom atom, - char **target) -{ - char hostname[HOST_NAME_MAX + 1]; - gboolean modified = FALSE; - - if (!target) - return FALSE; - - g_free (*target); - - if (!title) - *target = g_strdup (""); - else if (g_utf8_strlen (title, MAX_TITLE_LENGTH + 1) > MAX_TITLE_LENGTH) - { - *target = meta_g_utf8_strndup (title, MAX_TITLE_LENGTH); - modified = TRUE; - } - /* if WM_CLIENT_MACHINE indicates this machine is on a remote host - * lets place that hostname in the title */ - else if (window->wm_client_machine && - !gethostname (hostname, HOST_NAME_MAX + 1) && - strcmp (hostname, window->wm_client_machine)) - { - *target = g_strdup_printf (_("%s (on %s)"), - title, window->wm_client_machine); - modified = TRUE; - } - else - *target = g_strdup (title); - - if (modified && atom != None) - meta_prop_set_utf8_string_hint (window->display, - window->xwindow, - atom, *target); - - /* Bug 330671 -- Don't forget to clear _NET_WM_VISIBLE_(ICON_)NAME */ - if (!modified && previous_was_modified) - { - meta_error_trap_push (window->display); - XDeleteProperty (window->display->xdisplay, - window->xwindow, - atom); - meta_error_trap_pop (window->display, FALSE); - } - - return modified; -} - -static void -set_window_title (MetaWindow *window, - const char *title) -{ - char *str; - - gboolean modified = - set_title_text (window, - window->using_net_wm_visible_name, - title, - window->display->atom__NET_WM_VISIBLE_NAME, - &window->title); - window->using_net_wm_visible_name = modified; - - /* strndup is a hack since GNU libc has broken %.10s */ - str = g_strndup (window->title, 10); - g_free (window->desc); - window->desc = g_strdup_printf ("0x%lx (%s)", window->xwindow, str); - g_free (str); - - if (window->frame) - meta_ui_set_frame_title (window->screen->ui, - window->frame->xwindow, - window->title); -} - -static void -init_net_wm_name (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_UTF8; - value->atom = display->atom__NET_WM_NAME; -} - -static void -reload_net_wm_name (MetaWindow *window, - MetaPropValue *value) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - set_window_title (window, value->v.str); - window->using_net_wm_name = TRUE; - - meta_verbose ("Using _NET_WM_NAME for new title of %s: \"%s\"\n", - window->desc, window->title); - } - else - { - set_window_title (window, NULL); - window->using_net_wm_name = FALSE; - } -} - - -static void -init_wm_name (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_TEXT_PROPERTY; - value->atom = XA_WM_NAME; -} - -static void -reload_wm_name (MetaWindow *window, - MetaPropValue *value) -{ - if (window->using_net_wm_name) - { - meta_verbose ("Ignoring WM_NAME \"%s\" as _NET_WM_NAME is set\n", - value->v.str); - return; - } - - if (value->type != META_PROP_VALUE_INVALID) - { - set_window_title (window, value->v.str); - - meta_verbose ("Using WM_NAME for new title of %s: \"%s\"\n", - window->desc, window->title); - } - else - { - set_window_title (window, NULL); - } -} - -static void -set_icon_title (MetaWindow *window, - const char *title) -{ - gboolean modified = - set_title_text (window, - window->using_net_wm_visible_icon_name, - title, - window->display->atom__NET_WM_VISIBLE_ICON_NAME, - &window->icon_name); - window->using_net_wm_visible_icon_name = modified; -} - -static void -init_net_wm_icon_name (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_UTF8; - value->atom = display->atom__NET_WM_ICON_NAME; -} - -static void -reload_net_wm_icon_name (MetaWindow *window, - MetaPropValue *value) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - set_icon_title (window, value->v.str); - window->using_net_wm_icon_name = TRUE; - - meta_verbose ("Using _NET_WM_ICON_NAME for new title of %s: \"%s\"\n", - window->desc, window->title); - } - else - { - set_icon_title (window, NULL); - window->using_net_wm_icon_name = FALSE; - } -} - - -static void -init_wm_icon_name (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_TEXT_PROPERTY; - value->atom = XA_WM_ICON_NAME; -} - -static void -reload_wm_icon_name (MetaWindow *window, - MetaPropValue *value) -{ - if (window->using_net_wm_icon_name) - { - meta_verbose ("Ignoring WM_ICON_NAME \"%s\" as _NET_WM_ICON_NAME is set\n", - value->v.str); - return; - } - - if (value->type != META_PROP_VALUE_INVALID) - { - set_icon_title (window, value->v.str); - - meta_verbose ("Using WM_ICON_NAME for new title of %s: \"%s\"\n", - window->desc, window->title); - } - else - { - set_icon_title (window, NULL); - } -} - -static void -init_net_wm_state (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_ATOM_LIST; - value->atom = display->atom__NET_WM_STATE; -} - -static void -reload_net_wm_state (MetaWindow *window, - MetaPropValue *value) -{ - int i; - - /* We know this is only an initial window creation, - * clients don't change the property. - */ - - window->shaded = FALSE; - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; - window->wm_state_modal = FALSE; - window->wm_state_skip_taskbar = FALSE; - window->wm_state_skip_pager = FALSE; - window->wm_state_above = FALSE; - window->wm_state_below = FALSE; - window->wm_state_demands_attention = FALSE; - - if (value->type == META_PROP_VALUE_INVALID) - return; - - i = 0; - while (i < value->v.atom_list.n_atoms) - { - if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SHADED) - window->shaded = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_MAXIMIZED_HORZ) - window->maximize_horizontally_after_placement = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_MAXIMIZED_VERT) - window->maximize_vertically_after_placement = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_HIDDEN) - window->minimize_after_placement = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_MODAL) - window->wm_state_modal = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_TASKBAR) - window->wm_state_skip_taskbar = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_PAGER) - window->wm_state_skip_pager = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_FULLSCREEN) - window->fullscreen = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_ABOVE) - window->wm_state_above = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_BELOW) - window->wm_state_below = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_DEMANDS_ATTENTION) - window->wm_state_demands_attention = TRUE; - else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_STICKY) - window->on_all_workspaces = TRUE; - - ++i; - } - - meta_verbose ("Reloaded _NET_WM_STATE for %s\n", - window->desc); - - meta_window_recalc_window_type (window); -} - -static void -init_mwm_hints (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_MOTIF_HINTS; - value->atom = display->atom__MOTIF_WM_HINTS; -} - -static void -reload_mwm_hints (MetaWindow *window, - MetaPropValue *value) -{ - MotifWmHints *hints; - - window->mwm_decorated = TRUE; - window->mwm_border_only = FALSE; - window->mwm_has_close_func = TRUE; - window->mwm_has_minimize_func = TRUE; - window->mwm_has_maximize_func = TRUE; - window->mwm_has_move_func = TRUE; - window->mwm_has_resize_func = TRUE; - - if (value->type == META_PROP_VALUE_INVALID) - { - meta_verbose ("Window %s has no MWM hints\n", window->desc); - meta_window_recalc_features (window); - return; - } - - hints = value->v.motif_hints; - - /* We support those MWM hints deemed non-stupid */ - - meta_verbose ("Window %s has MWM hints\n", - window->desc); - - if (hints->flags & MWM_HINTS_DECORATIONS) - { - meta_verbose ("Window %s sets MWM_HINTS_DECORATIONS 0x%lx\n", - window->desc, hints->decorations); - - if (hints->decorations == 0) - window->mwm_decorated = FALSE; - /* some input methods use this */ - else if (hints->decorations == MWM_DECOR_BORDER) - window->mwm_border_only = TRUE; - } - else - meta_verbose ("Decorations flag unset\n"); - - if (hints->flags & MWM_HINTS_FUNCTIONS) - { - gboolean toggle_value; - - meta_verbose ("Window %s sets MWM_HINTS_FUNCTIONS 0x%lx\n", - window->desc, hints->functions); - - /* If _ALL is specified, then other flags indicate what to turn off; - * if ALL is not specified, flags are what to turn on. - * at least, I think so - */ - - if ((hints->functions & MWM_FUNC_ALL) == 0) - { - toggle_value = TRUE; - - meta_verbose ("Window %s disables all funcs then reenables some\n", - window->desc); - window->mwm_has_close_func = FALSE; - window->mwm_has_minimize_func = FALSE; - window->mwm_has_maximize_func = FALSE; - window->mwm_has_move_func = FALSE; - window->mwm_has_resize_func = FALSE; - } - else - { - meta_verbose ("Window %s enables all funcs then disables some\n", - window->desc); - toggle_value = FALSE; - } - - if ((hints->functions & MWM_FUNC_CLOSE) != 0) - { - meta_verbose ("Window %s toggles close via MWM hints\n", - window->desc); - window->mwm_has_close_func = toggle_value; - } - if ((hints->functions & MWM_FUNC_MINIMIZE) != 0) - { - meta_verbose ("Window %s toggles minimize via MWM hints\n", - window->desc); - window->mwm_has_minimize_func = toggle_value; - } - if ((hints->functions & MWM_FUNC_MAXIMIZE) != 0) - { - meta_verbose ("Window %s toggles maximize via MWM hints\n", - window->desc); - window->mwm_has_maximize_func = toggle_value; - } - if ((hints->functions & MWM_FUNC_MOVE) != 0) - { - meta_verbose ("Window %s toggles move via MWM hints\n", - window->desc); - window->mwm_has_move_func = toggle_value; - } - if ((hints->functions & MWM_FUNC_RESIZE) != 0) - { - meta_verbose ("Window %s toggles resize via MWM hints\n", - window->desc); - window->mwm_has_resize_func = toggle_value; - } - } - else - meta_verbose ("Functions flag unset\n"); - - meta_window_recalc_features (window); - - /* We do all this anyhow at the end of meta_window_new() */ - if (!window->constructing) - { - if (window->decorated) - meta_window_ensure_frame (window); - else - meta_window_destroy_frame (window); - - meta_window_queue (window, - META_QUEUE_MOVE_RESIZE | - /* because ensure/destroy frame may unmap: */ - META_QUEUE_CALC_SHOWING); - } -} - -static void -init_wm_class (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_CLASS_HINT; - value->atom = XA_WM_CLASS; -} - -static void -reload_wm_class (MetaWindow *window, - MetaPropValue *value) -{ - if (window->res_class) - g_free (window->res_class); - if (window->res_name) - g_free (window->res_name); - - window->res_class = NULL; - window->res_name = NULL; - - if (value->type != META_PROP_VALUE_INVALID) - { - if (value->v.class_hint.res_name) - window->res_name = g_strdup (value->v.class_hint.res_name); - - if (value->v.class_hint.res_class) - window->res_class = g_strdup (value->v.class_hint.res_class); - } - - meta_verbose ("Window %s class: '%s' name: '%s'\n", - window->desc, - window->res_class ? window->res_class : "none", - window->res_name ? window->res_name : "none"); -} - -static void -init_net_wm_desktop (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_CARDINAL; - value->atom = display->atom__NET_WM_DESKTOP; -} - -static void -reload_net_wm_desktop (MetaWindow *window, - MetaPropValue *value) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - window->initial_workspace_set = TRUE; - window->initial_workspace = value->v.cardinal; - meta_topic (META_DEBUG_PLACEMENT, - "Read initial workspace prop %d for %s\n", - window->initial_workspace, window->desc); - } -} - -static void -init_net_startup_id (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_UTF8; - value->atom = display->atom__NET_STARTUP_ID; -} - -static void -reload_net_startup_id (MetaWindow *window, - MetaPropValue *value) -{ - guint32 timestamp = window->net_wm_user_time; - MetaWorkspace *workspace = NULL; - - g_free (window->startup_id); - - if (value->type != META_PROP_VALUE_INVALID) - window->startup_id = g_strdup (value->v.str); - else - window->startup_id = NULL; - - /* Update timestamp and workspace on a running window */ - if (!window->constructing) - { - window->initial_timestamp_set = 0; - window->initial_workspace_set = 0; - - if (meta_screen_apply_startup_properties (window->screen, window)) - { - - if (window->initial_timestamp_set) - timestamp = window->initial_timestamp; - if (window->initial_workspace_set) - workspace = meta_screen_get_workspace_by_index (window->screen, window->initial_workspace); - - meta_window_activate_with_workspace (window, timestamp, workspace); - } - } - - meta_verbose ("New _NET_STARTUP_ID \"%s\" for %s\n", - window->startup_id ? window->startup_id : "unset", - window->desc); -} - -static void -init_update_counter (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_SYNC_COUNTER; - value->atom = display->atom__NET_WM_SYNC_REQUEST_COUNTER; -} - -static void -reload_update_counter (MetaWindow *window, - MetaPropValue *value) -{ - if (value->type != META_PROP_VALUE_INVALID) - { -#ifdef HAVE_XSYNC - XSyncCounter counter = value->v.xcounter; - - window->sync_request_counter = counter; - meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx\n", - window->sync_request_counter); -#endif - } -} - - -static void -init_normal_hints (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_SIZE_HINTS; - value->atom = XA_WM_NORMAL_HINTS; -} - - -#define FLAG_TOGGLED_ON(old,new,flag) \ - (((old)->flags & (flag)) == 0 && \ - ((new)->flags & (flag)) != 0) - -#define FLAG_TOGGLED_OFF(old,new,flag) \ - (((old)->flags & (flag)) != 0 && \ - ((new)->flags & (flag)) == 0) - -#define FLAG_CHANGED(old,new,flag) \ - (FLAG_TOGGLED_ON(old,new,flag) || FLAG_TOGGLED_OFF(old,new,flag)) - -static void -spew_size_hints_differences (const XSizeHints *old, - const XSizeHints *new) -{ - if (FLAG_CHANGED (old, new, USPosition)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USPosition now %s\n", - FLAG_TOGGLED_ON (old, new, USPosition) ? "set" : "unset"); - if (FLAG_CHANGED (old, new, USSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USSize now %s\n", - FLAG_TOGGLED_ON (old, new, USSize) ? "set" : "unset"); - if (FLAG_CHANGED (old, new, PPosition)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PPosition now %s\n", - FLAG_TOGGLED_ON (old, new, PPosition) ? "set" : "unset"); - if (FLAG_CHANGED (old, new, PSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PSize now %s\n", - FLAG_TOGGLED_ON (old, new, PSize) ? "set" : "unset"); - if (FLAG_CHANGED (old, new, PMinSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMinSize now %s (%d x %d -> %d x %d)\n", - FLAG_TOGGLED_ON (old, new, PMinSize) ? "set" : "unset", - old->min_width, old->min_height, - new->min_width, new->min_height); - if (FLAG_CHANGED (old, new, PMaxSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMaxSize now %s (%d x %d -> %d x %d)\n", - FLAG_TOGGLED_ON (old, new, PMaxSize) ? "set" : "unset", - old->max_width, old->max_height, - new->max_width, new->max_height); - if (FLAG_CHANGED (old, new, PResizeInc)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PResizeInc now %s (width_inc %d -> %d height_inc %d -> %d)\n", - FLAG_TOGGLED_ON (old, new, PResizeInc) ? "set" : "unset", - old->width_inc, new->width_inc, - old->height_inc, new->height_inc); - if (FLAG_CHANGED (old, new, PAspect)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PAspect now %s (min %d/%d -> %d/%d max %d/%d -> %d/%d)\n", - FLAG_TOGGLED_ON (old, new, PAspect) ? "set" : "unset", - old->min_aspect.x, old->min_aspect.y, - new->min_aspect.x, new->min_aspect.y, - old->max_aspect.x, old->max_aspect.y, - new->max_aspect.x, new->max_aspect.y); - if (FLAG_CHANGED (old, new, PBaseSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PBaseSize now %s (%d x %d -> %d x %d)\n", - FLAG_TOGGLED_ON (old, new, PBaseSize) ? "set" : "unset", - old->base_width, old->base_height, - new->base_width, new->base_height); - if (FLAG_CHANGED (old, new, PWinGravity)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PWinGravity now %s (%d -> %d)\n", - FLAG_TOGGLED_ON (old, new, PWinGravity) ? "set" : "unset", - old->win_gravity, new->win_gravity); -} - -void -meta_set_normal_hints (MetaWindow *window, - XSizeHints *hints) -{ - int x, y, w, h; - double minr, maxr; - /* Some convenience vars */ - int minw, minh, maxw, maxh; /* min/max width/height */ - int basew, baseh, winc, hinc; /* base width/height, width/height increment */ - - /* Save the last ConfigureRequest, which we put here. - * Values here set in the hints are supposed to - * be ignored. - */ - x = window->size_hints.x; - y = window->size_hints.y; - w = window->size_hints.width; - h = window->size_hints.height; - - /* as far as I can tell, value->v.size_hints.flags is just to - * check whether we had old-style normal hints without gravity, - * base size as returned by XGetNormalHints(), so we don't - * really use it as we fixup window->size_hints to have those - * fields if they're missing. - */ - - /* - * When the window is first created, NULL hints will - * be passed in which will initialize all of the fields - * as if flags were zero - */ - if (hints) - window->size_hints = *hints; - else - window->size_hints.flags = 0; - - /* Put back saved ConfigureRequest. */ - window->size_hints.x = x; - window->size_hints.y = y; - window->size_hints.width = w; - window->size_hints.height = h; - - /* Get base size hints */ - if (window->size_hints.flags & PBaseSize) - { - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets base size %d x %d\n", - window->desc, - window->size_hints.base_width, - window->size_hints.base_height); - } - else if (window->size_hints.flags & PMinSize) - { - window->size_hints.base_width = window->size_hints.min_width; - window->size_hints.base_height = window->size_hints.min_height; - } - else - { - window->size_hints.base_width = 0; - window->size_hints.base_height = 0; - } - window->size_hints.flags |= PBaseSize; - - /* Get min size hints */ - if (window->size_hints.flags & PMinSize) - { - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min size %d x %d\n", - window->desc, - window->size_hints.min_width, - window->size_hints.min_height); - } - else if (window->size_hints.flags & PBaseSize) - { - window->size_hints.min_width = window->size_hints.base_width; - window->size_hints.min_height = window->size_hints.base_height; - } - else - { - window->size_hints.min_width = 0; - window->size_hints.min_height = 0; - } - window->size_hints.flags |= PMinSize; - - /* Get max size hints */ - if (window->size_hints.flags & PMaxSize) - { - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max size %d x %d\n", - window->desc, - window->size_hints.max_width, - window->size_hints.max_height); - } - else - { - window->size_hints.max_width = G_MAXINT; - window->size_hints.max_height = G_MAXINT; - window->size_hints.flags |= PMaxSize; - } - - /* Get resize increment hints */ - if (window->size_hints.flags & PResizeInc) - { - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets resize width inc: %d height inc: %d\n", - window->desc, - window->size_hints.width_inc, - window->size_hints.height_inc); - } - else - { - window->size_hints.width_inc = 1; - window->size_hints.height_inc = 1; - window->size_hints.flags |= PResizeInc; - } - - /* Get aspect ratio hints */ - if (window->size_hints.flags & PAspect) - { - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min_aspect: %d/%d max_aspect: %d/%d\n", - window->desc, - window->size_hints.min_aspect.x, - window->size_hints.min_aspect.y, - window->size_hints.max_aspect.x, - window->size_hints.max_aspect.y); - } - else - { - window->size_hints.min_aspect.x = 1; - window->size_hints.min_aspect.y = G_MAXINT; - window->size_hints.max_aspect.x = G_MAXINT; - window->size_hints.max_aspect.y = 1; - window->size_hints.flags |= PAspect; - } - - /* Get gravity hint */ - if (window->size_hints.flags & PWinGravity) - { - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets gravity %d\n", - window->desc, - window->size_hints.win_gravity); - } - else - { - meta_topic (META_DEBUG_GEOMETRY, - "Window %s doesn't set gravity, using NW\n", - window->desc); - window->size_hints.win_gravity = NorthWestGravity; - window->size_hints.flags |= PWinGravity; - } - - /*** Lots of sanity checking ***/ - - /* Verify all min & max hints are at least 1 pixel */ - if (window->size_hints.min_width < 1) - { - /* someone is on crack */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min width to 0, which makes no sense\n", - window->desc); - window->size_hints.min_width = 1; - } - if (window->size_hints.max_width < 1) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max width to 0, which makes no sense\n", - window->desc); - window->size_hints.max_width = 1; - } - if (window->size_hints.min_height < 1) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min height to 0, which makes no sense\n", - window->desc); - window->size_hints.min_height = 1; - } - if (window->size_hints.max_height < 1) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max height to 0, which makes no sense\n", - window->desc); - window->size_hints.max_height = 1; - } - - /* Verify size increment hints are at least 1 pixel */ - if (window->size_hints.width_inc < 1) - { - /* app authors find so many ways to smoke crack */ - window->size_hints.width_inc = 1; - meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 width_inc to 1\n"); - } - if (window->size_hints.height_inc < 1) - { - /* another cracksmoker */ - window->size_hints.height_inc = 1; - meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 height_inc to 1\n"); - } - /* divide by 0 cracksmokers; note that x & y in (min|max)_aspect are - * numerator & denominator - */ - if (window->size_hints.min_aspect.y < 1) - window->size_hints.min_aspect.y = 1; - if (window->size_hints.max_aspect.y < 1) - window->size_hints.max_aspect.y = 1; - - minw = window->size_hints.min_width; minh = window->size_hints.min_height; - maxw = window->size_hints.max_width; maxh = window->size_hints.max_height; - basew = window->size_hints.base_width; baseh = window->size_hints.base_height; - winc = window->size_hints.width_inc; hinc = window->size_hints.height_inc; - - /* Make sure min and max size hints are consistent with the base + increment - * size hints. If they're not, it's not a real big deal, but it means the - * effective min and max size are more restrictive than the application - * specified values. - */ - if ((minw - basew) % winc != 0) - { - /* Take advantage of integer division throwing away the remainder... */ - window->size_hints.min_width = basew + ((minw - basew)/winc + 1)*winc; - - meta_topic (META_DEBUG_GEOMETRY, - "Window %s has width_inc (%d) that does not evenly divide " - "min_width - base_width (%d - %d); thus effective " - "min_width is really %d\n", - window->desc, - winc, minw, basew, window->size_hints.min_width); - minw = window->size_hints.min_width; - } - if (maxw != G_MAXINT && (maxw - basew) % winc != 0) - { - /* Take advantage of integer division throwing away the remainder... */ - window->size_hints.max_width = basew + ((maxw - basew)/winc)*winc; - - meta_topic (META_DEBUG_GEOMETRY, - "Window %s has width_inc (%d) that does not evenly divide " - "max_width - base_width (%d - %d); thus effective " - "max_width is really %d\n", - window->desc, - winc, maxw, basew, window->size_hints.max_width); - maxw = window->size_hints.max_width; - } - if ((minh - baseh) % hinc != 0) - { - /* Take advantage of integer division throwing away the remainder... */ - window->size_hints.min_height = baseh + ((minh - baseh)/hinc + 1)*hinc; - - meta_topic (META_DEBUG_GEOMETRY, - "Window %s has height_inc (%d) that does not evenly divide " - "min_height - base_height (%d - %d); thus effective " - "min_height is really %d\n", - window->desc, - hinc, minh, baseh, window->size_hints.min_height); - minh = window->size_hints.min_height; - } - if (maxh != G_MAXINT && (maxh - baseh) % hinc != 0) - { - /* Take advantage of integer division throwing away the remainder... */ - window->size_hints.max_height = baseh + ((maxh - baseh)/hinc)*hinc; - - meta_topic (META_DEBUG_GEOMETRY, - "Window %s has height_inc (%d) that does not evenly divide " - "max_height - base_height (%d - %d); thus effective " - "max_height is really %d\n", - window->desc, - hinc, maxh, baseh, window->size_hints.max_height); - maxh = window->size_hints.max_height; - } - - /* make sure maximum size hints are compatible with minimum size hints; min - * size hints take precedence. - */ - if (window->size_hints.max_width < window->size_hints.min_width) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max width %d less than min width %d, " - "disabling resize\n", - window->desc, - window->size_hints.max_width, - window->size_hints.min_width); - maxw = window->size_hints.max_width = window->size_hints.min_width; - } - if (window->size_hints.max_height < window->size_hints.min_height) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max height %d less than min height %d, " - "disabling resize\n", - window->desc, - window->size_hints.max_height, - window->size_hints.min_height); - maxh = window->size_hints.max_height = window->size_hints.min_height; - } - - /* Make sure the aspect ratio hints are sane. */ - minr = window->size_hints.min_aspect.x / - (double)window->size_hints.min_aspect.y; - maxr = window->size_hints.max_aspect.x / - (double)window->size_hints.max_aspect.y; - if (minr > maxr) - { - /* another cracksmoker; not even minimally (self) consistent */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min aspect ratio larger than max aspect " - "ratio; disabling aspect ratio constraints.\n", - window->desc); - window->size_hints.min_aspect.x = 1; - window->size_hints.min_aspect.y = G_MAXINT; - window->size_hints.max_aspect.x = G_MAXINT; - window->size_hints.max_aspect.y = 1; - } - else /* check consistency of aspect ratio hints with other hints */ - { - if (minh > 0 && minr > (maxw / (double)minh)) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min aspect ratio larger than largest " - "aspect ratio possible given min/max size constraints; " - "disabling min aspect ratio constraint.\n", - window->desc); - window->size_hints.min_aspect.x = 1; - window->size_hints.min_aspect.y = G_MAXINT; - } - if (maxr < (minw / (double)maxh)) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max aspect ratio smaller than smallest " - "aspect ratio possible given min/max size constraints; " - "disabling max aspect ratio constraint.\n", - window->desc); - window->size_hints.max_aspect.x = G_MAXINT; - window->size_hints.max_aspect.y = 1; - } - /* FIXME: Would be nice to check that aspect ratios are - * consistent with base and size increment constraints. - */ - } -} - -static void -reload_normal_hints (MetaWindow *window, - MetaPropValue *value) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - XSizeHints old_hints; - - meta_topic (META_DEBUG_GEOMETRY, "Updating WM_NORMAL_HINTS for %s\n", window->desc); - - old_hints = window->size_hints; - - meta_set_normal_hints (window, value->v.size_hints.hints); - - spew_size_hints_differences (&old_hints, &window->size_hints); - - meta_window_recalc_features (window); - } -} - - -static void -init_wm_protocols (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_ATOM_LIST; - value->atom = display->atom_WM_PROTOCOLS; -} - -static void -reload_wm_protocols (MetaWindow *window, - MetaPropValue *value) -{ - int i; - - window->take_focus = FALSE; - window->delete_window = FALSE; - window->net_wm_ping = FALSE; - - if (value->type == META_PROP_VALUE_INVALID) - return; - - i = 0; - while (i < value->v.atom_list.n_atoms) - { - if (value->v.atom_list.atoms[i] == - window->display->atom_WM_TAKE_FOCUS) - window->take_focus = TRUE; - else if (value->v.atom_list.atoms[i] == - window->display->atom_WM_DELETE_WINDOW) - window->delete_window = TRUE; - else if (value->v.atom_list.atoms[i] == - window->display->atom__NET_WM_PING) - window->net_wm_ping = TRUE; - ++i; - } - - meta_verbose ("New _NET_STARTUP_ID \"%s\" for %s\n", - window->startup_id ? window->startup_id : "unset", - window->desc); -} - -static void -init_wm_hints (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_WM_HINTS; - value->atom = XA_WM_HINTS; -} - -static void -reload_wm_hints (MetaWindow *window, - MetaPropValue *value) -{ - Window old_group_leader; - - old_group_leader = window->xgroup_leader; - - /* Fill in defaults */ - window->input = TRUE; - window->initially_iconic = FALSE; - window->xgroup_leader = None; - window->wm_hints_pixmap = None; - window->wm_hints_mask = None; - - if (value->type != META_PROP_VALUE_INVALID) - { - const XWMHints *hints = value->v.wm_hints; - - if (hints->flags & InputHint) - window->input = hints->input; - - if (hints->flags & StateHint) - window->initially_iconic = (hints->initial_state == IconicState); - - if (hints->flags & WindowGroupHint) - window->xgroup_leader = hints->window_group; - - if (hints->flags & IconPixmapHint) - window->wm_hints_pixmap = hints->icon_pixmap; - - if (hints->flags & IconMaskHint) - window->wm_hints_mask = hints->icon_mask; - - meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n", - window->input, window->initially_iconic, - window->xgroup_leader, - window->wm_hints_pixmap, - window->wm_hints_mask); - } - - if (window->xgroup_leader != old_group_leader) - { - meta_verbose ("Window %s changed its group leader to 0x%lx\n", - window->desc, window->xgroup_leader); - - meta_window_group_leader_changed (window); - } - - meta_icon_cache_property_changed (&window->icon_cache, - window->display, - XA_WM_HINTS); - - meta_window_queue (window, META_QUEUE_UPDATE_ICON | META_QUEUE_MOVE_RESIZE); -} - -static void -init_transient_for (MetaDisplay *display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_WINDOW; - value->atom = XA_WM_TRANSIENT_FOR; -} - -static void -reload_transient_for (MetaWindow *window, - MetaPropValue *value) -{ - window->xtransient_for = None; - - if (value->type != META_PROP_VALUE_INVALID) - window->xtransient_for = value->v.xwindow; - - /* Make sure transient_for is valid */ - if (window->xtransient_for != None && - meta_display_lookup_x_window (window->display, - window->xtransient_for) == NULL) - { - meta_warning (_("Invalid WM_TRANSIENT_FOR window 0x%lx specified " - "for %s.\n"), - window->xtransient_for, window->desc); - window->xtransient_for = None; - } - - window->transient_parent_is_root_window = - window->xtransient_for == window->screen->xroot; - - if (window->xtransient_for != None) - meta_verbose ("Window %s transient for 0x%lx (root = %d)\n", window->desc, - window->xtransient_for, window->transient_parent_is_root_window); - else - meta_verbose ("Window %s is not transient\n", window->desc); - - /* may now be a dialog */ - meta_window_recalc_window_type (window); - - /* update stacking constraints */ - meta_stack_update_transient (window->screen->stack, window); - - /* possibly change its group. We treat being a window's transient as - * equivalent to making it your group leader, to work around shortcomings - * in programs such as xmms-- see #328211. - */ - if (window->xtransient_for != None && - window->xgroup_leader != None && - window->xtransient_for != window->xgroup_leader) - meta_window_group_leader_changed (window); - - if (!window->constructing) - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); -} - -#define N_HOOKS 26 - -void -meta_display_init_window_prop_hooks (MetaDisplay *display) -{ - int i; - MetaWindowPropHooks *hooks; - - g_assert (display->prop_hooks == NULL); - - display->prop_hooks = g_new0 (MetaWindowPropHooks, N_HOOKS); - hooks = display->prop_hooks; - - i = 0; - - hooks[i].property = display->atom_WM_STATE; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = display->atom_WM_CLIENT_MACHINE; - hooks[i].init_func = init_wm_client_machine; - hooks[i].reload_func = reload_wm_client_machine; - ++i; - - hooks[i].property = display->atom__NET_WM_PID; - hooks[i].init_func = init_net_wm_pid; - hooks[i].reload_func = reload_net_wm_pid; - ++i; - - hooks[i].property = display->atom__NET_WM_USER_TIME; - hooks[i].init_func = init_net_wm_user_time; - hooks[i].reload_func = reload_net_wm_user_time; - ++i; - - hooks[i].property = display->atom__NET_WM_NAME; - hooks[i].init_func = init_net_wm_name; - hooks[i].reload_func = reload_net_wm_name; - ++i; - - hooks[i].property = XA_WM_NAME; - hooks[i].init_func = init_wm_name; - hooks[i].reload_func = reload_wm_name; - ++i; - - hooks[i].property = display->atom__NET_WM_ICON_NAME; - hooks[i].init_func = init_net_wm_icon_name; - hooks[i].reload_func = reload_net_wm_icon_name; - ++i; - - hooks[i].property = XA_WM_ICON_NAME; - hooks[i].init_func = init_wm_icon_name; - hooks[i].reload_func = reload_wm_icon_name; - ++i; - - hooks[i].property = display->atom__NET_WM_STATE; - hooks[i].init_func = init_net_wm_state; - hooks[i].reload_func = reload_net_wm_state; - ++i; - - hooks[i].property = display->atom__MOTIF_WM_HINTS; - hooks[i].init_func = init_mwm_hints; - hooks[i].reload_func = reload_mwm_hints; - ++i; - - hooks[i].property = display->atom__NET_WM_ICON_GEOMETRY; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = XA_WM_CLASS; - hooks[i].init_func = init_wm_class; - hooks[i].reload_func = reload_wm_class; - ++i; - - hooks[i].property = display->atom_WM_CLIENT_LEADER; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = display->atom_SM_CLIENT_ID; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = display->atom_WM_WINDOW_ROLE; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = display->atom__NET_WM_WINDOW_TYPE; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = display->atom__NET_WM_DESKTOP; - hooks[i].init_func = init_net_wm_desktop; - hooks[i].reload_func = reload_net_wm_desktop; - ++i; - - hooks[i].property = display->atom__NET_WM_STRUT; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = display->atom__NET_WM_STRUT_PARTIAL; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = display->atom__NET_STARTUP_ID; - hooks[i].init_func = init_net_startup_id; - hooks[i].reload_func = reload_net_startup_id; - ++i; - - hooks[i].property = display->atom__NET_WM_SYNC_REQUEST_COUNTER; - hooks[i].init_func = init_update_counter; - hooks[i].reload_func = reload_update_counter; - ++i; - - hooks[i].property = XA_WM_NORMAL_HINTS; - hooks[i].init_func = init_normal_hints; - hooks[i].reload_func = reload_normal_hints; - ++i; - - hooks[i].property = display->atom_WM_PROTOCOLS; - hooks[i].init_func = init_wm_protocols; - hooks[i].reload_func = reload_wm_protocols; - ++i; - - hooks[i].property = XA_WM_HINTS; - hooks[i].init_func = init_wm_hints; - hooks[i].reload_func = reload_wm_hints; - ++i; - - hooks[i].property = XA_WM_TRANSIENT_FOR; - hooks[i].init_func = init_transient_for; - hooks[i].reload_func = reload_transient_for; - ++i; - - hooks[i].property = display->atom__NET_WM_USER_TIME_WINDOW; - hooks[i].init_func = init_net_wm_user_time_window; - hooks[i].reload_func = reload_net_wm_user_time_window; - ++i; - - if (i != N_HOOKS) - { - g_error ("Initialized %d hooks should have been %d\n", i, N_HOOKS); - } -} - -void -meta_display_free_window_prop_hooks (MetaDisplay *display) -{ - g_assert (display->prop_hooks != NULL); - - g_free (display->prop_hooks); - display->prop_hooks = NULL; -} - -static MetaWindowPropHooks* -find_hooks (MetaDisplay *display, - Atom property) -{ - int i; - - /* FIXME we could sort the array and do binary search or - * something - */ - - i = 0; - while (i < N_HOOKS) - { - if (display->prop_hooks[i].property == property) - return &display->prop_hooks[i]; - - ++i; - } - - return NULL; -} diff --git a/src/core/window-props.h b/src/core/window-props.h deleted file mode 100644 index 9ac3cf19..00000000 --- a/src/core/window-props.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file window-props.h MetaWindow property handling - * - * A system which can inspect sets of properties of given windows - * and take appropriate action given their values. - * - * Note that all the meta_window_reload_propert* functions require a - * round trip to the server. - */ - -/* - * Copyright (C) 2001, 2002 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WINDOW_PROPS_H -#define META_WINDOW_PROPS_H - -#include "window-private.h" - -/** - * Requests the current values of a single property for a given - * window from the server, and deals with it appropriately. - * Does not return it to the caller (it's been dealt with!) - * - * \param window The window. - * \param property A single X atom. - */ -void meta_window_reload_property (MetaWindow *window, - Atom property); - - -/** - * Requests the current values of a set of properties for a given - * window from the server, and deals with them appropriately. - * Does not return them to the caller (they've been dealt with!) - * - * \param window The window. - * \param properties A pointer to a list of X atoms, "n_properties" long. - * \param n_properties The length of the properties list. - */ -void meta_window_reload_properties (MetaWindow *window, - const Atom *properties, - int n_properties); - -/** - * Requests the current values of a single property for a given - * window from the server, and deals with it appropriately. - * Does not return it to the caller (it's been dealt with!) - * - * \param window A window on the same display as the one we're - * investigating (only used to find the display) - * \param xwindow The X handle for the window. - * \param property A single X atom. - */ -void meta_window_reload_property_from_xwindow - (MetaWindow *window, - Window xwindow, - Atom property); - -/** - * Requests the current values of a set of properties for a given - * window from the server, and deals with them appropriately. - * Does not return them to the caller (they've been dealt with!) - * - * \param window A window on the same display as the one we're - * investigating (only used to find the display) - * \param xwindow The X handle for the window. - * \param properties A pointer to a list of X atoms, "n_properties" long. - * \param n_properties The length of the properties list. - */ -void meta_window_reload_properties_from_xwindow - (MetaWindow *window, - Window xwindow, - const Atom *properties, - int n_properties); - -/** - * Initialises the hooks used for the reload_propert* functions - * on a particular display, and stores a pointer to them in the - * display. - * - * \param display The display. - */ -void meta_display_init_window_prop_hooks (MetaDisplay *display); - -/** - * Frees the hooks used for the reload_propert* functions - * for a particular display. - * - * \param display The display. - */ -void meta_display_free_window_prop_hooks (MetaDisplay *display); - -/** - * Sets the size hints for a window. This happens when a - * WM_NORMAL_HINTS property is set on a window, but it is public - * because the size hints are set to defaults when a window is - * created. See - * http://tronche.com/gui/x/icccm/sec-4.html#WM_NORMAL_HINTS - * for the X details. - * - * \param window The window to set the size hints on. - * \param hints Either some X size hints, or NULL for default. - */ -void meta_set_normal_hints (MetaWindow *window, - XSizeHints *hints); - -#endif /* META_WINDOW_PROPS_H */ diff --git a/src/core/window.c b/src/core/window.c deleted file mode 100644 index 0f93c409..00000000 --- a/src/core/window.c +++ /dev/null @@ -1,8262 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X managed windows */ - -/* - * Copyright (C) 2001 Havoc Pennington, Anders Carlsson - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "window-private.h" -#include "edge-resistance.h" -#include "util.h" -#include "frame-private.h" -#include "errors.h" -#include "workspace.h" -#include "stack.h" -#include "keybindings.h" -#include "ui.h" -#include "place.h" -#include "session.h" -#include "effects.h" -#include "prefs.h" -#include "resizepopup.h" -#include "xprops.h" -#include "group.h" -#include "window-props.h" -#include "constraints.h" -#include "compositor.h" -#include "effects.h" - -#include <X11/Xatom.h> -#include <string.h> - -#ifdef HAVE_SHAPE -#include <X11/extensions/shape.h> -#endif - -static int destroying_windows_disallowed = 0; - - -static void update_sm_hints (MetaWindow *window); -static void update_role (MetaWindow *window); -static void update_net_wm_type (MetaWindow *window); -static void update_net_frame_extents (MetaWindow *window); -static void recalc_window_type (MetaWindow *window); -static void recalc_window_features (MetaWindow *window); -static void invalidate_work_areas (MetaWindow *window); -static void recalc_window_type (MetaWindow *window); -static void set_wm_state (MetaWindow *window, - int state); -static void set_net_wm_state (MetaWindow *window); - -static void send_configure_notify (MetaWindow *window); -static gboolean process_property_notify (MetaWindow *window, - XPropertyEvent *event); -static void meta_window_show (MetaWindow *window); -static void meta_window_hide (MetaWindow *window); - -static void meta_window_save_rect (MetaWindow *window); -static void save_user_window_placement (MetaWindow *window); -static void force_save_user_window_placement (MetaWindow *window); - -static void meta_window_move_resize_internal (MetaWindow *window, - MetaMoveResizeFlags flags, - int resize_gravity, - int root_x_nw, - int root_y_nw, - int w, - int h); - -static void ensure_mru_position_after (MetaWindow *window, - MetaWindow *after_this_one); - - -static void meta_window_move_resize_now (MetaWindow *window); - -static void meta_window_unqueue (MetaWindow *window, guint queuebits); - -static void update_move (MetaWindow *window, - gboolean snap, - int x, - int y); -static gboolean update_move_timeout (gpointer data); -static void update_resize (MetaWindow *window, - gboolean snap, - int x, - int y, - gboolean force); -static gboolean update_resize_timeout (gpointer data); - - -static void meta_window_flush_calc_showing (MetaWindow *window); - -static gboolean queue_calc_showing_func (MetaWindow *window, - void *data); - -static void meta_window_apply_session_info (MetaWindow *window, - const MetaWindowSessionInfo *info); - -static void unmaximize_window_before_freeing (MetaWindow *window); -static void unminimize_window_and_all_transient_parents (MetaWindow *window); - -/* Idle handlers for the three queues. The "data" parameter in each case - * will be a GINT_TO_POINTER of the index into the queue arrays to use. - * - * TODO: Possibly there is still some code duplication among these, which we - * need to sort out at some point. - */ -static gboolean idle_calc_showing (gpointer data); -static gboolean idle_move_resize (gpointer data); -static gboolean idle_update_icon (gpointer data); - -#ifdef WITH_VERBOSE_MODE -static const char* -wm_state_to_string (int state) -{ - switch (state) - { - case NormalState: - return "NormalState"; - case IconicState: - return "IconicState"; - case WithdrawnState: - return "WithdrawnState"; - } - - return "Unknown"; -} -#endif - -static gboolean -is_desktop_or_dock_foreach (MetaWindow *window, - void *data) -{ - gboolean *result = data; - - *result = - window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK; - if (*result) - return FALSE; /* stop as soon as we find one */ - else - return TRUE; -} - -/* window is the window that's newly mapped provoking - * the possible change - */ -static void -maybe_leave_show_desktop_mode (MetaWindow *window) -{ - gboolean is_desktop_or_dock; - - if (!window->screen->active_workspace->showing_desktop) - return; - - /* If the window is a transient for the dock or desktop, don't - * leave show desktop mode when the window opens. That's - * so you can e.g. hide all windows, manipulate a file on - * the desktop via a dialog, then unshow windows again. - */ - is_desktop_or_dock = FALSE; - is_desktop_or_dock_foreach (window, - &is_desktop_or_dock); - - meta_window_foreach_ancestor (window, is_desktop_or_dock_foreach, - &is_desktop_or_dock); - - if (!is_desktop_or_dock) - { - meta_screen_minimize_all_on_active_workspace_except (window->screen, - window); - meta_screen_unshow_desktop (window->screen); - } -} - -MetaWindow* -meta_window_new (MetaDisplay *display, - Window xwindow, - gboolean must_be_viewable) -{ - XWindowAttributes attrs; - MetaWindow *window; - - meta_display_grab (display); - meta_error_trap_push (display); /* Push a trap over all of window - * creation, to reduce XSync() calls - */ - - meta_error_trap_push_with_return (display); - - if (XGetWindowAttributes (display->xdisplay,xwindow, &attrs)) - { - if(meta_error_trap_pop_with_return (display, TRUE) != Success) - { - meta_verbose ("Failed to get attributes for window 0x%lx\n", - xwindow); - meta_error_trap_pop (display, TRUE); - meta_display_ungrab (display); - return NULL; - } - window = meta_window_new_with_attrs (display, xwindow, - must_be_viewable, &attrs); - } - else - { - meta_error_trap_pop_with_return (display, TRUE); - meta_verbose ("Failed to get attributes for window 0x%lx\n", - xwindow); - meta_error_trap_pop (display, TRUE); - meta_display_ungrab (display); - return NULL; - } - - - meta_error_trap_pop (display, FALSE); - meta_display_ungrab (display); - - return window; -} - -MetaWindow* -meta_window_new_with_attrs (MetaDisplay *display, - Window xwindow, - gboolean must_be_viewable, - XWindowAttributes *attrs) -{ - MetaWindow *window; - GSList *tmp; - MetaWorkspace *space; - gulong existing_wm_state; - gulong event_mask; - MetaMoveResizeFlags flags; -#define N_INITIAL_PROPS 19 - Atom initial_props[N_INITIAL_PROPS]; - int i; - gboolean has_shape; - - g_assert (attrs != NULL); - g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props)); - - meta_verbose ("Attempting to manage 0x%lx\n", xwindow); - - if (meta_display_xwindow_is_a_no_focus_window (display, xwindow)) - { - meta_verbose ("Not managing no_focus_window 0x%lx\n", - xwindow); - return NULL; - } - - if (attrs->override_redirect) - { - meta_verbose ("Deciding not to manage override_redirect window 0x%lx\n", xwindow); - return NULL; - } - - /* Grab server */ - meta_display_grab (display); - meta_error_trap_push (display); /* Push a trap over all of window - * creation, to reduce XSync() calls - */ - - meta_verbose ("must_be_viewable = %d attrs->map_state = %d (%s)\n", - must_be_viewable, - attrs->map_state, - (attrs->map_state == IsUnmapped) ? - "IsUnmapped" : - (attrs->map_state == IsViewable) ? - "IsViewable" : - (attrs->map_state == IsUnviewable) ? - "IsUnviewable" : - "(unknown)"); - - existing_wm_state = WithdrawnState; - if (must_be_viewable && attrs->map_state != IsViewable) - { - /* Only manage if WM_STATE is IconicState or NormalState */ - gulong state; - - /* WM_STATE isn't a cardinal, it's type WM_STATE, but is an int */ - if (!(meta_prop_get_cardinal_with_atom_type (display, xwindow, - display->atom_WM_STATE, - display->atom_WM_STATE, - &state) && - (state == IconicState || state == NormalState))) - { - meta_verbose ("Deciding not to manage unmapped or unviewable window 0x%lx\n", xwindow); - meta_error_trap_pop (display, TRUE); - meta_display_ungrab (display); - return NULL; - } - - existing_wm_state = state; - meta_verbose ("WM_STATE of %lx = %s\n", xwindow, - wm_state_to_string (existing_wm_state)); - } - - meta_error_trap_push_with_return (display); - - XAddToSaveSet (display->xdisplay, xwindow); - - event_mask = - PropertyChangeMask | EnterWindowMask | LeaveWindowMask | - FocusChangeMask | ColormapChangeMask; - - XSelectInput (display->xdisplay, xwindow, event_mask); - - has_shape = FALSE; -#ifdef HAVE_SHAPE - if (META_DISPLAY_HAS_SHAPE (display)) - { - int x_bounding, y_bounding, x_clip, y_clip; - unsigned w_bounding, h_bounding, w_clip, h_clip; - int bounding_shaped, clip_shaped; - - XShapeSelectInput (display->xdisplay, xwindow, ShapeNotifyMask); - - XShapeQueryExtents (display->xdisplay, xwindow, - &bounding_shaped, &x_bounding, &y_bounding, - &w_bounding, &h_bounding, - &clip_shaped, &x_clip, &y_clip, - &w_clip, &h_clip); - - has_shape = bounding_shaped != FALSE; - - meta_topic (META_DEBUG_SHAPES, - "Window has_shape = %d extents %d,%d %u x %u\n", - has_shape, x_bounding, y_bounding, - w_bounding, h_bounding); - } -#endif - - /* Get rid of any borders */ - if (attrs->border_width != 0) - XSetWindowBorderWidth (display->xdisplay, xwindow, 0); - - /* Get rid of weird gravities */ - if (attrs->win_gravity != NorthWestGravity) - { - XSetWindowAttributes set_attrs; - - set_attrs.win_gravity = NorthWestGravity; - - XChangeWindowAttributes (display->xdisplay, - xwindow, - CWWinGravity, - &set_attrs); - } - - if (meta_error_trap_pop_with_return (display, FALSE) != Success) - { - meta_verbose ("Window 0x%lx disappeared just as we tried to manage it\n", - xwindow); - meta_error_trap_pop (display, FALSE); - meta_display_ungrab (display); - return NULL; - } - - g_assert (!attrs->override_redirect); - - window = g_new (MetaWindow, 1); - - window->constructing = TRUE; - - window->dialog_pid = -1; - window->dialog_pipe = -1; - - window->xwindow = xwindow; - - /* this is in window->screen->display, but that's too annoying to - * type - */ - window->display = display; - window->workspace = NULL; - -#ifdef HAVE_XSYNC - window->sync_request_counter = None; - window->sync_request_serial = 0; - window->sync_request_time.tv_sec = 0; - window->sync_request_time.tv_usec = 0; -#endif - - window->screen = NULL; - tmp = display->screens; - while (tmp != NULL) - { - MetaScreen *scr = tmp->data; - - if (scr->xroot == attrs->root) - { - window->screen = tmp->data; - break; - } - - tmp = tmp->next; - } - - g_assert (window->screen); - - window->desc = g_strdup_printf ("0x%lx", window->xwindow); - - /* avoid tons of stack updates */ - meta_stack_freeze (window->screen->stack); - - window->has_shape = has_shape; - - window->rect.x = attrs->x; - window->rect.y = attrs->y; - window->rect.width = attrs->width; - window->rect.height = attrs->height; - - /* And border width, size_hints are the "request" */ - window->border_width = attrs->border_width; - window->size_hints.x = attrs->x; - window->size_hints.y = attrs->y; - window->size_hints.width = attrs->width; - window->size_hints.height = attrs->height; - /* initialize the remaining size_hints as if size_hints.flags were zero */ - meta_set_normal_hints (window, NULL); - - /* And this is our unmaximized size */ - window->saved_rect = window->rect; - window->user_rect = window->rect; - - window->depth = attrs->depth; - window->xvisual = attrs->visual; - window->colormap = attrs->colormap; - - window->title = NULL; - window->icon_name = NULL; - window->icon = NULL; - window->mini_icon = NULL; - meta_icon_cache_init (&window->icon_cache); - window->wm_hints_pixmap = None; - window->wm_hints_mask = None; - - window->frame = NULL; - window->has_focus = FALSE; - - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; - window->maximize_horizontally_after_placement = FALSE; - window->maximize_vertically_after_placement = FALSE; - window->minimize_after_placement = FALSE; - window->fullscreen = FALSE; - window->fullscreen_monitors[0] = -1; - window->require_fully_onscreen = TRUE; - window->require_on_single_xinerama = TRUE; - window->require_titlebar_visible = TRUE; - window->on_all_workspaces = FALSE; - window->shaded = FALSE; - window->initially_iconic = FALSE; - window->minimized = FALSE; - window->was_minimized = FALSE; - window->tab_unminimized = FALSE; - window->iconic = FALSE; - window->mapped = attrs->map_state != IsUnmapped; - /* if already mapped, no need to worry about focus-on-first-time-showing */ - window->showing_for_first_time = !window->mapped; - /* if already mapped we don't want to do the placement thing */ - window->placed = window->mapped; - if (window->placed) - meta_topic (META_DEBUG_PLACEMENT, - "Not placing window 0x%lx since it's already mapped\n", - xwindow); - window->denied_focus_and_not_transient = FALSE; - window->unmanaging = FALSE; - window->is_in_queues = 0; - window->keys_grabbed = FALSE; - window->grab_on_frame = FALSE; - window->all_keys_grabbed = FALSE; - window->withdrawn = FALSE; - window->initial_workspace_set = FALSE; - window->initial_timestamp_set = FALSE; - window->net_wm_user_time_set = FALSE; - window->user_time_window = None; - window->calc_placement = FALSE; - window->shaken_loose = FALSE; - window->have_focus_click_grab = FALSE; - window->disable_sync = FALSE; - - window->unmaps_pending = 0; - - window->mwm_decorated = TRUE; - window->mwm_border_only = FALSE; - window->mwm_has_close_func = TRUE; - window->mwm_has_minimize_func = TRUE; - window->mwm_has_maximize_func = TRUE; - window->mwm_has_move_func = TRUE; - window->mwm_has_resize_func = TRUE; - - window->decorated = TRUE; - window->has_close_func = TRUE; - window->has_minimize_func = TRUE; - window->has_maximize_func = TRUE; - window->has_move_func = TRUE; - window->has_resize_func = TRUE; - - window->has_shade_func = TRUE; - - window->has_fullscreen_func = TRUE; - - window->always_sticky = FALSE; - - window->wm_state_modal = FALSE; - window->skip_taskbar = FALSE; - window->skip_pager = FALSE; - window->wm_state_skip_taskbar = FALSE; - window->wm_state_skip_pager = FALSE; - window->wm_state_above = FALSE; - window->wm_state_below = FALSE; - window->wm_state_demands_attention = FALSE; - - window->res_class = NULL; - window->res_name = NULL; - window->role = NULL; - window->sm_client_id = NULL; - window->wm_client_machine = NULL; - window->startup_id = NULL; - - window->net_wm_pid = -1; - - window->xtransient_for = None; - window->xclient_leader = None; - window->transient_parent_is_root_window = FALSE; - - window->type = META_WINDOW_NORMAL; - window->type_atom = None; - - window->struts = NULL; - - window->using_net_wm_name = FALSE; - window->using_net_wm_visible_name = FALSE; - window->using_net_wm_icon_name = FALSE; - window->using_net_wm_visible_icon_name = FALSE; - - window->need_reread_icon = TRUE; - - window->layer = META_LAYER_LAST; /* invalid value */ - window->stack_position = -1; - window->initial_workspace = 0; /* not used */ - window->initial_timestamp = 0; /* not used */ - - meta_display_register_x_window (display, &window->xwindow, window); - - - /* assign the window to its group, or create a new group if needed - */ - window->group = NULL; - window->xgroup_leader = None; - meta_window_compute_group (window); - - /* Fill these in the order we want them to be gotten. we want to - * get window name and class first so we can use them in error - * messages and such. However, name is modified depending on - * wm_client_machine, so push it slightly sooner. - */ - i = 0; - initial_props[i++] = display->atom_WM_CLIENT_MACHINE; - initial_props[i++] = display->atom__NET_WM_NAME; - initial_props[i++] = XA_WM_CLASS; - initial_props[i++] = display->atom__NET_WM_PID; - initial_props[i++] = XA_WM_NAME; - initial_props[i++] = display->atom__NET_WM_ICON_NAME; - initial_props[i++] = XA_WM_ICON_NAME; - initial_props[i++] = display->atom__NET_WM_DESKTOP; - initial_props[i++] = display->atom__NET_STARTUP_ID; - initial_props[i++] = display->atom__NET_WM_SYNC_REQUEST_COUNTER; - initial_props[i++] = XA_WM_NORMAL_HINTS; - initial_props[i++] = display->atom_WM_PROTOCOLS; - initial_props[i++] = XA_WM_HINTS; - initial_props[i++] = display->atom__NET_WM_USER_TIME; - initial_props[i++] = display->atom__NET_WM_STATE; - initial_props[i++] = display->atom__MOTIF_WM_HINTS; - initial_props[i++] = XA_WM_TRANSIENT_FOR; - initial_props[i++] = display->atom__NET_WM_USER_TIME_WINDOW; - initial_props[i++] = display->atom__NET_WM_FULLSCREEN_MONITORS; - g_assert (N_INITIAL_PROPS == i); - - meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS); - - update_sm_hints (window); /* must come after transient_for */ - update_role (window); - update_net_wm_type (window); - meta_window_update_icon_now (window); - - if (window->initially_iconic) - { - /* WM_HINTS said minimized */ - window->minimized = TRUE; - meta_verbose ("Window %s asked to start out minimized\n", window->desc); - } - - if (existing_wm_state == IconicState) - { - /* WM_STATE said minimized */ - window->minimized = TRUE; - meta_verbose ("Window %s had preexisting WM_STATE = IconicState, minimizing\n", - window->desc); - - /* Assume window was previously placed, though perhaps it's - * been iconic its whole life, we have no way of knowing. - */ - window->placed = TRUE; - } - - /* Apply any window attributes such as initial workspace - * based on startup notification - */ - meta_screen_apply_startup_properties (window->screen, window); - - /* Try to get a "launch timestamp" for the window. If the window is - * a transient, we'd like to be able to get a last-usage timestamp - * from the parent window. If the window has no parent, there isn't - * much we can do...except record the current time so that any children - * can use this time as a fallback. - */ - if (!window->net_wm_user_time_set) { - MetaWindow *parent = NULL; - if (window->xtransient_for) - parent = meta_display_lookup_x_window (window->display, - window->xtransient_for); - - /* First, maybe the app was launched with startup notification using an - * obsolete version of the spec; use that timestamp if it exists. - */ - if (window->initial_timestamp_set) - /* NOTE: Do NOT toggle net_wm_user_time_set to true; this is just - * being recorded as a fallback for potential transients - */ - window->net_wm_user_time = window->initial_timestamp; - else if (parent != NULL) - meta_window_set_user_time(window, parent->net_wm_user_time); - else - /* NOTE: Do NOT toggle net_wm_user_time_set to true; this is just - * being recorded as a fallback for potential transients - */ - window->net_wm_user_time = - meta_display_get_current_time_roundtrip (window->display); - } - - if (window->decorated) - meta_window_ensure_frame (window); - - meta_window_grab_keys (window); - if (window->type != META_WINDOW_DOCK) - { - meta_display_grab_window_buttons (window->display, window->xwindow); - meta_display_grab_focus_window_button (window->display, window); - } - - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK) - { - /* Change the default, but don't enforce this if the user - * focuses the dock/desktop and unsticks it using key shortcuts. - * Need to set this before adding to the workspaces so the MRU - * lists will be updated. - */ - window->on_all_workspaces = TRUE; - } - - /* For the workspace, first honor hints, - * if that fails put transients with parents, - * otherwise put window on active space - */ - - if (window->initial_workspace_set) - { - if (window->initial_workspace == (int) 0xFFFFFFFF) - { - meta_topic (META_DEBUG_PLACEMENT, - "Window %s is initially on all spaces\n", - window->desc); - - /* need to set on_all_workspaces first so that it will be - * added to all the MRU lists - */ - window->on_all_workspaces = TRUE; - meta_workspace_add_window (window->screen->active_workspace, window); - } - else - { - meta_topic (META_DEBUG_PLACEMENT, - "Window %s is initially on space %d\n", - window->desc, window->initial_workspace); - - space = - meta_screen_get_workspace_by_index (window->screen, - window->initial_workspace); - - if (space) - meta_workspace_add_window (space, window); - } - } - - if (window->workspace == NULL && - window->xtransient_for != None) - { - /* Try putting dialog on parent's workspace */ - MetaWindow *parent; - - parent = meta_display_lookup_x_window (window->display, - window->xtransient_for); - - if (parent && parent->workspace) - { - meta_topic (META_DEBUG_PLACEMENT, - "Putting window %s on same workspace as parent %s\n", - window->desc, parent->desc); - - if (parent->on_all_workspaces) - window->on_all_workspaces = TRUE; - - /* this will implicitly add to the appropriate MRU lists - */ - meta_workspace_add_window (parent->workspace, window); - } - } - - if (window->workspace == NULL) - { - meta_topic (META_DEBUG_PLACEMENT, - "Putting window %s on active workspace\n", - window->desc); - - space = window->screen->active_workspace; - - meta_workspace_add_window (space, window); - } - - /* for the various on_all_workspaces = TRUE possible above */ - meta_window_set_current_workspace_hint (window); - - meta_window_update_struts (window); - - /* Must add window to stack before doing move/resize, since the - * window might have fullscreen size (i.e. should have been - * fullscreen'd; acrobat is one such braindead case; it withdraws - * and remaps its window whenever trying to become fullscreen...) - * and thus constraints may try to auto-fullscreen it which also - * means restacking it. - */ - meta_stack_add (window->screen->stack, - window); - - /* Put our state back where it should be, - * passing TRUE for is_configure_request, ICCCM says - * initial map is handled same as configure request - */ - flags = - META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION; - meta_window_move_resize_internal (window, - flags, - window->size_hints.win_gravity, - window->size_hints.x, - window->size_hints.y, - window->size_hints.width, - window->size_hints.height); - - /* Now try applying saved stuff from the session */ - { - const MetaWindowSessionInfo *info; - - info = meta_window_lookup_saved_state (window); - - if (info) - { - meta_window_apply_session_info (window, info); - meta_window_release_saved_state (info); - } - } - - /* FIXME we have a tendency to set this then immediately - * change it again. - */ - set_wm_state (window, window->iconic ? IconicState : NormalState); - set_net_wm_state (window); - - /* Sync stack changes */ - meta_stack_thaw (window->screen->stack); - - /* disable show desktop mode unless we're a desktop component */ - maybe_leave_show_desktop_mode (window); - - meta_window_queue (window, META_QUEUE_CALC_SHOWING); - /* See bug 303284; a transient of the given window can already exist, in which - * case we think it should probably be shown. - */ - meta_window_foreach_transient (window, - queue_calc_showing_func, - NULL); - /* See bug 334899; the window may have minimized ancestors - * which need to be shown. - * - * However, we shouldn't unminimize windows here when opening - * a new display because that breaks passing _NET_WM_STATE_HIDDEN - * between window managers when replacing them; see bug 358042. - * - * And we shouldn't unminimize windows if they were initially - * iconic. - */ - if (!display->display_opening && !window->initially_iconic) - unminimize_window_and_all_transient_parents (window); - - meta_error_trap_pop (display, FALSE); /* pop the XSync()-reducing trap */ - meta_display_ungrab (display); - - window->constructing = FALSE; - - return window; -} - -/* This function should only be called from the end of meta_window_new_with_attrs () */ -static void -meta_window_apply_session_info (MetaWindow *window, - const MetaWindowSessionInfo *info) -{ - if (info->stack_position_set) - { - meta_topic (META_DEBUG_SM, - "Restoring stack position %d for window %s\n", - info->stack_position, window->desc); - - /* FIXME well, I'm not sure how to do this. */ - } - - if (info->minimized_set) - { - meta_topic (META_DEBUG_SM, - "Restoring minimized state %d for window %s\n", - info->minimized, window->desc); - - if (window->has_minimize_func && info->minimized) - meta_window_minimize (window); - } - - if (info->maximized_set) - { - meta_topic (META_DEBUG_SM, - "Restoring maximized state %d for window %s\n", - info->maximized, window->desc); - - if (window->has_maximize_func && info->maximized) - { - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - - if (info->saved_rect_set) - { - meta_topic (META_DEBUG_SM, - "Restoring saved rect %d,%d %dx%d for window %s\n", - info->saved_rect.x, - info->saved_rect.y, - info->saved_rect.width, - info->saved_rect.height, - window->desc); - - window->saved_rect.x = info->saved_rect.x; - window->saved_rect.y = info->saved_rect.y; - window->saved_rect.width = info->saved_rect.width; - window->saved_rect.height = info->saved_rect.height; - } - } - } - - if (info->on_all_workspaces_set) - { - window->on_all_workspaces = info->on_all_workspaces; - meta_topic (META_DEBUG_SM, - "Restoring sticky state %d for window %s\n", - window->on_all_workspaces, window->desc); - } - - if (info->workspace_indices) - { - GSList *tmp; - GSList *spaces; - - spaces = NULL; - - tmp = info->workspace_indices; - while (tmp != NULL) - { - MetaWorkspace *space; - - space = - meta_screen_get_workspace_by_index (window->screen, - GPOINTER_TO_INT (tmp->data)); - - if (space) - spaces = g_slist_prepend (spaces, space); - - tmp = tmp->next; - } - - if (spaces) - { - /* This briefly breaks the invariant that we are supposed - * to always be on some workspace. But we paranoically - * ensured that one of the workspaces from the session was - * indeed valid, so we know we'll go right back to one. - */ - if (window->workspace) - meta_workspace_remove_window (window->workspace, window); - - /* Only restore to the first workspace if the window - * happened to be on more than one, since we have replaces - * window->workspaces with window->workspace - */ - meta_workspace_add_window (spaces->data, window); - - meta_topic (META_DEBUG_SM, - "Restoring saved window %s to workspace %d\n", - window->desc, - meta_workspace_index (spaces->data)); - - g_slist_free (spaces); - } - } - - if (info->geometry_set) - { - int x, y, w, h; - MetaMoveResizeFlags flags; - - window->placed = TRUE; /* don't do placement algorithms later */ - - x = info->rect.x; - y = info->rect.y; - - w = window->size_hints.base_width + - info->rect.width * window->size_hints.width_inc; - h = window->size_hints.base_height + - info->rect.height * window->size_hints.height_inc; - - /* Force old gravity, ignoring anything now set */ - window->size_hints.win_gravity = info->gravity; - - meta_topic (META_DEBUG_SM, - "Restoring pos %d,%d size %d x %d for %s\n", - x, y, w, h, window->desc); - - flags = META_DO_GRAVITY_ADJUST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION; - meta_window_move_resize_internal (window, - flags, - window->size_hints.win_gravity, - x, y, w, h); - } -} - -void -meta_window_free (MetaWindow *window, - guint32 timestamp) -{ - GList *tmp; - - meta_verbose ("Unmanaging 0x%lx\n", window->xwindow); - - if (window->display->compositor) - meta_compositor_free_window (window->display->compositor, window); - - if (window->display->window_with_menu == window) - { - meta_ui_window_menu_free (window->display->window_menu); - window->display->window_menu = NULL; - window->display->window_with_menu = NULL; - } - - if (destroying_windows_disallowed > 0) - meta_bug ("Tried to destroy window %s while destruction was not allowed\n", - window->desc); - - window->unmanaging = TRUE; - - if (window->fullscreen) - { - MetaGroup *group; - - /* If the window is fullscreen, it may be forcing - * other windows in its group to a higher layer - */ - - meta_stack_freeze (window->screen->stack); - group = meta_window_get_group (window); - if (group) - meta_group_update_layers (group); - meta_stack_thaw (window->screen->stack); - } - - meta_window_shutdown_group (window); /* safe to do this early as - * group.c won't re-add to the - * group if window->unmanaging - */ - - /* If we have the focus, focus some other window. - * This is done first, so that if the unmap causes - * an EnterNotify the EnterNotify will have final say - * on what gets focused, maintaining sloppy focus - * invariants. - */ - if (window->has_focus) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing default window since we're unmanaging %s\n", - window->desc); - meta_workspace_focus_default_window (window->screen->active_workspace, - window, - timestamp); - } - else if (window->display->expected_focus_window == window) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing default window since expected focus window freed %s\n", - window->desc); - window->display->expected_focus_window = NULL; - meta_workspace_focus_default_window (window->screen->active_workspace, - window, - timestamp); - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Unmanaging window %s which doesn't currently have focus\n", - window->desc); - } - - if (window->struts) - { - meta_free_gslist_and_elements (window->struts); - window->struts = NULL; - - meta_topic (META_DEBUG_WORKAREA, - "Unmanaging window %s which has struts, so invalidating work areas\n", - window->desc); - invalidate_work_areas (window); - } - - if (window->display->grab_window == window) - meta_display_end_grab_op (window->display, timestamp); - - g_assert (window->display->grab_window != window); - - if (window->display->focus_window == window) - { - window->display->focus_window = NULL; - meta_compositor_set_active_window (window->display->compositor, - window->screen, NULL); - } - - if (window->maximized_horizontally || window->maximized_vertically) - unmaximize_window_before_freeing (window); - - /* The XReparentWindow call in meta_window_destroy_frame() moves the - * window so we need to send a configure notify; see bug 399552. (We - * also do this just in case a window got unmaximized.) - */ - send_configure_notify (window); - - meta_window_unqueue (window, META_QUEUE_CALC_SHOWING | - META_QUEUE_MOVE_RESIZE | - META_QUEUE_UPDATE_ICON); - meta_window_free_delete_dialog (window); - - if (window->workspace) - meta_workspace_remove_window (window->workspace, window); - - g_assert (window->workspace == NULL); - -#ifndef G_DISABLE_CHECKS - tmp = window->screen->workspaces; - while (tmp != NULL) - { - MetaWorkspace *workspace = tmp->data; - - g_assert (g_list_find (workspace->windows, window) == NULL); - g_assert (g_list_find (workspace->mru_list, window) == NULL); - - tmp = tmp->next; - } -#endif - - meta_stack_remove (window->screen->stack, window); - - if (window->frame) - meta_window_destroy_frame (window); - - if (window->withdrawn) - { - /* We need to clean off the window's state so it - * won't be restored if the app maps it again. - */ - meta_error_trap_push (window->display); - meta_verbose ("Cleaning state from window %s\n", window->desc); - XDeleteProperty (window->display->xdisplay, - window->xwindow, - window->display->atom__NET_WM_DESKTOP); - XDeleteProperty (window->display->xdisplay, - window->xwindow, - window->display->atom__NET_WM_STATE); - XDeleteProperty (window->display->xdisplay, - window->xwindow, - window->display->atom__NET_WM_FULLSCREEN_MONITORS); - set_wm_state (window, WithdrawnState); - meta_error_trap_pop (window->display, FALSE); - } - else - { - /* We need to put WM_STATE so that others will understand it on - * restart. - */ - if (!window->minimized) - { - meta_error_trap_push (window->display); - set_wm_state (window, NormalState); - meta_error_trap_pop (window->display, FALSE); - } - - /* And we need to be sure the window is mapped so other WMs - * know that it isn't Withdrawn - */ - meta_error_trap_push (window->display); - XMapWindow (window->display->xdisplay, - window->xwindow); - meta_error_trap_pop (window->display, FALSE); - } - - meta_window_ungrab_keys (window); - meta_display_ungrab_window_buttons (window->display, window->xwindow); - meta_display_ungrab_focus_window_button (window->display, window); - - meta_display_unregister_x_window (window->display, window->xwindow); - - - meta_error_trap_push (window->display); - - /* Put back anything we messed up */ - if (window->border_width != 0) - XSetWindowBorderWidth (window->display->xdisplay, - window->xwindow, - window->border_width); - - /* No save set */ - XRemoveFromSaveSet (window->display->xdisplay, - window->xwindow); - - /* Don't get events on not-managed windows */ - XSelectInput (window->display->xdisplay, - window->xwindow, - NoEventMask); - - /* Stop getting events for the window's _NET_WM_USER_TIME_WINDOW too */ - if (window->user_time_window != None) - { - meta_display_unregister_x_window (window->display, - window->user_time_window); - XSelectInput (window->display->xdisplay, - window->user_time_window, - NoEventMask); - window->user_time_window = None; - } - -#ifdef HAVE_SHAPE - if (META_DISPLAY_HAS_SHAPE (window->display)) - XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask); -#endif - - meta_error_trap_pop (window->display, FALSE); - - if (window->icon) - g_object_unref (G_OBJECT (window->icon)); - - if (window->mini_icon) - g_object_unref (G_OBJECT (window->mini_icon)); - - meta_icon_cache_free (&window->icon_cache); - - g_free (window->sm_client_id); - g_free (window->wm_client_machine); - g_free (window->startup_id); - g_free (window->role); - g_free (window->res_class); - g_free (window->res_name); - g_free (window->title); - g_free (window->icon_name); - g_free (window->desc); - g_free (window); -} - -static void -set_wm_state (MetaWindow *window, - int state) -{ - unsigned long data[2]; - - meta_verbose ("Setting wm state %s on %s\n", - wm_state_to_string (state), window->desc); - - /* Metacity doesn't use icon windows, so data[1] should be None - * according to the ICCCM 2.0 Section 4.1.3.1. - */ - data[0] = state; - data[1] = None; - - meta_error_trap_push (window->display); - XChangeProperty (window->display->xdisplay, window->xwindow, - window->display->atom_WM_STATE, - window->display->atom_WM_STATE, - 32, PropModeReplace, (guchar*) data, 2); - meta_error_trap_pop (window->display, FALSE); -} - -static void -set_net_wm_state (MetaWindow *window) -{ - int i; - unsigned long data[12]; - - i = 0; - if (window->shaded) - { - data[i] = window->display->atom__NET_WM_STATE_SHADED; - ++i; - } - if (window->wm_state_modal) - { - data[i] = window->display->atom__NET_WM_STATE_MODAL; - ++i; - } - if (window->skip_pager) - { - data[i] = window->display->atom__NET_WM_STATE_SKIP_PAGER; - ++i; - } - if (window->skip_taskbar) - { - data[i] = window->display->atom__NET_WM_STATE_SKIP_TASKBAR; - ++i; - } - if (window->maximized_horizontally) - { - data[i] = window->display->atom__NET_WM_STATE_MAXIMIZED_HORZ; - ++i; - } - if (window->maximized_vertically) - { - data[i] = window->display->atom__NET_WM_STATE_MAXIMIZED_VERT; - ++i; - } - if (window->fullscreen) - { - data[i] = window->display->atom__NET_WM_STATE_FULLSCREEN; - ++i; - } - if (!meta_window_showing_on_its_workspace (window) || window->shaded) - { - data[i] = window->display->atom__NET_WM_STATE_HIDDEN; - ++i; - } - if (window->wm_state_above) - { - data[i] = window->display->atom__NET_WM_STATE_ABOVE; - ++i; - } - if (window->wm_state_below) - { - data[i] = window->display->atom__NET_WM_STATE_BELOW; - ++i; - } - if (window->wm_state_demands_attention) - { - data[i] = window->display->atom__NET_WM_STATE_DEMANDS_ATTENTION; - ++i; - } - if (window->on_all_workspaces) - { - data[i] = window->display->atom__NET_WM_STATE_STICKY; - ++i; - } - - meta_verbose ("Setting _NET_WM_STATE with %d atoms\n", i); - - meta_error_trap_push (window->display); - XChangeProperty (window->display->xdisplay, window->xwindow, - window->display->atom__NET_WM_STATE, - XA_ATOM, - 32, PropModeReplace, (guchar*) data, i); - meta_error_trap_pop (window->display, FALSE); - - if (window->fullscreen) - { - data[0] = window->fullscreen_monitors[0]; - data[1] = window->fullscreen_monitors[1]; - data[2] = window->fullscreen_monitors[2]; - data[3] = window->fullscreen_monitors[3]; - - meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n"); - meta_error_trap_push (window->display); - XChangeProperty (window->display->xdisplay, - window->xwindow, - window->display->atom__NET_WM_FULLSCREEN_MONITORS, - XA_CARDINAL, 32, PropModeReplace, - (guchar*) data, 4); - meta_error_trap_pop (window->display, FALSE); - } -} - -gboolean -meta_window_located_on_workspace (MetaWindow *window, - MetaWorkspace *workspace) -{ - return (window->on_all_workspaces && window->screen == workspace->screen) || - (window->workspace == workspace); -} - -static gboolean -is_minimized_foreach (MetaWindow *window, - void *data) -{ - gboolean *result = data; - - *result = window->minimized; - if (*result) - return FALSE; /* stop as soon as we find one */ - else - return TRUE; -} - -static gboolean -ancestor_is_minimized (MetaWindow *window) -{ - gboolean is_minimized; - - is_minimized = FALSE; - - meta_window_foreach_ancestor (window, is_minimized_foreach, &is_minimized); - - return is_minimized; -} - -gboolean -meta_window_showing_on_its_workspace (MetaWindow *window) -{ - gboolean showing; - gboolean is_desktop_or_dock; - MetaWorkspace* workspace_of_window; - - showing = TRUE; - - /* 1. See if we're minimized */ - if (window->minimized) - showing = FALSE; - - /* 2. See if we're in "show desktop" mode */ - is_desktop_or_dock = FALSE; - is_desktop_or_dock_foreach (window, - &is_desktop_or_dock); - - meta_window_foreach_ancestor (window, is_desktop_or_dock_foreach, - &is_desktop_or_dock); - - if (window->on_all_workspaces) - workspace_of_window = window->screen->active_workspace; - else if (window->workspace) - workspace_of_window = window->workspace; - else /* This only seems to be needed for startup */ - workspace_of_window = NULL; - - if (showing && - workspace_of_window && workspace_of_window->showing_desktop && - !is_desktop_or_dock) - { - meta_verbose ("We're showing the desktop on the workspace(s) that window %s is on\n", - window->desc); - showing = FALSE; - } - - /* 3. See if an ancestor is minimized (note that - * ancestor's "mapped" field may not be up to date - * since it's being computed in this same idle queue) - */ - - if (showing) - { - if (ancestor_is_minimized (window)) - showing = FALSE; - } - -#if 0 - /* 4. See if we're drawing wireframe - */ - if (window->display->grab_window == window && - window->display->grab_wireframe_active) - showing = FALSE; -#endif - - return showing; -} - -gboolean -meta_window_should_be_showing (MetaWindow *window) -{ - gboolean on_workspace; - - meta_verbose ("Should be showing for window %s\n", window->desc); - - /* See if we're on the workspace */ - on_workspace = meta_window_located_on_workspace (window, - window->screen->active_workspace); - - if (!on_workspace) - meta_verbose ("Window %s is not on workspace %d\n", - window->desc, - meta_workspace_index (window->screen->active_workspace)); - else - meta_verbose ("Window %s is on the active workspace %d\n", - window->desc, - meta_workspace_index (window->screen->active_workspace)); - - if (window->on_all_workspaces) - meta_verbose ("Window %s is on all workspaces\n", window->desc); - - return on_workspace && meta_window_showing_on_its_workspace (window); -} - -static void -finish_minimize (gpointer data) -{ - MetaWindow *window = data; - /* FIXME: It really sucks to put timestamp pinging here; it'd - * probably make more sense in implement_showing() so that it's at - * least not duplicated in meta_window_show; but since - * finish_minimize is a callback making things just slightly icky, I - * haven't done that yet. - */ - guint32 timestamp = meta_display_get_current_time_roundtrip (window->display); - - meta_window_hide (window); - if (window->has_focus) - { - meta_workspace_focus_default_window (window->screen->active_workspace, - window, - timestamp); - } -} - -static void -implement_showing (MetaWindow *window, - gboolean showing) -{ - /* Actually show/hide the window */ - meta_verbose ("Implement showing = %d for window %s\n", - showing, window->desc); - - if (!showing) - { - gboolean on_workspace; - - on_workspace = meta_window_located_on_workspace (window, - window->screen->active_workspace); - - /* Really this effects code should probably - * be in meta_window_hide so the window->mapped - * test isn't duplicated here. Anyhow, we animate - * if we are mapped now, we are supposed to - * be minimized, and we are on the current workspace. - */ - if (on_workspace && window->minimized && window->mapped && - !meta_prefs_get_reduced_resources ()) - { - MetaRectangle icon_rect, window_rect; - gboolean result; - - /* Check if the window has an icon geometry */ - result = meta_window_get_icon_geometry (window, &icon_rect); - - if (!result) - { - /* just animate into the corner somehow - maybe - * not a good idea... - */ - icon_rect.x = window->screen->rect.width; - icon_rect.y = window->screen->rect.height; - icon_rect.width = 1; - icon_rect.height = 1; - } - - meta_window_get_outer_rect (window, &window_rect); - - meta_effect_run_minimize (window, - &window_rect, - &icon_rect, - finish_minimize, - window); - } - else - { - finish_minimize (window); - } - } - else - { - meta_window_show (window); - } -} - -void -meta_window_calc_showing (MetaWindow *window) -{ - implement_showing (window, meta_window_should_be_showing (window)); -} - -static guint queue_idle[NUMBER_OF_QUEUES] = {0, 0, 0}; -static GSList *queue_pending[NUMBER_OF_QUEUES] = {NULL, NULL, NULL}; - -static int -stackcmp (gconstpointer a, gconstpointer b) -{ - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; - - if (aw->screen != bw->screen) - return 0; /* don't care how they sort with respect to each other */ - else - return meta_stack_windows_cmp (aw->screen->stack, - aw, bw); -} - -static gboolean -idle_calc_showing (gpointer data) -{ - GSList *tmp; - GSList *copy; - GSList *should_show; - GSList *should_hide; - GSList *unplaced; - GSList *displays; - MetaWindow *first_window; - guint queue_index = GPOINTER_TO_INT (data); - - meta_topic (META_DEBUG_WINDOW_STATE, - "Clearing the calc_showing queue\n"); - - /* Work with a copy, for reentrancy. The allowed reentrancy isn't - * complete; destroying a window while we're in here would result in - * badness. But it's OK to queue/unqueue calc_showings. - */ - copy = g_slist_copy (queue_pending[queue_index]); - g_slist_free (queue_pending[queue_index]); - queue_pending[queue_index] = NULL; - queue_idle[queue_index] = 0; - - destroying_windows_disallowed += 1; - - /* We map windows from top to bottom and unmap from bottom to - * top, to avoid extra expose events. The exception is - * for unplaced windows, which have to be mapped from bottom to - * top so placement works. - */ - should_show = NULL; - should_hide = NULL; - unplaced = NULL; - displays = NULL; - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - if (!window->placed) - unplaced = g_slist_prepend (unplaced, window); - else if (meta_window_should_be_showing (window)) - should_show = g_slist_prepend (should_show, window); - else - should_hide = g_slist_prepend (should_hide, window); - - tmp = tmp->next; - } - - /* bottom to top */ - unplaced = g_slist_sort (unplaced, stackcmp); - should_hide = g_slist_sort (should_hide, stackcmp); - /* top to bottom */ - should_show = g_slist_sort (should_show, stackcmp); - should_show = g_slist_reverse (should_show); - - first_window = copy->data; - - meta_display_grab (first_window->display); - - tmp = unplaced; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - meta_window_calc_showing (window); - - tmp = tmp->next; - } - - tmp = should_show; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - implement_showing (window, TRUE); - - tmp = tmp->next; - } - - tmp = should_hide; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - implement_showing (window, FALSE); - - tmp = tmp->next; - } - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - /* important to set this here for reentrancy - - * if we queue a window again while it's in "copy", - * then queue_calc_showing will just return since - * we are still in the calc_showing queue - */ - window->is_in_queues &= ~META_QUEUE_CALC_SHOWING; - - tmp = tmp->next; - } - - if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK) - { - /* When display->mouse_mode is false, we want to ignore - * EnterNotify events unless they come from mouse motion. To do - * that, we set a sentinel property on the root window if we're - * not in mouse_mode. - */ - tmp = should_show; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (!window->display->mouse_mode) - meta_display_increment_focus_sentinel (window->display); - - tmp = tmp->next; - } - } - - meta_display_ungrab (first_window->display); - - g_slist_free (copy); - - g_slist_free (unplaced); - g_slist_free (should_show); - g_slist_free (should_hide); - g_slist_free (displays); - - destroying_windows_disallowed -= 1; - - return FALSE; -} - -static const gchar* meta_window_queue_names[NUMBER_OF_QUEUES] = - {"calc_showing", "move_resize", "update_icon"}; - -static void -meta_window_unqueue (MetaWindow *window, guint queuebits) -{ - gint queuenum; - - for (queuenum=0; queuenum<NUMBER_OF_QUEUES; queuenum++) - { - if ((queuebits & 1<<queuenum) /* they have asked to unqueue */ - && - (window->is_in_queues & 1<<queuenum)) /* it's in the queue */ - { - - meta_topic (META_DEBUG_WINDOW_STATE, - "Removing %s from the %s queue\n", - window->desc, - meta_window_queue_names[queuenum]); - - /* Note that window may not actually be in the queue - * because it may have been in "copy" inside the idle handler - */ - queue_pending[queuenum] = g_slist_remove (queue_pending[queuenum], window); - window->is_in_queues &= ~(1<<queuenum); - - /* Okay, so maybe we've used up all the entries in the queue. - * In that case, we should kill the function that deals with - * the queue, because there's nothing left for it to do. - */ - if (queue_pending[queuenum] == NULL && queue_idle[queuenum] != 0) - { - g_source_remove (queue_idle[queuenum]); - queue_idle[queuenum] = 0; - } - } - } -} - -static void -meta_window_flush_calc_showing (MetaWindow *window) -{ - if (window->is_in_queues & META_QUEUE_CALC_SHOWING) - { - meta_window_unqueue (window, META_QUEUE_CALC_SHOWING); - meta_window_calc_showing (window); - } -} - -void -meta_window_queue (MetaWindow *window, guint queuebits) -{ - guint queuenum; - - for (queuenum=0; queuenum<NUMBER_OF_QUEUES; queuenum++) - { - if (queuebits & 1<<queuenum) - { - /* Data which varies between queues. - * Yes, these do look a lot like associative arrays: - * I seem to be turning into a Perl programmer. - */ - - const gint window_queue_idle_priority[NUMBER_OF_QUEUES] = - { - G_PRIORITY_DEFAULT_IDLE, /* CALC_SHOWING */ - META_PRIORITY_RESIZE, /* MOVE_RESIZE */ - G_PRIORITY_DEFAULT_IDLE /* UPDATE_ICON */ - }; - - const GSourceFunc window_queue_idle_handler[NUMBER_OF_QUEUES] = - { - idle_calc_showing, - idle_move_resize, - idle_update_icon, - }; - - /* If we're about to drop the window, there's no point in putting - * it on a queue. - */ - if (window->unmanaging) - break; - - /* If the window already claims to be in that queue, there's no - * point putting it in the queue. - */ - if (window->is_in_queues & 1<<queuenum) - break; - - meta_topic (META_DEBUG_WINDOW_STATE, - "Putting %s in the %s queue\n", - window->desc, - meta_window_queue_names[queuenum]); - - /* So, mark it as being in this queue. */ - window->is_in_queues |= 1<<queuenum; - - /* There's not a lot of point putting things into a queue if - * nobody's on the other end pulling them out. Therefore, - * let's check to see whether an idle handler exists to do - * that. If not, we'll create one. - */ - - if (queue_idle[queuenum] == 0) - queue_idle[queuenum] = g_idle_add_full - ( - window_queue_idle_priority[queuenum], - window_queue_idle_handler[queuenum], - GUINT_TO_POINTER(queuenum), - NULL - ); - - /* And now we actually put it on the queue. */ - queue_pending[queuenum] = g_slist_prepend (queue_pending[queuenum], - window); - } - } -} - -static gboolean -intervening_user_event_occurred (MetaWindow *window) -{ - guint32 compare; - MetaWindow *focus_window; - - focus_window = window->display->focus_window; - - meta_topic (META_DEBUG_STARTUP, - "COMPARISON:\n" - " net_wm_user_time_set : %d\n" - " net_wm_user_time : %u\n" - " initial_timestamp_set: %d\n" - " initial_timestamp : %u\n", - window->net_wm_user_time_set, - window->net_wm_user_time, - window->initial_timestamp_set, - window->initial_timestamp); - if (focus_window != NULL) - { - meta_topic (META_DEBUG_STARTUP, - "COMPARISON (continued):\n" - " focus_window : %s\n" - " fw->net_wm_user_time_set : %d\n" - " fw->net_wm_user_time : %u\n", - focus_window->desc, - focus_window->net_wm_user_time_set, - focus_window->net_wm_user_time); - } - - /* We expect the most common case for not focusing a new window - * to be when a hint to not focus it has been set. Since we can - * deal with that case rapidly, we use special case it--this is - * merely a preliminary optimization. :) - */ - if ( ((window->net_wm_user_time_set == TRUE) && - (window->net_wm_user_time == 0)) - || - ((window->initial_timestamp_set == TRUE) && - (window->initial_timestamp == 0))) - { - meta_topic (META_DEBUG_STARTUP, - "window %s explicitly requested no focus\n", - window->desc); - return TRUE; - } - - if (!(window->net_wm_user_time_set) && !(window->initial_timestamp_set)) - { - meta_topic (META_DEBUG_STARTUP, - "no information about window %s found\n", - window->desc); - return FALSE; - } - - if (focus_window != NULL && - !focus_window->net_wm_user_time_set) - { - meta_topic (META_DEBUG_STARTUP, - "focus window, %s, doesn't have a user time set yet!\n", - window->desc); - return FALSE; - } - - /* To determine the "launch" time of an application, - * startup-notification can set the TIMESTAMP and the - * application (usually via its toolkit such as gtk or qt) can - * set the _NET_WM_USER_TIME. If both are set, then it means - * the user has interacted with the application since it - * launched, and _NET_WM_USER_TIME is the value that should be - * used in the comparison. - */ - compare = window->initial_timestamp_set ? window->initial_timestamp : 0; - compare = window->net_wm_user_time_set ? window->net_wm_user_time : compare; - - if ((focus_window != NULL) && - XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time)) - { - meta_topic (META_DEBUG_STARTUP, - "window %s focus prevented by other activity; %u < %u\n", - window->desc, - compare, - focus_window->net_wm_user_time); - return TRUE; - } - else - { - meta_topic (META_DEBUG_STARTUP, - "new window %s with no intervening events\n", - window->desc); - return FALSE; - } -} - -/* This function is an ugly hack. It's experimental in nature and ought to be - * replaced by a real hint from the app to the WM if we decide the experimental - * behavior is worthwhile. The basic idea is to get more feedback about how - * usage scenarios of "strict" focus users and what they expect. See #326159. - */ -gboolean -__window_is_terminal (MetaWindow *window) -{ - if (window == NULL || window->res_class == NULL) - return FALSE; - - /* - * Compare res_class, which is not user-settable, and thus theoretically - * a more-reliable indication of term-ness. - */ - - /* gnome-terminal -- if you couldn't guess */ - if (strcmp (window->res_class, "Gnome-terminal") == 0) - return TRUE; - /* xterm, rxvt, aterm */ - else if (strcmp (window->res_class, "XTerm") == 0) - return TRUE; - /* konsole, KDE's terminal program */ - else if (strcmp (window->res_class, "Konsole") == 0) - return TRUE; - /* rxvt-unicode */ - else if (strcmp (window->res_class, "URxvt") == 0) - return TRUE; - /* eterm */ - else if (strcmp (window->res_class, "Eterm") == 0) - return TRUE; - /* KTerm -- some terminal not KDE based; so not like Konsole */ - else if (strcmp (window->res_class, "KTerm") == 0) - return TRUE; - /* Multi-gnome-terminal */ - else if (strcmp (window->res_class, "Multi-gnome-terminal") == 0) - return TRUE; - /* mlterm ("multi lingual terminal emulator on X") */ - else if (strcmp (window->res_class, "mlterm") == 0) - return TRUE; - - return FALSE; -} - -/* This function determines what state the window should have assuming that it - * and the focus_window have no relation - */ -static void -window_state_on_map (MetaWindow *window, - gboolean *takes_focus, - gboolean *places_on_top) -{ - gboolean intervening_events; - - intervening_events = intervening_user_event_occurred (window); - - *takes_focus = !intervening_events; - *places_on_top = *takes_focus; - - /* don't initially focus windows that are intended to not accept - * focus - */ - if (!(window->input || window->take_focus)) - { - *takes_focus = FALSE; - return; - } - - /* Terminal usage may be different; some users intend to launch - * many apps in quick succession or to just view things in the new - * window while still interacting with the terminal. In that case, - * apps launched from the terminal should not take focus. This - * isn't quite the same as not allowing focus to transfer from - * terminals due to new window map, but the latter is a much easier - * approximation to enforce so we do that. - */ - if (*takes_focus && - meta_prefs_get_focus_new_windows () == META_FOCUS_NEW_WINDOWS_STRICT && - !window->display->allow_terminal_deactivation && - __window_is_terminal (window->display->focus_window) && - !meta_window_is_ancestor_of_transient (window->display->focus_window, - window)) - { - meta_topic (META_DEBUG_FOCUS, - "focus_window is terminal; not focusing new window.\n"); - *takes_focus = FALSE; - *places_on_top = FALSE; - } - - switch (window->type) - { - case META_WINDOW_UTILITY: - case META_WINDOW_TOOLBAR: - *takes_focus = FALSE; - *places_on_top = FALSE; - break; - case META_WINDOW_DOCK: - case META_WINDOW_DESKTOP: - case META_WINDOW_SPLASHSCREEN: - case META_WINDOW_MENU: - /* don't focus any of these; places_on_top may be irrelevant for some of - * these (e.g. dock)--but you never know--the focus window might also be - * of the same type in some weird situation... - */ - *takes_focus = FALSE; - break; - case META_WINDOW_NORMAL: - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - /* The default is correct for these */ - break; - } -} - -static gboolean -windows_overlap (const MetaWindow *w1, const MetaWindow *w2) -{ - MetaRectangle w1rect, w2rect; - meta_window_get_outer_rect (w1, &w1rect); - meta_window_get_outer_rect (w2, &w2rect); - return meta_rectangle_overlap (&w1rect, &w2rect); -} - -/* Returns whether a new window would be covered by any - * existing window on the same workspace that is set - * to be "above" ("always on top"). A window that is not - * set "above" would be underneath the new window anyway. - * - * We take "covered" to mean even partially covered, but - * some people might prefer entirely covered. I think it - * is more useful to behave this way if any part of the - * window is covered, because a partial coverage could be - * (say) ninety per cent and almost indistinguishable from total. - */ -static gboolean -window_would_be_covered (const MetaWindow *newbie) -{ - MetaWorkspace *workspace = newbie->workspace; - GList *tmp, *windows; - - windows = meta_workspace_list_windows (workspace); - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->wm_state_above && w != newbie) - { - /* We have found a window that is "above". Perhaps it overlaps. */ - if (windows_overlap (w, newbie)) - { - g_list_free (windows); /* clean up... */ - return TRUE; /* yes, it does */ - } - } - - tmp = tmp->next; - } - - g_list_free (windows); - return FALSE; /* none found */ -} - -/* XXX META_EFFECT_*_MAP */ -void -meta_window_show (MetaWindow *window) -{ - gboolean did_show; - gboolean takes_focus_on_map; - gboolean place_on_top_on_map; - gboolean needs_stacking_adjustment; - MetaWindow *focus_window; - guint32 timestamp; - - /* FIXME: It really sucks to put timestamp pinging here; it'd - * probably make more sense in implement_showing() so that it's at - * least not duplicated in finish_minimize. *shrug* - */ - timestamp = meta_display_get_current_time_roundtrip (window->display); - - meta_topic (META_DEBUG_WINDOW_STATE, - "Showing window %s, shaded: %d iconic: %d placed: %d\n", - window->desc, window->shaded, window->iconic, window->placed); - - focus_window = window->display->focus_window; /* May be NULL! */ - did_show = FALSE; - window_state_on_map (window, &takes_focus_on_map, &place_on_top_on_map); - needs_stacking_adjustment = FALSE; - - meta_topic (META_DEBUG_WINDOW_STATE, - "Window %s %s focus on map, and %s place on top on map.\n", - window->desc, - takes_focus_on_map ? "does" : "does not", - place_on_top_on_map ? "does" : "does not"); - - /* Now, in some rare cases we should *not* put a new window on top. - * These cases include certain types of windows showing for the first - * time, and any window which would be covered because of another window - * being set "above" ("always on top"). - * - * FIXME: Although "place_on_top_on_map" and "takes_focus_on_map" are - * generally based on the window type, there is a special case when the - * focus window is a terminal for them both to be false; this should - * probably rather be a term in the "if" condition below. - */ - - if ( focus_window != NULL && window->showing_for_first_time && - ( (!place_on_top_on_map && !takes_focus_on_map) || - window_would_be_covered (window) ) - ) { - if (meta_window_is_ancestor_of_transient (focus_window, window)) - { - /* This happens for error dialogs or alerts; these need to remain on - * top, but it would be confusing to have its ancestor remain - * focused. - */ - meta_topic (META_DEBUG_STARTUP, - "The focus window %s is an ancestor of the newly mapped " - "window %s which isn't being focused. Unfocusing the " - "ancestor.\n", - focus_window->desc, window->desc); - - meta_display_focus_the_no_focus_window (window->display, - window->screen, - timestamp); - } - else - { - needs_stacking_adjustment = TRUE; - if (!window->placed) - window->denied_focus_and_not_transient = TRUE; - } - } - - if (!window->placed) - { - /* We have to recalc the placement here since other windows may - * have been mapped/placed since we last did constrain_position - */ - - /* calc_placement is an efficiency hack to avoid - * multiple placement calculations before we finally - * show the window. - */ - window->calc_placement = TRUE; - meta_window_move_resize_now (window); - window->calc_placement = FALSE; - - /* don't ever do the initial position constraint thing again. - * This is toggled here so that initially-iconified windows - * still get placed when they are ultimately shown. - */ - window->placed = TRUE; - - /* Don't want to accidentally reuse the fact that we had been denied - * focus in any future constraints unless we're denied focus again. - */ - window->denied_focus_and_not_transient = FALSE; - } - - if (needs_stacking_adjustment) - { - gboolean overlap; - - /* This window isn't getting focus on map. We may need to do some - * special handing with it in regards to - * - the stacking of the window - * - the MRU position of the window - * - the demands attention setting of the window - * - * Firstly, set the flag so we don't give the window focus anyway - * and confuse people. - */ - - takes_focus_on_map = FALSE; - - overlap = windows_overlap (window, focus_window); - - /* We want alt tab to go to the denied-focus window */ - ensure_mru_position_after (window, focus_window); - - /* We don't want the denied-focus window to obscure the focus - * window, and if we're in both click-to-focus mode and - * raise-on-click mode then we want to maintain the invariant - * that MRU order == stacking order. The need for this if - * comes from the fact that in sloppy/mouse focus the focus - * window may not overlap other windows and also can be - * considered "below" them; this combination means that - * placing the denied-focus window "below" the focus window - * in the stack when it doesn't overlap it confusingly places - * that new window below a lot of other windows. - */ - if (overlap || - (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK && - meta_prefs_get_raise_on_click ())) - meta_window_stack_just_below (window, focus_window); - - /* If the window will be obscured by the focus window, then the - * user might not notice the window appearing so set the - * demands attention hint. - * - * We set the hint ourselves rather than calling - * meta_window_set_demands_attention() because that would cause - * a recalculation of overlap, and a call to set_net_wm_state() - * which we are going to call ourselves here a few lines down. - */ - if (overlap) - window->wm_state_demands_attention = TRUE; - } - - /* Shaded means the frame is mapped but the window is not */ - - if (window->frame && !window->frame->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "Frame actually needs map\n"); - window->frame->mapped = TRUE; - meta_ui_map_frame (window->screen->ui, window->frame->xwindow); - did_show = TRUE; - } - - if (window->shaded) - { - if (window->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "%s actually needs unmap (shaded)\n", window->desc); - meta_topic (META_DEBUG_WINDOW_STATE, - "Incrementing unmaps_pending on %s for shade\n", - window->desc); - window->mapped = FALSE; - window->unmaps_pending += 1; - meta_error_trap_push (window->display); - XUnmapWindow (window->display->xdisplay, window->xwindow); - meta_error_trap_pop (window->display, FALSE); - } - - if (!window->iconic) - { - window->iconic = TRUE; - set_wm_state (window, IconicState); - } - } - else - { - if (!window->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "%s actually needs map\n", window->desc); - window->mapped = TRUE; - meta_error_trap_push (window->display); - XMapWindow (window->display->xdisplay, window->xwindow); - meta_error_trap_pop (window->display, FALSE); - did_show = TRUE; - - if (window->was_minimized) - { - MetaRectangle window_rect; - MetaRectangle icon_rect; - - window->was_minimized = FALSE; - - if (meta_window_get_icon_geometry (window, &icon_rect)) - { - meta_window_get_outer_rect (window, &window_rect); - - meta_effect_run_unminimize (window, - &window_rect, - &icon_rect, - NULL, NULL); - } - } - } - - if (window->iconic) - { - window->iconic = FALSE; - set_wm_state (window, NormalState); - } - } - - /* We don't want to worry about all cases from inside - * implement_showing(); we only want to worry about focus if this - * window has not been shown before. - */ - if (window->showing_for_first_time) - { - window->showing_for_first_time = FALSE; - if (takes_focus_on_map) - { - meta_window_focus (window, timestamp); - } - else - { - /* Prevent EnterNotify events in sloppy/mouse focus from - * erroneously focusing the window that had been denied - * focus. FIXME: This introduces a race; I have a couple - * ideas for a better way to accomplish the same thing, but - * they're more involved so do it this way for now. - */ - meta_display_increment_focus_sentinel (window->display); - } - } - - set_net_wm_state (window); - - if (did_show && window->struts) - { - meta_topic (META_DEBUG_WORKAREA, - "Mapped window %s with struts, so invalidating work areas\n", - window->desc); - invalidate_work_areas (window); - } -} - -/* XXX META_EFFECT_*_UNMAP */ -static void -meta_window_hide (MetaWindow *window) -{ - gboolean did_hide; - - meta_topic (META_DEBUG_WINDOW_STATE, - "Hiding window %s\n", window->desc); - - did_hide = FALSE; - - if (window->frame && window->frame->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, "Frame actually needs unmap\n"); - window->frame->mapped = FALSE; - meta_ui_unmap_frame (window->screen->ui, window->frame->xwindow); - did_hide = TRUE; - } - - if (window->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "%s actually needs unmap\n", window->desc); - meta_topic (META_DEBUG_WINDOW_STATE, - "Incrementing unmaps_pending on %s for hide\n", - window->desc); - window->mapped = FALSE; - window->unmaps_pending += 1; - meta_error_trap_push (window->display); - XUnmapWindow (window->display->xdisplay, window->xwindow); - meta_error_trap_pop (window->display, FALSE); - did_hide = TRUE; - } - - if (!window->iconic) - { - window->iconic = TRUE; - set_wm_state (window, IconicState); - } - - set_net_wm_state (window); - - if (did_hide && window->struts) - { - meta_topic (META_DEBUG_WORKAREA, - "Unmapped window %s with struts, so invalidating work areas\n", - window->desc); - invalidate_work_areas (window); - } -} - -static gboolean -queue_calc_showing_func (MetaWindow *window, - void *data) -{ - meta_window_queue(window, META_QUEUE_CALC_SHOWING); - return TRUE; -} - -void -meta_window_minimize (MetaWindow *window) -{ - if (!window->minimized) - { - window->minimized = TRUE; - meta_window_queue(window, META_QUEUE_CALC_SHOWING); - - meta_window_foreach_transient (window, - queue_calc_showing_func, - NULL); - - if (window->has_focus) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing default window due to minimization of focus window %s\n", - window->desc); - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Minimizing window %s which doesn't have the focus\n", - window->desc); - } - } -} - -void -meta_window_unminimize (MetaWindow *window) -{ - if (window->minimized) - { - window->minimized = FALSE; - window->was_minimized = TRUE; - meta_window_queue(window, META_QUEUE_CALC_SHOWING); - - meta_window_foreach_transient (window, - queue_calc_showing_func, - NULL); - } -} - -static void -ensure_size_hints_satisfied (MetaRectangle *rect, - const XSizeHints *size_hints) -{ - int minw, minh, maxw, maxh; /* min/max width/height */ - int basew, baseh, winc, hinc; /* base width/height, width/height increment */ - int extra_width, extra_height; - - minw = size_hints->min_width; minh = size_hints->min_height; - maxw = size_hints->max_width; maxh = size_hints->max_height; - basew = size_hints->base_width; baseh = size_hints->base_height; - winc = size_hints->width_inc; hinc = size_hints->height_inc; - - /* First, enforce min/max size constraints */ - rect->width = CLAMP (rect->width, minw, maxw); - rect->height = CLAMP (rect->height, minh, maxh); - - /* Now, verify size increment constraints are satisfied, or make them be */ - extra_width = (rect->width - basew) % winc; - extra_height = (rect->height - baseh) % hinc; - - rect->width -= extra_width; - rect->height -= extra_height; - - /* Adjusting width/height down, as done above, may violate minimum size - * constraints, so one last fix. - */ - if (rect->width < minw) - rect->width += ((minw - rect->width)/winc + 1)*winc; - if (rect->height < minh) - rect->height += ((minh - rect->height)/hinc + 1)*hinc; -} - -static void -meta_window_save_rect (MetaWindow *window) -{ - if (!(META_WINDOW_MAXIMIZED (window) || window->fullscreen)) - { - /* save size/pos as appropriate args for move_resize */ - if (!window->maximized_horizontally) - { - window->saved_rect.x = window->rect.x; - window->saved_rect.width = window->rect.width; - if (window->frame) - window->saved_rect.x += window->frame->rect.x; - } - if (!window->maximized_vertically) - { - window->saved_rect.y = window->rect.y; - window->saved_rect.height = window->rect.height; - if (window->frame) - window->saved_rect.y += window->frame->rect.y; - } - } -} - -/** - * Save the user_rect regardless of whether the window is maximized or - * fullscreen. See save_user_window_placement() for most uses. - * - * \param window Store current position of this window for future reference - */ -static void -force_save_user_window_placement (MetaWindow *window) -{ - meta_window_get_client_root_coords (window, &window->user_rect); -} - -/** - * Save the user_rect, but only if the window is neither maximized nor - * fullscreen, otherwise the window may snap back to those dimensions - * (bug #461927). - * - * \param window Store current position of this window for future reference - */ -static void -save_user_window_placement (MetaWindow *window) -{ - if (!(META_WINDOW_MAXIMIZED (window) || window->fullscreen)) - { - MetaRectangle user_rect; - - meta_window_get_client_root_coords (window, &user_rect); - - if (!window->maximized_horizontally) - { - window->user_rect.x = user_rect.x; - window->user_rect.width = user_rect.width; - } - if (!window->maximized_vertically) - { - window->user_rect.y = user_rect.y; - window->user_rect.height = user_rect.height; - } - } -} - -void -meta_window_maximize_internal (MetaWindow *window, - MetaMaximizeFlags directions, - MetaRectangle *saved_rect) -{ - /* At least one of the two directions ought to be set */ - gboolean maximize_horizontally, maximize_vertically; - maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; - maximize_vertically = directions & META_MAXIMIZE_VERTICAL; - g_assert (maximize_horizontally || maximize_vertically); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Maximizing %s%s\n", - window->desc, - maximize_horizontally && maximize_vertically ? "" : - maximize_horizontally ? " horizontally" : - maximize_vertically ? " vertically" : "BUGGGGG"); - - if (saved_rect != NULL) - window->saved_rect = *saved_rect; - else - meta_window_save_rect (window); - - window->maximized_horizontally = - window->maximized_horizontally || maximize_horizontally; - window->maximized_vertically = - window->maximized_vertically || maximize_vertically; - - /* Fix for #336850: If the frame shape isn't reapplied, it is - * possible that the frame will retains its rounded corners. That - * happens if the client's size when maximized equals the unmaximized - * size. - */ - if (window->frame) - window->frame->need_reapply_frame_shape = TRUE; - - recalc_window_features (window); - set_net_wm_state (window); -} - -void -meta_window_maximize (MetaWindow *window, - MetaMaximizeFlags directions) -{ - /* At least one of the two directions ought to be set */ - gboolean maximize_horizontally, maximize_vertically; - maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; - maximize_vertically = directions & META_MAXIMIZE_VERTICAL; - g_assert (maximize_horizontally || maximize_vertically); - - /* Only do something if the window isn't already maximized in the - * given direction(s). - */ - if ((maximize_horizontally && !window->maximized_horizontally) || - (maximize_vertically && !window->maximized_vertically)) - { - if (window->shaded && maximize_vertically) - { - /* Shading sucks anyway; I'm not adding a timestamp argument - * to this function just for this niche usage & corner case. - */ - guint32 timestamp = - meta_display_get_current_time_roundtrip (window->display); - meta_window_unshade (window, timestamp); - } - - /* if the window hasn't been placed yet, we'll maximize it then - */ - if (!window->placed) - { - window->maximize_horizontally_after_placement = - window->maximize_horizontally_after_placement || - maximize_horizontally; - window->maximize_vertically_after_placement = - window->maximize_vertically_after_placement || - maximize_vertically; - return; - } - - meta_window_maximize_internal (window, - directions, - NULL); - - /* move_resize with new maximization constraints - */ - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); - } -} - -static void -unmaximize_window_before_freeing (MetaWindow *window) -{ - meta_topic (META_DEBUG_WINDOW_OPS, - "Unmaximizing %s just before freeing\n", - window->desc); - - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; - - if (window->withdrawn) /* See bug #137185 */ - { - window->rect = window->saved_rect; - set_net_wm_state (window); - } - else if (window->screen->closing) /* See bug #358042 */ - { - /* Do NOT update net_wm_state: this screen is closing, - * it likely will be managed by another window manager - * that will need the current _NET_WM_STATE atoms. - * Moreover, it will need to know the unmaximized geometry, - * therefore move_resize the window to saved_rect here - * before closing it. */ - meta_window_move_resize (window, - FALSE, - window->saved_rect.x, - window->saved_rect.y, - window->saved_rect.width, - window->saved_rect.height); - } -} - -void -meta_window_unmaximize (MetaWindow *window, - MetaMaximizeFlags directions) -{ - /* At least one of the two directions ought to be set */ - gboolean unmaximize_horizontally, unmaximize_vertically; - unmaximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; - unmaximize_vertically = directions & META_MAXIMIZE_VERTICAL; - g_assert (unmaximize_horizontally || unmaximize_vertically); - - /* Only do something if the window isn't already maximized in the - * given direction(s). - */ - if ((unmaximize_horizontally && window->maximized_horizontally) || - (unmaximize_vertically && window->maximized_vertically)) - { - MetaRectangle target_rect; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Unmaximizing %s%s\n", - window->desc, - unmaximize_horizontally && unmaximize_vertically ? "" : - unmaximize_horizontally ? " horizontally" : - unmaximize_vertically ? " vertically" : "BUGGGGG"); - - window->maximized_horizontally = - window->maximized_horizontally && !unmaximize_horizontally; - window->maximized_vertically = - window->maximized_vertically && !unmaximize_vertically; - - /* Unmaximize to the saved_rect position in the direction(s) - * being unmaximized. - */ - meta_window_get_client_root_coords (window, &target_rect); - if (unmaximize_horizontally) - { - target_rect.x = window->saved_rect.x; - target_rect.width = window->saved_rect.width; - } - if (unmaximize_vertically) - { - target_rect.y = window->saved_rect.y; - target_rect.height = window->saved_rect.height; - } - - /* Window's size hints may have changed while maximized, making - * saved_rect invalid. #329152 - */ - ensure_size_hints_satisfied (&target_rect, &window->size_hints); - - /* When we unmaximize, if we're doing a mouse move also we could - * get the window suddenly jumping to the upper left corner of - * the workspace, since that's where it was when the grab op - * started. So we need to update the grab state. - */ - if (meta_grab_op_is_moving (window->display->grab_op) && - window->display->grab_window == window) - { - window->display->grab_anchor_window_pos = target_rect; - } - - meta_window_move_resize (window, - FALSE, - target_rect.x, - target_rect.y, - target_rect.width, - target_rect.height); - - if (window->display->grab_wireframe_active) - { - window->display->grab_wireframe_rect = target_rect; - } - - recalc_window_features (window); - set_net_wm_state (window); - } -} - -void -meta_window_make_above (MetaWindow *window) -{ - window->wm_state_above = TRUE; - meta_window_update_layer (window); - meta_window_raise (window); - set_net_wm_state (window); -} - -void -meta_window_unmake_above (MetaWindow *window) -{ - window->wm_state_above = FALSE; - meta_window_raise (window); - meta_window_update_layer (window); - set_net_wm_state (window); -} - -void -meta_window_make_fullscreen_internal (MetaWindow *window) -{ - if (!window->fullscreen) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Fullscreening %s\n", window->desc); - - if (window->shaded) - { - /* Shading sucks anyway; I'm not adding a timestamp argument - * to this function just for this niche usage & corner case. - */ - guint32 timestamp = - meta_display_get_current_time_roundtrip (window->display); - meta_window_unshade (window, timestamp); - } - - meta_window_save_rect (window); - - window->fullscreen = TRUE; - - meta_stack_freeze (window->screen->stack); - meta_window_update_layer (window); - - meta_window_raise (window); - meta_stack_thaw (window->screen->stack); - - recalc_window_features (window); - set_net_wm_state (window); - } -} - -void -meta_window_make_fullscreen (MetaWindow *window) -{ - if (!window->fullscreen) - { - meta_window_make_fullscreen_internal (window); - /* move_resize with new constraints - */ - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); - } -} - -void -meta_window_unmake_fullscreen (MetaWindow *window) -{ - if (window->fullscreen) - { - MetaRectangle target_rect; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Unfullscreening %s\n", window->desc); - - window->fullscreen = FALSE; - target_rect = window->saved_rect; - - /* Window's size hints may have changed while maximized, making - * saved_rect invalid. #329152 - */ - ensure_size_hints_satisfied (&target_rect, &window->size_hints); - - meta_window_move_resize (window, - FALSE, - target_rect.x, - target_rect.y, - target_rect.width, - target_rect.height); - - meta_window_update_layer (window); - - recalc_window_features (window); - set_net_wm_state (window); - } -} - -void -meta_window_update_fullscreen_monitors (MetaWindow *window, - unsigned long top, - unsigned long bottom, - unsigned long left, - unsigned long right) -{ - if ((int)top < window->screen->n_xinerama_infos && - (int)bottom < window->screen->n_xinerama_infos && - (int)left < window->screen->n_xinerama_infos && - (int)right < window->screen->n_xinerama_infos) - { - window->fullscreen_monitors[0] = top; - window->fullscreen_monitors[1] = bottom; - window->fullscreen_monitors[2] = left; - window->fullscreen_monitors[3] = right; - } - else - { - window->fullscreen_monitors[0] = -1; - } - - if (window->fullscreen) - { - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); - } -} - -void -meta_window_shade (MetaWindow *window, - guint32 timestamp) -{ - meta_topic (META_DEBUG_WINDOW_OPS, - "Shading %s\n", window->desc); - if (!window->shaded) - { - window->shaded = TRUE; - - meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); - - /* After queuing the calc showing, since _focus flushes it, - * and we need to focus the frame - */ - meta_topic (META_DEBUG_FOCUS, - "Re-focusing window %s after shading it\n", - window->desc); - meta_window_focus (window, timestamp); - - set_net_wm_state (window); - } -} - -void -meta_window_unshade (MetaWindow *window, - guint32 timestamp) -{ - meta_topic (META_DEBUG_WINDOW_OPS, - "Unshading %s\n", window->desc); - if (window->shaded) - { - window->shaded = FALSE; - meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); - - /* focus the window */ - meta_topic (META_DEBUG_FOCUS, - "Focusing window %s after unshading it\n", - window->desc); - meta_window_focus (window, timestamp); - - set_net_wm_state (window); - } -} - -static gboolean -unminimize_func (MetaWindow *window, - void *data) -{ - meta_window_unminimize (window); - return TRUE; -} - -static void -unminimize_window_and_all_transient_parents (MetaWindow *window) -{ - meta_window_unminimize (window); - meta_window_foreach_ancestor (window, unminimize_func, NULL); -} - -static void -window_activate (MetaWindow *window, - guint32 timestamp, - MetaClientType source_indication, - MetaWorkspace *workspace) -{ - gboolean can_ignore_outdated_timestamps; - meta_topic (META_DEBUG_FOCUS, - "_NET_ACTIVE_WINDOW message sent for %s at time %u " - "by client type %u.\n", - window->desc, timestamp, source_indication); - - /* Older EWMH spec didn't specify a timestamp; we decide to honor these only - * if the app specifies that it is a pager. - * - * Update: Unconditionally honor 0 timestamps for now; we'll fight - * that battle later. Just remove the "FALSE &&" in order to only - * honor 0 timestamps for pagers. - */ - can_ignore_outdated_timestamps = - (timestamp != 0 || (FALSE && source_indication != META_CLIENT_TYPE_PAGER)); - if (XSERVER_TIME_IS_BEFORE (timestamp, window->display->last_user_time) && - can_ignore_outdated_timestamps) - { - meta_topic (META_DEBUG_FOCUS, - "last_user_time (%u) is more recent; ignoring " - " _NET_ACTIVE_WINDOW message.\n", - window->display->last_user_time); - meta_window_set_demands_attention(window); - return; - } - - /* For those stupid pagers, get a valid timestamp and show a warning */ - if (timestamp == 0) - { - meta_warning ("meta_window_activate called by a pager with a 0 timestamp; " - "the pager needs to be fixed.\n"); - timestamp = meta_display_get_current_time_roundtrip (window->display); - } - - meta_window_set_user_time (window, timestamp); - - /* disable show desktop mode unless we're a desktop component */ - maybe_leave_show_desktop_mode (window); - - /* Get window on current or given workspace */ - if (workspace == NULL) - workspace = window->screen->active_workspace; - - /* For non-transient windows, we just set up a pulsing indicator, - rather than move windows or workspaces. - See http://bugzilla.gnome.org/show_bug.cgi?id=482354 */ - if (window->xtransient_for == None && - !meta_window_located_on_workspace (window, workspace)) - { - meta_window_set_demands_attention (window); - /* We've marked it as demanding, don't need to do anything else. */ - return; - } - else if (window->xtransient_for != None) - { - /* Move transients to current workspace - preference dialogs should appear over - the source window. */ - meta_window_change_workspace (window, workspace); - } - - if (window->shaded) - meta_window_unshade (window, timestamp); - - unminimize_window_and_all_transient_parents (window); - - if (meta_prefs_get_raise_on_click () || - source_indication == META_CLIENT_TYPE_PAGER) - meta_window_raise (window); - - meta_topic (META_DEBUG_FOCUS, - "Focusing window %s due to activation\n", - window->desc); - meta_window_focus (window, timestamp); -} - -/* This function exists since most of the functionality in window_activate - * is useful for Metacity, but Metacity shouldn't need to specify a client - * type for itself. ;-) - */ -void -meta_window_activate (MetaWindow *window, - guint32 timestamp) -{ - /* We're not really a pager, but the behavior we want is the same as if - * we were such. If we change the pager behavior later, we could revisit - * this and just add extra flags to window_activate. - */ - window_activate (window, timestamp, META_CLIENT_TYPE_PAGER, NULL); -} - -void -meta_window_activate_with_workspace (MetaWindow *window, - guint32 timestamp, - MetaWorkspace *workspace) -{ - /* We're not really a pager, but the behavior we want is the same as if - * we were such. If we change the pager behavior later, we could revisit - * this and just add extra flags to window_activate. - */ - window_activate (window, timestamp, META_CLIENT_TYPE_APPLICATION, workspace); -} - -/* Manually fix all the weirdness explained in the big comment at the - * beginning of meta_window_move_resize_internal() giving positions - * expected by meta_window_constrain (i.e. positions & sizes of the - * internal or client window). - */ -static void -adjust_for_gravity (MetaWindow *window, - MetaFrameGeometry *fgeom, - gboolean coords_assume_border, - int gravity, - MetaRectangle *rect) -{ - int ref_x, ref_y; - int bw; - int child_x, child_y; - int frame_width, frame_height; - - if (coords_assume_border) - bw = window->border_width; - else - bw = 0; - - if (fgeom) - { - child_x = fgeom->left_width; - child_y = fgeom->top_height; - frame_width = child_x + rect->width + fgeom->right_width; - frame_height = child_y + rect->height + fgeom->bottom_height; - } - else - { - child_x = 0; - child_y = 0; - frame_width = rect->width; - frame_height = rect->height; - } - - /* We're computing position to pass to window_move, which is - * the position of the client window (StaticGravity basically) - * - * (see WM spec description of gravity computation, but note that - * their formulas assume we're honoring the border width, rather - * than compensating for having turned it off) - */ - switch (gravity) - { - case NorthWestGravity: - ref_x = rect->x; - ref_y = rect->y; - break; - case NorthGravity: - ref_x = rect->x + rect->width / 2 + bw; - ref_y = rect->y; - break; - case NorthEastGravity: - ref_x = rect->x + rect->width + bw * 2; - ref_y = rect->y; - break; - case WestGravity: - ref_x = rect->x; - ref_y = rect->y + rect->height / 2 + bw; - break; - case CenterGravity: - ref_x = rect->x + rect->width / 2 + bw; - ref_y = rect->y + rect->height / 2 + bw; - break; - case EastGravity: - ref_x = rect->x + rect->width + bw * 2; - ref_y = rect->y + rect->height / 2 + bw; - break; - case SouthWestGravity: - ref_x = rect->x; - ref_y = rect->y + rect->height + bw * 2; - break; - case SouthGravity: - ref_x = rect->x + rect->width / 2 + bw; - ref_y = rect->y + rect->height + bw * 2; - break; - case SouthEastGravity: - ref_x = rect->x + rect->width + bw * 2; - ref_y = rect->y + rect->height + bw * 2; - break; - case StaticGravity: - default: - ref_x = rect->x; - ref_y = rect->y; - break; - } - - switch (gravity) - { - case NorthWestGravity: - rect->x = ref_x + child_x; - rect->y = ref_y + child_y; - break; - case NorthGravity: - rect->x = ref_x - frame_width / 2 + child_x; - rect->y = ref_y + child_y; - break; - case NorthEastGravity: - rect->x = ref_x - frame_width + child_x; - rect->y = ref_y + child_y; - break; - case WestGravity: - rect->x = ref_x + child_x; - rect->y = ref_y - frame_height / 2 + child_y; - break; - case CenterGravity: - rect->x = ref_x - frame_width / 2 + child_x; - rect->y = ref_y - frame_height / 2 + child_y; - break; - case EastGravity: - rect->x = ref_x - frame_width + child_x; - rect->y = ref_y - frame_height / 2 + child_y; - break; - case SouthWestGravity: - rect->x = ref_x + child_x; - rect->y = ref_y - frame_height + child_y; - break; - case SouthGravity: - rect->x = ref_x - frame_width / 2 + child_x; - rect->y = ref_y - frame_height + child_y; - break; - case SouthEastGravity: - rect->x = ref_x - frame_width + child_x; - rect->y = ref_y - frame_height + child_y; - break; - case StaticGravity: - default: - rect->x = ref_x; - rect->y = ref_y; - break; - } -} - -static gboolean -static_gravity_works (MetaDisplay *display) -{ - return display->static_gravity_works; -} - -#ifdef HAVE_XSYNC -static void -send_sync_request (MetaWindow *window) -{ - XSyncValue value; - XClientMessageEvent ev; - - window->sync_request_serial++; - - XSyncIntToValue (&value, window->sync_request_serial); - - ev.type = ClientMessage; - ev.window = window->xwindow; - ev.message_type = window->display->atom_WM_PROTOCOLS; - ev.format = 32; - ev.data.l[0] = window->display->atom__NET_WM_SYNC_REQUEST; - /* FIXME: meta_display_get_current_time() is bad, but since calls - * come from meta_window_move_resize_internal (which in turn come - * from all over), I'm not sure what we can do to fix it. Do we - * want to use _roundtrip, though? - */ - ev.data.l[1] = meta_display_get_current_time (window->display); - ev.data.l[2] = XSyncValueLow32 (value); - ev.data.l[3] = XSyncValueHigh32 (value); - - /* We don't need to trap errors here as we are already - * inside an error_trap_push()/pop() pair. - */ - XSendEvent (window->display->xdisplay, - window->xwindow, False, 0, (XEvent*) &ev); - - g_get_current_time (&window->sync_request_time); -} -#endif - -static void -meta_window_move_resize_internal (MetaWindow *window, - MetaMoveResizeFlags flags, - int gravity, - int root_x_nw, - int root_y_nw, - int w, - int h) -{ - /* meta_window_move_resize_internal gets called with very different - * meanings for root_x_nw and root_y_nw. w & h are always the area - * of the inner or client window (i.e. excluding the frame) and - * gravity is the relevant gravity associated with the request (note - * that gravity is ignored for move-only operations unless its - * e.g. a configure request). The location is different for - * different cases because of how this function gets called; note - * that in all cases what we want to find out is the upper left - * corner of the position of the inner window: - * - * Case | Called from (flags; gravity) - * -----+----------------------------------------------- - * 1 | A resize only ConfigureRequest - * 1 | meta_window_resize - * 1 | meta_window_resize_with_gravity - * 2 | New window - * 2 | Session restore - * 2 | A not-resize-only ConfigureRequest/net_moveresize_window request - * 3 | meta_window_move - * 3 | meta_window_move_resize - * - * For each of the cases, root_x_nw and root_y_nw must be treated as follows: - * - * (1) They should be entirely ignored; instead the previous position - * and size of the window should be resized according to the given - * gravity in order to determine the new position of the window. - * (2) Needs to be fixed up by adjust_for_gravity() as these - * coordinates are relative to some corner or side of the outer - * window (except for the case of StaticGravity) and we want to - * know the location of the upper left corner of the inner window. - * (3) These values are already the desired positon of the NW corner - * of the inner window - */ - XWindowChanges values; - unsigned int mask; - gboolean need_configure_notify; - MetaFrameGeometry fgeom; - gboolean need_move_client = FALSE; - gboolean need_move_frame = FALSE; - gboolean need_resize_client = FALSE; - gboolean need_resize_frame = FALSE; - int frame_size_dx; - int frame_size_dy; - int size_dx; - int size_dy; - gboolean is_configure_request; - gboolean do_gravity_adjust; - gboolean is_user_action; - gboolean configure_frame_first; - gboolean use_static_gravity; - /* used for the configure request, but may not be final - * destination due to StaticGravity etc. - */ - int client_move_x; - int client_move_y; - MetaRectangle new_rect; - MetaRectangle old_rect; - - is_configure_request = (flags & META_IS_CONFIGURE_REQUEST) != 0; - do_gravity_adjust = (flags & META_DO_GRAVITY_ADJUST) != 0; - is_user_action = (flags & META_IS_USER_ACTION) != 0; - - /* The action has to be a move or a resize or both... */ - g_assert (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)); - - /* We don't need it in the idle queue anymore. */ - meta_window_unqueue (window, META_QUEUE_MOVE_RESIZE); - - meta_window_get_client_root_coords (window, &old_rect); - - meta_topic (META_DEBUG_GEOMETRY, - "Move/resize %s to %d,%d %dx%d%s%s from %d,%d %dx%d\n", - window->desc, root_x_nw, root_y_nw, w, h, - is_configure_request ? " (configure request)" : "", - is_user_action ? " (user move/resize)" : "", - old_rect.x, old_rect.y, old_rect.width, old_rect.height); - - if (window->frame) - meta_frame_calc_geometry (window->frame, - &fgeom); - - new_rect.x = root_x_nw; - new_rect.y = root_y_nw; - new_rect.width = w; - new_rect.height = h; - - /* If this is a resize only, the position should be ignored and - * instead obtained by resizing the old rectangle according to the - * relevant gravity. - */ - if ((flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)) == - META_IS_RESIZE_ACTION) - { - meta_rectangle_resize_with_gravity (&old_rect, - &new_rect, - gravity, - new_rect.width, - new_rect.height); - - meta_topic (META_DEBUG_GEOMETRY, - "Compensated for gravity in resize action; new pos %d,%d\n", - new_rect.x, new_rect.y); - } - else if (is_configure_request || do_gravity_adjust) - { - adjust_for_gravity (window, - window->frame ? &fgeom : NULL, - /* configure request coords assume - * the border width existed - */ - is_configure_request, - gravity, - &new_rect); - - meta_topic (META_DEBUG_GEOMETRY, - "Compensated for configure_request/do_gravity_adjust needing " - "weird positioning; new pos %d,%d\n", - new_rect.x, new_rect.y); - } - - meta_window_constrain (window, - window->frame ? &fgeom : NULL, - flags, - gravity, - &old_rect, - &new_rect); - - w = new_rect.width; - h = new_rect.height; - root_x_nw = new_rect.x; - root_y_nw = new_rect.y; - - if (w != window->rect.width || - h != window->rect.height) - need_resize_client = TRUE; - - window->rect.width = w; - window->rect.height = h; - - if (window->frame) - { - int new_w, new_h; - - new_w = window->rect.width + fgeom.left_width + fgeom.right_width; - - if (window->shaded) - new_h = fgeom.top_height; - else - new_h = window->rect.height + fgeom.top_height + fgeom.bottom_height; - - frame_size_dx = new_w - window->frame->rect.width; - frame_size_dy = new_h - window->frame->rect.height; - - need_resize_frame = (frame_size_dx != 0 || frame_size_dy != 0); - - window->frame->rect.width = new_w; - window->frame->rect.height = new_h; - - meta_topic (META_DEBUG_GEOMETRY, - "Calculated frame size %dx%d\n", - window->frame->rect.width, - window->frame->rect.height); - } - else - { - frame_size_dx = 0; - frame_size_dy = 0; - } - - /* For nice effect, when growing the window we want to move/resize - * the frame first, when shrinking the window we want to move/resize - * the client first. If we grow one way and shrink the other, - * see which way we're moving "more" - * - * Mail from Owen subject "Suggestion: Gravity and resizing from the left" - * http://mail.gnome.org/archives/wm-spec-list/1999-November/msg00088.html - * - * An annoying fact you need to know in this code is that StaticGravity - * does nothing if you _only_ resize or _only_ move the frame; - * it must move _and_ resize, otherwise you get NorthWestGravity - * behavior. The move and resize must actually occur, it is not - * enough to set CWX | CWWidth but pass in the current size/pos. - */ - - if (window->frame) - { - int new_x, new_y; - int frame_pos_dx, frame_pos_dy; - - /* Compute new frame coords */ - new_x = root_x_nw - fgeom.left_width; - new_y = root_y_nw - fgeom.top_height; - - frame_pos_dx = new_x - window->frame->rect.x; - frame_pos_dy = new_y - window->frame->rect.y; - - need_move_frame = (frame_pos_dx != 0 || frame_pos_dy != 0); - - window->frame->rect.x = new_x; - window->frame->rect.y = new_y; - - /* If frame will both move and resize, then StaticGravity - * on the child window will kick in and implicitly move - * the child with respect to the frame. The implicit - * move will keep the child in the same place with - * respect to the root window. If frame only moves - * or only resizes, then the child will just move along - * with the frame. - */ - - /* window->rect.x, window->rect.y are relative to frame, - * remember they are the server coords - */ - - new_x = fgeom.left_width; - new_y = fgeom.top_height; - - if (need_resize_frame && need_move_frame && - static_gravity_works (window->display)) - { - /* static gravity kicks in because frame - * is both moved and resized - */ - /* when we move the frame by frame_pos_dx, frame_pos_dy the - * client will implicitly move relative to frame by the - * inverse delta. - * - * When moving client then frame, we move the client by the - * frame delta, to be canceled out by the implicit move by - * the inverse frame delta, resulting in a client at new_x, - * new_y. - * - * When moving frame then client, we move the client - * by the same delta as the frame, because the client - * was "left behind" by the frame - resulting in a client - * at new_x, new_y. - * - * In both cases we need to move the client window - * in all cases where we had to move the frame window. - */ - - client_move_x = new_x + frame_pos_dx; - client_move_y = new_y + frame_pos_dy; - - if (need_move_frame) - need_move_client = TRUE; - - use_static_gravity = TRUE; - } - else - { - client_move_x = new_x; - client_move_y = new_y; - - if (client_move_x != window->rect.x || - client_move_y != window->rect.y) - need_move_client = TRUE; - - use_static_gravity = FALSE; - } - - /* This is the final target position, but not necessarily what - * we pass to XConfigureWindow, due to StaticGravity implicit - * movement. - */ - window->rect.x = new_x; - window->rect.y = new_y; - } - else - { - if (root_x_nw != window->rect.x || - root_y_nw != window->rect.y) - need_move_client = TRUE; - - window->rect.x = root_x_nw; - window->rect.y = root_y_nw; - - client_move_x = window->rect.x; - client_move_y = window->rect.y; - - use_static_gravity = FALSE; - } - - /* If frame extents have changed, fill in other frame fields and - change frame's extents property. */ - if (window->frame && - (window->frame->child_x != fgeom.left_width || - window->frame->child_y != fgeom.top_height || - window->frame->right_width != fgeom.right_width || - window->frame->bottom_height != fgeom.bottom_height)) - { - window->frame->child_x = fgeom.left_width; - window->frame->child_y = fgeom.top_height; - window->frame->right_width = fgeom.right_width; - window->frame->bottom_height = fgeom.bottom_height; - - update_net_frame_extents (window); - } - - /* See ICCCM 4.1.5 for when to send ConfigureNotify */ - - need_configure_notify = FALSE; - - /* If this is a configure request and we change nothing, then we - * must send configure notify. - */ - if (is_configure_request && - !(need_move_client || need_move_frame || - need_resize_client || need_resize_frame || - window->border_width != 0)) - need_configure_notify = TRUE; - - /* We must send configure notify if we move but don't resize, since - * the client window may not get a real event - */ - if ((need_move_client || need_move_frame) && - !(need_resize_client || need_resize_frame)) - need_configure_notify = TRUE; - - /* MapRequest events with a PPosition or UPosition hint with a frame - * are moved by metacity without resizing; send a configure notify - * in such cases. See #322840. (Note that window->constructing is - * only true iff this call is due to a MapRequest, and when - * PPosition/UPosition hints aren't set, metacity seems to send a - * ConfigureNotify anyway due to the above code.) - */ - if (window->constructing && window->frame && - ((window->size_hints.flags & PPosition) || - (window->size_hints.flags & USPosition))) - need_configure_notify = TRUE; - - /* The rest of this function syncs our new size/pos with X as - * efficiently as possible - */ - - /* configure frame first if we grow more than we shrink - */ - size_dx = w - window->rect.width; - size_dy = h - window->rect.height; - - configure_frame_first = (size_dx + size_dy >= 0); - - if (use_static_gravity) - meta_window_set_gravity (window, StaticGravity); - - if (configure_frame_first && window->frame) - meta_frame_sync_to_window (window->frame, - gravity, - need_move_frame, need_resize_frame); - - values.border_width = 0; - values.x = client_move_x; - values.y = client_move_y; - values.width = window->rect.width; - values.height = window->rect.height; - - mask = 0; - if (is_configure_request && window->border_width != 0) - mask |= CWBorderWidth; /* must force to 0 */ - if (need_move_client) - mask |= (CWX | CWY); - if (need_resize_client) - mask |= (CWWidth | CWHeight); - - if (mask != 0) - { - { - int newx, newy; - meta_window_get_position (window, &newx, &newy); - meta_topic (META_DEBUG_GEOMETRY, - "Syncing new client geometry %d,%d %dx%d, border: %s pos: %s size: %s\n", - newx, newy, - window->rect.width, window->rect.height, - mask & CWBorderWidth ? "true" : "false", - need_move_client ? "true" : "false", - need_resize_client ? "true" : "false"); - } - - meta_error_trap_push (window->display); - -#ifdef HAVE_XSYNC - if (window->sync_request_counter != None && - window->display->grab_sync_request_alarm != None && - window->sync_request_time.tv_usec == 0 && - window->sync_request_time.tv_sec == 0) - { - /* turn off updating */ - if (window->display->compositor) - meta_compositor_set_updates (window->display->compositor, window, FALSE); - - send_sync_request (window); - } -#endif - - XConfigureWindow (window->display->xdisplay, - window->xwindow, - mask, - &values); - - meta_error_trap_pop (window->display, FALSE); - } - - if (!configure_frame_first && window->frame) - meta_frame_sync_to_window (window->frame, - gravity, - need_move_frame, need_resize_frame); - - /* Put gravity back to be nice to lesser window managers */ - if (use_static_gravity) - meta_window_set_gravity (window, NorthWestGravity); - - if (need_configure_notify) - send_configure_notify (window); - - if (!window->placed) - force_save_user_window_placement (window); - else if (is_user_action) - save_user_window_placement (window); - - if (need_move_frame || need_resize_frame || - need_move_client || need_resize_client) - { - int newx, newy; - meta_window_get_position (window, &newx, &newy); - meta_topic (META_DEBUG_GEOMETRY, - "New size/position %d,%d %dx%d (user %d,%d %dx%d)\n", - newx, newy, window->rect.width, window->rect.height, - window->user_rect.x, window->user_rect.y, - window->user_rect.width, window->user_rect.height); - } - else - { - meta_topic (META_DEBUG_GEOMETRY, "Size/position not modified\n"); - } - - if (window->display->grab_wireframe_active) - meta_window_update_wireframe (window, root_x_nw, root_y_nw, w, h); - else - meta_window_refresh_resize_popup (window); - - /* Invariants leaving this function are: - * a) window->rect and frame->rect reflect the actual - * server-side size/pos of window->xwindow and frame->xwindow - * b) all constraints are obeyed by window->rect and frame->rect - */ -} - -void -meta_window_resize (MetaWindow *window, - gboolean user_op, - int w, - int h) -{ - int x, y; - MetaMoveResizeFlags flags; - - meta_window_get_position (window, &x, &y); - - flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_RESIZE_ACTION; - meta_window_move_resize_internal (window, - flags, - NorthWestGravity, - x, y, w, h); -} - -void -meta_window_move (MetaWindow *window, - gboolean user_op, - int root_x_nw, - int root_y_nw) -{ - MetaMoveResizeFlags flags = - (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION; - meta_window_move_resize_internal (window, - flags, - NorthWestGravity, - root_x_nw, root_y_nw, - window->rect.width, - window->rect.height); -} - -void -meta_window_move_resize (MetaWindow *window, - gboolean user_op, - int root_x_nw, - int root_y_nw, - int w, - int h) -{ - MetaMoveResizeFlags flags = - (user_op ? META_IS_USER_ACTION : 0) | - META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION; - meta_window_move_resize_internal (window, - flags, - NorthWestGravity, - root_x_nw, root_y_nw, - w, h); -} - -void -meta_window_resize_with_gravity (MetaWindow *window, - gboolean user_op, - int w, - int h, - int gravity) -{ - int x, y; - MetaMoveResizeFlags flags; - - meta_window_get_position (window, &x, &y); - - flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_RESIZE_ACTION; - meta_window_move_resize_internal (window, - flags, - gravity, - x, y, w, h); -} - -static void -meta_window_move_resize_now (MetaWindow *window) -{ - /* If constraints have changed then we want to snap back to wherever - * the user had the window. We use user_rect for this reason. See - * also bug 426519 comment 3. - */ - meta_window_move_resize (window, FALSE, - window->user_rect.x, - window->user_rect.y, - window->user_rect.width, - window->user_rect.height); -} - -static gboolean -idle_move_resize (gpointer data) -{ - GSList *tmp; - GSList *copy; - guint queue_index = GPOINTER_TO_INT (data); - - meta_topic (META_DEBUG_GEOMETRY, "Clearing the move_resize queue\n"); - - /* Work with a copy, for reentrancy. The allowed reentrancy isn't - * complete; destroying a window while we're in here would result in - * badness. But it's OK to queue/unqueue move_resizes. - */ - copy = g_slist_copy (queue_pending[queue_index]); - g_slist_free (queue_pending[queue_index]); - queue_pending[queue_index] = NULL; - queue_idle[queue_index] = 0; - - destroying_windows_disallowed += 1; - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - /* As a side effect, sets window->move_resize_queued = FALSE */ - meta_window_move_resize_now (window); - - tmp = tmp->next; - } - - g_slist_free (copy); - - destroying_windows_disallowed -= 1; - - return FALSE; -} - -void -meta_window_get_position (MetaWindow *window, - int *x, - int *y) -{ - if (window->frame) - { - if (x) - *x = window->frame->rect.x + window->frame->child_x; - if (y) - *y = window->frame->rect.y + window->frame->child_y; - } - else - { - if (x) - *x = window->rect.x; - if (y) - *y = window->rect.y; - } -} - -void -meta_window_get_client_root_coords (MetaWindow *window, - MetaRectangle *rect) -{ - meta_window_get_position (window, &rect->x, &rect->y); - rect->width = window->rect.width; - rect->height = window->rect.height; -} - -void -meta_window_get_gravity_position (MetaWindow *window, - int gravity, - int *root_x, - int *root_y) -{ - MetaRectangle frame_extents; - int w, h; - int x, y; - - w = window->rect.width; - h = window->rect.height; - - if (gravity == StaticGravity) - { - frame_extents = window->rect; - if (window->frame) - { - frame_extents.x = window->frame->rect.x + window->frame->child_x; - frame_extents.y = window->frame->rect.y + window->frame->child_y; - } - } - else - { - if (window->frame == NULL) - frame_extents = window->rect; - else - frame_extents = window->frame->rect; - } - - x = frame_extents.x; - y = frame_extents.y; - - switch (gravity) - { - case NorthGravity: - case CenterGravity: - case SouthGravity: - /* Find center of frame. */ - x += frame_extents.width / 2; - /* Center client window on that point. */ - x -= w / 2; - break; - - case SouthEastGravity: - case EastGravity: - case NorthEastGravity: - /* Find right edge of frame */ - x += frame_extents.width; - /* Align left edge of client at that point. */ - x -= w; - break; - default: - break; - } - - switch (gravity) - { - case WestGravity: - case CenterGravity: - case EastGravity: - /* Find center of frame. */ - y += frame_extents.height / 2; - /* Center client window there. */ - y -= h / 2; - break; - case SouthWestGravity: - case SouthGravity: - case SouthEastGravity: - /* Find south edge of frame */ - y += frame_extents.height; - /* Place bottom edge of client there */ - y -= h; - break; - default: - break; - } - - if (root_x) - *root_x = x; - if (root_y) - *root_y = y; -} - -void -meta_window_get_geometry (MetaWindow *window, - int *x, - int *y, - int *width, - int *height) -{ - meta_window_get_gravity_position (window, - window->size_hints.win_gravity, - x, y); - - *width = (window->rect.width - window->size_hints.base_width) / - window->size_hints.width_inc; - *height = (window->rect.height - window->size_hints.base_height) / - window->size_hints.height_inc; -} - -void -meta_window_get_outer_rect (const MetaWindow *window, - MetaRectangle *rect) -{ - if (window->frame) - *rect = window->frame->rect; - else - *rect = window->rect; -} - -void -meta_window_get_xor_rect (MetaWindow *window, - const MetaRectangle *grab_wireframe_rect, - MetaRectangle *xor_rect) -{ - if (window->frame) - { - xor_rect->x = grab_wireframe_rect->x - window->frame->child_x; - xor_rect->y = grab_wireframe_rect->y - window->frame->child_y; - xor_rect->width = grab_wireframe_rect->width + window->frame->child_x + window->frame->right_width; - - if (window->shaded) - xor_rect->height = window->frame->child_y; - else - xor_rect->height = grab_wireframe_rect->height + window->frame->child_y + window->frame->bottom_height; - } - else - *xor_rect = *grab_wireframe_rect; -} - -/* Figure out the numbers that show up in the - * resize popup when in reduced resources mode. - */ -static void -meta_window_get_wireframe_geometry (MetaWindow *window, - int *width, - int *height) -{ - if (!window->display->grab_wireframe_active) - return; - - if ((width == NULL) || (height == NULL)) - return; - - if ((window->display->grab_window->size_hints.width_inc <= 1) || - (window->display->grab_window->size_hints.height_inc <= 1)) - { - *width = -1; - *height = -1; - return; - } - - *width = window->display->grab_wireframe_rect.width - - window->display->grab_window->size_hints.base_width; - *width /= window->display->grab_window->size_hints.width_inc; - - *height = window->display->grab_wireframe_rect.height - - window->display->grab_window->size_hints.base_height; - *height /= window->display->grab_window->size_hints.height_inc; -} - -/* XXX META_EFFECT_ALT_TAB, well, this and others */ -void -meta_window_begin_wireframe (MetaWindow *window) -{ - - MetaRectangle new_xor; - int display_width, display_height; - - meta_window_get_client_root_coords (window, - &window->display->grab_wireframe_rect); - - meta_window_get_xor_rect (window, &window->display->grab_wireframe_rect, - &new_xor); - meta_window_get_wireframe_geometry (window, &display_width, &display_height); - - meta_effects_begin_wireframe (window->screen, - &new_xor, display_width, display_height); - - window->display->grab_wireframe_last_xor_rect = new_xor; - window->display->grab_wireframe_last_display_width = display_width; - window->display->grab_wireframe_last_display_height = display_height; -} - -void -meta_window_update_wireframe (MetaWindow *window, - int x, - int y, - int width, - int height) -{ - - MetaRectangle new_xor; - int display_width, display_height; - - window->display->grab_wireframe_rect.x = x; - window->display->grab_wireframe_rect.y = y; - window->display->grab_wireframe_rect.width = width; - window->display->grab_wireframe_rect.height = height; - - meta_window_get_xor_rect (window, &window->display->grab_wireframe_rect, - &new_xor); - meta_window_get_wireframe_geometry (window, &display_width, &display_height); - - meta_effects_update_wireframe (window->screen, - &window->display->grab_wireframe_last_xor_rect, - window->display->grab_wireframe_last_display_width, - window->display->grab_wireframe_last_display_height, - &new_xor, display_width, display_height); - - window->display->grab_wireframe_last_xor_rect = new_xor; - window->display->grab_wireframe_last_display_width = display_width; - window->display->grab_wireframe_last_display_height = display_height; -} - -void -meta_window_end_wireframe (MetaWindow *window) -{ - meta_effects_end_wireframe (window->display->grab_window->screen, - &window->display->grab_wireframe_last_xor_rect, - window->display->grab_wireframe_last_display_width, - window->display->grab_wireframe_last_display_height); -} - -const char* -meta_window_get_startup_id (MetaWindow *window) -{ - if (window->startup_id == NULL) - { - MetaGroup *group; - - group = meta_window_get_group (window); - - if (group != NULL) - return meta_group_get_startup_id (group); - } - - return window->startup_id; -} - -static MetaWindow* -get_modal_transient (MetaWindow *window) -{ - GSList *windows; - GSList *tmp; - MetaWindow *modal_transient; - - /* A window can't be the transient of itself, but this is just for - * convenience in the loop below; we manually fix things up at the - * end if no real modal transient was found. - */ - modal_transient = window; - - windows = meta_display_list_windows (window->display); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *transient = tmp->data; - - if (transient->xtransient_for == modal_transient->xwindow && - transient->wm_state_modal) - { - modal_transient = transient; - tmp = windows; - continue; - } - - tmp = tmp->next; - } - - g_slist_free (windows); - - if (window == modal_transient) - modal_transient = NULL; - - return modal_transient; -} - -/* XXX META_EFFECT_FOCUS */ -void -meta_window_focus (MetaWindow *window, - guint32 timestamp) -{ - MetaWindow *modal_transient; - - meta_topic (META_DEBUG_FOCUS, - "Setting input focus to window %s, input: %d take_focus: %d\n", - window->desc, window->input, window->take_focus); - - if (window->display->grab_window && - window->display->grab_window->all_keys_grabbed) - { - meta_topic (META_DEBUG_FOCUS, - "Current focus window %s has global keygrab, not focusing window %s after all\n", - window->display->grab_window->desc, window->desc); - return; - } - - modal_transient = get_modal_transient (window); - if (modal_transient != NULL && - !modal_transient->unmanaging) - { - meta_topic (META_DEBUG_FOCUS, - "%s has %s as a modal transient, so focusing it instead.\n", - window->desc, modal_transient->desc); - if (!modal_transient->on_all_workspaces && - modal_transient->workspace != window->screen->active_workspace) - meta_window_change_workspace (modal_transient, - window->screen->active_workspace); - window = modal_transient; - } - - meta_window_flush_calc_showing (window); - - if (!window->mapped && !window->shaded) - { - meta_topic (META_DEBUG_FOCUS, - "Window %s is not showing, not focusing after all\n", - window->desc); - return; - } - - /* For output-only or shaded windows, focus the frame. - * This seems to result in the client window getting key events - * though, so I don't know if it's icccm-compliant. - * - * Still, we have to do this or keynav breaks for these windows. - */ - if (window->frame && - (window->shaded || - !(window->input || window->take_focus))) - { - if (window->frame) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing frame of %s\n", window->desc); - meta_display_set_input_focus_window (window->display, - window, - TRUE, - timestamp); - } - } - else - { - if (window->input) - { - meta_topic (META_DEBUG_FOCUS, - "Setting input focus on %s since input = true\n", - window->desc); - meta_display_set_input_focus_window (window->display, - window, - FALSE, - timestamp); - } - - if (window->take_focus) - { - meta_topic (META_DEBUG_FOCUS, - "Sending WM_TAKE_FOCUS to %s since take_focus = true\n", - window->desc); - meta_window_send_icccm_message (window, - window->display->atom_WM_TAKE_FOCUS, - timestamp); - window->display->expected_focus_window = window; - } - } - - if (window->wm_state_demands_attention) - meta_window_unset_demands_attention(window); - - meta_effect_run_focus(window, NULL, NULL); -} - -static void -meta_window_change_workspace_without_transients (MetaWindow *window, - MetaWorkspace *workspace) -{ - meta_verbose ("Changing window %s to workspace %d\n", - window->desc, meta_workspace_index (workspace)); - - /* unstick if stuck. meta_window_unstick would call - * meta_window_change_workspace recursively if the window - * is not in the active workspace. - */ - if (window->on_all_workspaces) - meta_window_unstick (window); - - /* See if we're already on this space. If not, make sure we are */ - if (window->workspace != workspace) - { - meta_workspace_remove_window (window->workspace, window); - meta_workspace_add_window (workspace, window); - } -} - -static gboolean -change_workspace_foreach (MetaWindow *window, - void *data) -{ - meta_window_change_workspace_without_transients (window, data); - return TRUE; -} - -void -meta_window_change_workspace (MetaWindow *window, - MetaWorkspace *workspace) -{ - meta_window_change_workspace_without_transients (window, workspace); - - meta_window_foreach_transient (window, change_workspace_foreach, - workspace); - meta_window_foreach_ancestor (window, change_workspace_foreach, - workspace); -} - -static void -window_stick_impl (MetaWindow *window) -{ - GList *tmp; - MetaWorkspace *workspace; - - meta_verbose ("Sticking window %s current on_all_workspaces = %d\n", - window->desc, window->on_all_workspaces); - - if (window->on_all_workspaces) - return; - - /* We don't change window->workspaces, because we revert - * to that original workspace list if on_all_workspaces is - * toggled back off. - */ - window->on_all_workspaces = TRUE; - - /* We do, however, change the MRU lists of all the workspaces - */ - tmp = window->screen->workspaces; - while (tmp) - { - workspace = (MetaWorkspace *) tmp->data; - if (!g_list_find (workspace->mru_list, window)) - workspace->mru_list = g_list_prepend (workspace->mru_list, window); - - tmp = tmp->next; - } - - meta_window_set_current_workspace_hint (window); - - meta_window_queue(window, META_QUEUE_CALC_SHOWING); -} - -static void -window_unstick_impl (MetaWindow *window) -{ - GList *tmp; - MetaWorkspace *workspace; - - if (!window->on_all_workspaces) - return; - - /* Revert to window->workspaces */ - - window->on_all_workspaces = FALSE; - - /* Remove window from MRU lists that it doesn't belong in */ - tmp = window->screen->workspaces; - while (tmp) - { - workspace = (MetaWorkspace *) tmp->data; - if (window->workspace != workspace) - workspace->mru_list = g_list_remove (workspace->mru_list, window); - tmp = tmp->next; - } - - /* We change ourselves to the active workspace, since otherwise you'd get - * a weird window-vaporization effect. Once we have UI for being - * on more than one workspace this should probably be add_workspace - * not change_workspace. - */ - if (window->screen->active_workspace != window->workspace) - meta_window_change_workspace (window, window->screen->active_workspace); - - meta_window_set_current_workspace_hint (window); - - meta_window_queue(window, META_QUEUE_CALC_SHOWING); -} - -static gboolean -stick_foreach_func (MetaWindow *window, - void *data) -{ - gboolean stick; - - stick = *(gboolean*)data; - if (stick) - window_stick_impl (window); - else - window_unstick_impl (window); - return TRUE; -} - -void -meta_window_stick (MetaWindow *window) -{ - gboolean stick = TRUE; - window_stick_impl (window); - meta_window_foreach_transient (window, - stick_foreach_func, - &stick); -} - -void -meta_window_unstick (MetaWindow *window) -{ - gboolean stick = FALSE; - window_unstick_impl (window); - meta_window_foreach_transient (window, - stick_foreach_func, - &stick); -} - -unsigned long -meta_window_get_net_wm_desktop (MetaWindow *window) -{ - if (window->on_all_workspaces) - return 0xFFFFFFFF; - else - return meta_workspace_index (window->workspace); -} - -static void -update_net_frame_extents (MetaWindow *window) -{ - unsigned long data[4] = { 0, 0, 0, 0 }; - - if (window->frame) - { - /* Left */ - data[0] = window->frame->child_x; - /* Right */ - data[1] = window->frame->right_width; - /* Top */ - data[2] = window->frame->child_y; - /* Bottom */ - data[3] = window->frame->bottom_height; - } - - meta_topic (META_DEBUG_GEOMETRY, - "Setting _NET_FRAME_EXTENTS on managed window 0x%lx " - "to left = %lu, right = %lu, top = %lu, bottom = %lu\n", - window->xwindow, data[0], data[1], data[2], data[3]); - - meta_error_trap_push (window->display); - XChangeProperty (window->display->xdisplay, window->xwindow, - window->display->atom__NET_FRAME_EXTENTS, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 4); - meta_error_trap_pop (window->display, FALSE); -} - -void -meta_window_set_current_workspace_hint (MetaWindow *window) -{ - /* FIXME if on more than one workspace, we claim to be "sticky", - * the WM spec doesn't say what to do here. - */ - unsigned long data[1]; - - if (window->workspace == NULL) - { - /* this happens when unmanaging windows */ - return; - } - - data[0] = meta_window_get_net_wm_desktop (window); - - meta_verbose ("Setting _NET_WM_DESKTOP of %s to %lu\n", - window->desc, data[0]); - - meta_error_trap_push (window->display); - XChangeProperty (window->display->xdisplay, window->xwindow, - window->display->atom__NET_WM_DESKTOP, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - meta_error_trap_pop (window->display, FALSE); -} - -static gboolean -find_root_ancestor (MetaWindow *window, - void *data) -{ - MetaWindow **ancestor = data; - - /* Overwrite the previously "most-root" ancestor with the new one found */ - *ancestor = window; - - /* We want this to continue until meta_window_foreach_ancestor quits because - * there are no more valid ancestors. - */ - return TRUE; -} - -MetaWindow * -meta_window_find_root_ancestor (MetaWindow *window) -{ - MetaWindow *ancestor; - ancestor = window; - meta_window_foreach_ancestor (window, find_root_ancestor, &ancestor); - return ancestor; -} - -void -meta_window_raise (MetaWindow *window) -{ - MetaWindow *ancestor; - ancestor = meta_window_find_root_ancestor (window); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Raising window %s, ancestor of %s\n", - ancestor->desc, window->desc); - - /* Raise the ancestor of the window (if the window has no ancestor, - * then ancestor will be set to the window itself); do this because - * it's weird to see windows from other apps stacked between a child - * and parent window of the currently active app. The stacking - * constraints in stack.c then magically take care of raising all - * the child windows appropriately. - */ - if (window->screen->stack == ancestor->screen->stack) - meta_stack_raise (window->screen->stack, ancestor); - else - { - meta_warning ( - "Either stacks aren't per screen or some window has a weird " - "transient_for hint; window->screen->stack != " - "ancestor->screen->stack. window = %s, ancestor = %s.\n", - window->desc, ancestor->desc); - /* We could raise the window here, but don't want to do that twice and - * so we let the case below handle that. - */ - } - - /* Okay, so stacking constraints misses one case: If a window has - * two children and we want to raise one of those children, then - * raising the ancestor isn't enough; we need to also raise the - * correct child. See bug 307875. - */ - if (window != ancestor) - meta_stack_raise (window->screen->stack, window); -} - -void -meta_window_lower (MetaWindow *window) -{ - meta_topic (META_DEBUG_WINDOW_OPS, - "Lowering window %s\n", window->desc); - - meta_stack_lower (window->screen->stack, window); -} - -void -meta_window_send_icccm_message (MetaWindow *window, - Atom atom, - guint32 timestamp) -{ - /* This comment and code are from twm, copyright - * Open Group, Evans & Sutherland, etc. - */ - - /* - * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all - * client messages will have the following form: - * - * event type ClientMessage - * message type _XA_WM_PROTOCOLS - * window tmp->w - * format 32 - * data[0] message atom - * data[1] time stamp - */ - - XClientMessageEvent ev; - - ev.type = ClientMessage; - ev.window = window->xwindow; - ev.message_type = window->display->atom_WM_PROTOCOLS; - ev.format = 32; - ev.data.l[0] = atom; - ev.data.l[1] = timestamp; - - meta_error_trap_push (window->display); - XSendEvent (window->display->xdisplay, - window->xwindow, False, 0, (XEvent*) &ev); - meta_error_trap_pop (window->display, FALSE); -} - -void -meta_window_move_resize_request (MetaWindow *window, - guint value_mask, - int gravity, - int new_x, - int new_y, - int new_width, - int new_height) -{ - int x, y, width, height; - gboolean allow_position_change; - gboolean in_grab_op; - MetaMoveResizeFlags flags; - - /* We ignore configure requests while the user is moving/resizing - * the window, since these represent the app sucking and fighting - * the user, most likely due to a bug in the app (e.g. pfaedit - * seemed to do this) - * - * Still have to do the ConfigureNotify and all, but pretend the - * app asked for the current size/position instead of the new one. - */ - in_grab_op = FALSE; - if (window->display->grab_op != META_GRAB_OP_NONE && - window == window->display->grab_window) - { - switch (window->display->grab_op) - { - case META_GRAB_OP_MOVING: - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_E: - in_grab_op = TRUE; - break; - default: - break; - } - } - - /* it's essential to use only the explicitly-set fields, - * and otherwise use our current up-to-date position. - * - * Otherwise you get spurious position changes when the app changes - * size, for example, if window->rect is not in sync with the - * server-side position in effect when the configure request was - * generated. - */ - meta_window_get_gravity_position (window, - gravity, - &x, &y); - - allow_position_change = FALSE; - - if (meta_prefs_get_disable_workarounds ()) - { - if (window->type == META_WINDOW_DIALOG || - window->type == META_WINDOW_MODAL_DIALOG || - window->type == META_WINDOW_SPLASHSCREEN) - ; /* No position change for these */ - else if ((window->size_hints.flags & PPosition) || - /* USPosition is just stale if window is placed; - * no --geometry involved here. - */ - ((window->size_hints.flags & USPosition) && - !window->placed)) - allow_position_change = TRUE; - } - else - { - allow_position_change = TRUE; - } - - if (in_grab_op) - allow_position_change = FALSE; - - if (allow_position_change) - { - if (value_mask & CWX) - x = new_x; - if (value_mask & CWY) - y = new_y; - if (value_mask & (CWX | CWY)) - { - /* Once manually positioned, windows shouldn't be placed - * by the window manager. - */ - window->placed = TRUE; - } - } - else - { - meta_topic (META_DEBUG_GEOMETRY, - "Not allowing position change for window %s PPosition 0x%lx USPosition 0x%lx type %u\n", - window->desc, window->size_hints.flags & PPosition, - window->size_hints.flags & USPosition, - window->type); - } - - width = window->rect.width; - height = window->rect.height; - if (!in_grab_op) - { - if (value_mask & CWWidth) - width = new_width; - - if (value_mask & CWHeight) - height = new_height; - } - - /* ICCCM 4.1.5 */ - - /* We're ignoring the value_mask here, since sizes - * not in the mask will be the current window geometry. - */ - window->size_hints.x = x; - window->size_hints.y = y; - window->size_hints.width = width; - window->size_hints.height = height; - - /* NOTE: We consider ConfigureRequests to be "user" actions in one - * way, but not in another. Explanation of the two cases are in the - * next two big comments. - */ - - /* The constraints code allows user actions to move windows - * offscreen, etc., and configure request actions would often send - * windows offscreen when users don't want it if not constrained - * (e.g. hitting a dropdown triangle in a fileselector to show more - * options, which makes the window bigger). Thus we do not set - * META_IS_USER_ACTION in flags to the - * meta_window_move_resize_internal() call. - */ - flags = META_IS_CONFIGURE_REQUEST; - if (value_mask & (CWX | CWY)) - flags |= META_IS_MOVE_ACTION; - if (value_mask & (CWWidth | CWHeight)) - flags |= META_IS_RESIZE_ACTION; - - if (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)) - meta_window_move_resize_internal (window, - flags, - gravity, - x, - y, - width, - height); - - /* window->user_rect exists to allow "snapping-back" the window if a - * new strut is set (causing the window to move) and then the strut - * is later removed without the user moving the window in the - * interim. We'd like to "snap-back" to the position specified by - * ConfigureRequest events (at least the constrained version of the - * ConfigureRequest, since that is guaranteed to be onscreen) so we - * set user_rect here. - * - * See also bug 426519. - */ - save_user_window_placement (window); -} - -gboolean -meta_window_configure_request (MetaWindow *window, - XEvent *event) -{ - /* Note that x, y is the corner of the window border, - * and width, height is the size of the window inside - * its border, but that we always deny border requests - * and give windows a border of 0. But we save the - * requested border here. - */ - if (event->xconfigurerequest.value_mask & CWBorderWidth) - window->border_width = event->xconfigurerequest.border_width; - - meta_window_move_resize_request(window, - event->xconfigurerequest.value_mask, - window->size_hints.win_gravity, - event->xconfigurerequest.x, - event->xconfigurerequest.y, - event->xconfigurerequest.width, - event->xconfigurerequest.height); - - /* Handle stacking. We only handle raises/lowers, mostly because - * stack.c really can't deal with anything else. I guess we'll fix - * that if a client turns up that really requires it. Only a very - * few clients even require the raise/lower (and in fact all client - * attempts to deal with stacking order are essentially broken, - * since they have no idea what other clients are involved or how - * the stack looks). - * - * I'm pretty sure no interesting client uses TopIf, BottomIf, or - * Opposite anyway, so the only possible missing thing is - * Above/Below with a sibling set. For now we just pretend there's - * never a sibling set and always do the full raise/lower instead of - * the raise-just-above/below-sibling. - */ - if (event->xconfigurerequest.value_mask & CWStackMode) - { - MetaWindow *active_window; - active_window = window->display->expected_focus_window; - if (meta_prefs_get_disable_workarounds () || - !meta_prefs_get_raise_on_click ()) - { - meta_topic (META_DEBUG_STACK, - "%s sent an xconfigure stacking request; this is " - "broken behavior and the request is being ignored.\n", - window->desc); - } - else if (active_window && - !meta_window_same_application (window, active_window) && - XSERVER_TIME_IS_BEFORE (window->net_wm_user_time, - active_window->net_wm_user_time)) - { - meta_topic (META_DEBUG_STACK, - "Ignoring xconfigure stacking request from %s (with " - "user_time %u); currently active application is %s (with " - "user_time %u).\n", - window->desc, - window->net_wm_user_time, - active_window->desc, - active_window->net_wm_user_time); - if (event->xconfigurerequest.detail == Above) - meta_window_set_demands_attention(window); - } - else - { - switch (event->xconfigurerequest.detail) - { - case Above: - meta_window_raise (window); - break; - case Below: - meta_window_lower (window); - break; - case TopIf: - case BottomIf: - case Opposite: - break; - } - } - } - - return TRUE; -} - -gboolean -meta_window_property_notify (MetaWindow *window, - XEvent *event) -{ - return process_property_notify (window, &event->xproperty); -} - -#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 -#define _NET_WM_MOVERESIZE_SIZE_TOP 1 -#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 -#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 -#define _NET_WM_MOVERESIZE_SIZE_LEFT 7 -#define _NET_WM_MOVERESIZE_MOVE 8 -#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 -#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 - -gboolean -meta_window_client_message (MetaWindow *window, - XEvent *event) -{ - MetaDisplay *display; - - display = window->display; - - if (event->xclient.message_type == - display->atom__NET_CLOSE_WINDOW) - { - guint32 timestamp; - - if (event->xclient.data.l[0] != 0) - timestamp = event->xclient.data.l[0]; - else - { - meta_warning ("Receiving a NET_CLOSE_WINDOW message for %s without " - "a timestamp! This means some buggy (outdated) " - "application is on the loose!\n", - window->desc); - timestamp = meta_display_get_current_time (window->display); - } - - meta_window_delete (window, timestamp); - - return TRUE; - } - else if (event->xclient.message_type == - display->atom__NET_WM_DESKTOP) - { - int space; - MetaWorkspace *workspace; - - space = event->xclient.data.l[0]; - - meta_verbose ("Request to move %s to workspace %d\n", - window->desc, space); - - workspace = - meta_screen_get_workspace_by_index (window->screen, - space); - - if (workspace) - { - if (window->on_all_workspaces) - meta_window_unstick (window); - meta_window_change_workspace (window, workspace); - } - else if (space == (int) 0xFFFFFFFF) - { - meta_window_stick (window); - } - else - { - meta_verbose ("No such workspace %d for screen\n", space); - } - - meta_verbose ("Window %s now on_all_workspaces = %d\n", - window->desc, window->on_all_workspaces); - - return TRUE; - } - else if (event->xclient.message_type == - display->atom__NET_WM_STATE) - { - gulong action; - Atom first; - Atom second; - - action = event->xclient.data.l[0]; - first = event->xclient.data.l[1]; - second = event->xclient.data.l[2]; - - if (meta_is_verbose ()) - { - char *str1; - char *str2; - - meta_error_trap_push_with_return (display); - str1 = XGetAtomName (display->xdisplay, first); - if (meta_error_trap_pop_with_return (display, TRUE) != Success) - str1 = NULL; - - meta_error_trap_push_with_return (display); - str2 = XGetAtomName (display->xdisplay, second); - if (meta_error_trap_pop_with_return (display, TRUE) != Success) - str2 = NULL; - - meta_verbose ("Request to change _NET_WM_STATE action %lu atom1: %s atom2: %s\n", - action, - str1 ? str1 : "(unknown)", - str2 ? str2 : "(unknown)"); - - meta_XFree (str1); - meta_XFree (str2); - } - - if (first == display->atom__NET_WM_STATE_SHADED || - second == display->atom__NET_WM_STATE_SHADED) - { - gboolean shade; - guint32 timestamp; - - /* Stupid protocol has no timestamp; of course, shading - * sucks anyway so who really cares that we're forced to do - * a roundtrip here? - */ - timestamp = meta_display_get_current_time_roundtrip (window->display); - - shade = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && !window->shaded)); - if (shade && window->has_shade_func) - meta_window_shade (window, timestamp); - else - meta_window_unshade (window, timestamp); - } - - if (first == display->atom__NET_WM_STATE_FULLSCREEN || - second == display->atom__NET_WM_STATE_FULLSCREEN) - { - gboolean make_fullscreen; - - make_fullscreen = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && !window->fullscreen)); - if (make_fullscreen && window->has_fullscreen_func) - meta_window_make_fullscreen (window); - else - meta_window_unmake_fullscreen (window); - } - - if (first == display->atom__NET_WM_STATE_MAXIMIZED_HORZ || - second == display->atom__NET_WM_STATE_MAXIMIZED_HORZ) - { - gboolean max; - - max = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && - !window->maximized_horizontally)); - if (max && window->has_maximize_func) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL); - } - else - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL); - } - } - - if (first == display->atom__NET_WM_STATE_MAXIMIZED_VERT || - second == display->atom__NET_WM_STATE_MAXIMIZED_VERT) - { - gboolean max; - - max = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && - !window->maximized_vertically)); - if (max && window->has_maximize_func) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_maximize (window, META_MAXIMIZE_VERTICAL); - } - else - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL); - } - } - - if (first == display->atom__NET_WM_STATE_MODAL || - second == display->atom__NET_WM_STATE_MODAL) - { - window->wm_state_modal = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->wm_state_modal); - - recalc_window_type (window); - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); - } - - if (first == display->atom__NET_WM_STATE_SKIP_PAGER || - second == display->atom__NET_WM_STATE_SKIP_PAGER) - { - window->wm_state_skip_pager = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->skip_pager); - - recalc_window_features (window); - set_net_wm_state (window); - } - - if (first == display->atom__NET_WM_STATE_SKIP_TASKBAR || - second == display->atom__NET_WM_STATE_SKIP_TASKBAR) - { - window->wm_state_skip_taskbar = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->skip_taskbar); - - recalc_window_features (window); - set_net_wm_state (window); - } - - if (first == display->atom__NET_WM_STATE_ABOVE || - second == display->atom__NET_WM_STATE_ABOVE) - { - window->wm_state_above = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->wm_state_above); - - meta_window_update_layer (window); - set_net_wm_state (window); - } - - if (first == display->atom__NET_WM_STATE_BELOW || - second == display->atom__NET_WM_STATE_BELOW) - { - window->wm_state_below = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->wm_state_below); - - meta_window_update_layer (window); - set_net_wm_state (window); - } - - if (first == display->atom__NET_WM_STATE_DEMANDS_ATTENTION || - second == display->atom__NET_WM_STATE_DEMANDS_ATTENTION) - { - if ((action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->wm_state_demands_attention)) - meta_window_set_demands_attention (window); - else - meta_window_unset_demands_attention (window); - } - - if (first == display->atom__NET_WM_STATE_STICKY || - second == display->atom__NET_WM_STATE_STICKY) - { - if ((action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->on_all_workspaces)) - meta_window_stick (window); - else - meta_window_unstick (window); - } - - return TRUE; - } - else if (event->xclient.message_type == - display->atom_WM_CHANGE_STATE) - { - meta_verbose ("WM_CHANGE_STATE client message, state: %ld\n", - event->xclient.data.l[0]); - if (event->xclient.data.l[0] == IconicState && - window->has_minimize_func) - meta_window_minimize (window); - - return TRUE; - } - else if (event->xclient.message_type == - display->atom__NET_WM_MOVERESIZE) - { - int x_root; - int y_root; - int action; - MetaGrabOp op; - int button; - guint32 timestamp; - - /* _NET_WM_MOVERESIZE messages are almost certainly going to come from - * clients when users click on the fake "frame" that the client has, - * thus we should also treat such messages as though it were a - * "frame action". - */ - gboolean const frame_action = TRUE; - - x_root = event->xclient.data.l[0]; - y_root = event->xclient.data.l[1]; - action = event->xclient.data.l[2]; - button = event->xclient.data.l[3]; - - /* FIXME: What a braindead protocol; no timestamp?!? */ - timestamp = meta_display_get_current_time_roundtrip (display); - meta_warning ("Received a _NET_WM_MOVERESIZE message for %s; these " - "messages lack timestamps and therefore suck.\n", - window->desc); - meta_topic (META_DEBUG_WINDOW_OPS, - "Received _NET_WM_MOVERESIZE message on %s, %d,%d action = %d, button %d\n", - window->desc, - x_root, y_root, action, button); - - op = META_GRAB_OP_NONE; - switch (action) - { - case _NET_WM_MOVERESIZE_SIZE_TOPLEFT: - op = META_GRAB_OP_RESIZING_NW; - break; - case _NET_WM_MOVERESIZE_SIZE_TOP: - op = META_GRAB_OP_RESIZING_N; - break; - case _NET_WM_MOVERESIZE_SIZE_TOPRIGHT: - op = META_GRAB_OP_RESIZING_NE; - break; - case _NET_WM_MOVERESIZE_SIZE_RIGHT: - op = META_GRAB_OP_RESIZING_E; - break; - case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: - op = META_GRAB_OP_RESIZING_SE; - break; - case _NET_WM_MOVERESIZE_SIZE_BOTTOM: - op = META_GRAB_OP_RESIZING_S; - break; - case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: - op = META_GRAB_OP_RESIZING_SW; - break; - case _NET_WM_MOVERESIZE_SIZE_LEFT: - op = META_GRAB_OP_RESIZING_W; - break; - case _NET_WM_MOVERESIZE_MOVE: - op = META_GRAB_OP_MOVING; - break; - case _NET_WM_MOVERESIZE_SIZE_KEYBOARD: - op = META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN; - break; - case _NET_WM_MOVERESIZE_MOVE_KEYBOARD: - op = META_GRAB_OP_KEYBOARD_MOVING; - break; - default: - break; - } - - if (op != META_GRAB_OP_NONE && - ((window->has_move_func && op == META_GRAB_OP_KEYBOARD_MOVING) || - (window->has_resize_func && op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN))) - { - meta_window_begin_grab_op (window, op, frame_action, timestamp); - } - else if (op != META_GRAB_OP_NONE && - ((window->has_move_func && op == META_GRAB_OP_MOVING) || - (window->has_resize_func && - (op != META_GRAB_OP_MOVING && - op != META_GRAB_OP_KEYBOARD_MOVING)))) - { - /* - * the button SHOULD already be included in the message - */ - if (button == 0) - { - int x, y, query_root_x, query_root_y; - Window root, child; - guint mask; - - /* The race conditions in this _NET_WM_MOVERESIZE thing - * are mind-boggling - */ - mask = 0; - meta_error_trap_push (window->display); - XQueryPointer (window->display->xdisplay, - window->xwindow, - &root, &child, - &query_root_x, &query_root_y, - &x, &y, - &mask); - meta_error_trap_pop (window->display, TRUE); - - if (mask & Button1Mask) - button = 1; - else if (mask & Button2Mask) - button = 2; - else if (mask & Button3Mask) - button = 3; - else - button = 0; - } - - if (button != 0) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Beginning move/resize with button = %d\n", button); - meta_display_begin_grab_op (window->display, - window->screen, - window, - op, - FALSE, - frame_action, - button, 0, - timestamp, - x_root, - y_root); - } - } - - return TRUE; - } - else if (event->xclient.message_type == - display->atom__NET_MOVERESIZE_WINDOW) - { - int gravity, source; - guint value_mask; - - gravity = (event->xclient.data.l[0] & 0xff); - value_mask = (event->xclient.data.l[0] & 0xf00) >> 8; - source = (event->xclient.data.l[0] & 0xf000) >> 12; - - if (gravity == 0) - gravity = window->size_hints.win_gravity; - - meta_window_move_resize_request(window, - value_mask, - gravity, - event->xclient.data.l[1], /* x */ - event->xclient.data.l[2], /* y */ - event->xclient.data.l[3], /* width */ - event->xclient.data.l[4]); /* height */ - } - else if (event->xclient.message_type == - display->atom__NET_ACTIVE_WINDOW) - { - MetaClientType source_indication; - guint32 timestamp; - - meta_verbose ("_NET_ACTIVE_WINDOW request for window '%s', activating\n", - window->desc); - - source_indication = event->xclient.data.l[0]; - timestamp = event->xclient.data.l[1]; - - if (source_indication > META_CLIENT_TYPE_MAX_RECOGNIZED) - source_indication = META_CLIENT_TYPE_UNKNOWN; - - if (timestamp == 0) - { - /* Client using older EWMH _NET_ACTIVE_WINDOW without a timestamp */ - meta_warning ("Buggy client sent a _NET_ACTIVE_WINDOW message with a " - "timestamp of 0 for %s\n", - window->desc); - timestamp = meta_display_get_current_time (display); - } - - window_activate (window, timestamp, source_indication, NULL); - return TRUE; - } - else if (event->xclient.message_type == - display->atom__NET_WM_FULLSCREEN_MONITORS) - { - MetaClientType source_indication; - gulong top, bottom, left, right; - - meta_verbose ("_NET_WM_FULLSCREEN_MONITORS request for window '%s'\n", - window->desc); - - top = event->xclient.data.l[0]; - bottom = event->xclient.data.l[1]; - left = event->xclient.data.l[2]; - right = event->xclient.data.l[3]; - source_indication = event->xclient.data.l[4]; - - meta_window_update_fullscreen_monitors (window, top, bottom, left, right); - } - - return FALSE; -} - -gboolean -meta_window_notify_focus (MetaWindow *window, - XEvent *event) -{ - /* note the event can be on either the window or the frame, - * we focus the frame for shaded windows - */ - - /* The event can be FocusIn, FocusOut, or UnmapNotify. - * On UnmapNotify we have to pretend it's focus out, - * because we won't get a focus out if it occurs, apparently. - */ - - /* We ignore grabs, though this is questionable. - * It may be better to increase the intelligence of - * the focus window tracking. - * - * The problem is that keybindings for windows are done with - * XGrabKey, which means focus_window disappears and the front of - * the MRU list gets confused from what the user expects once a - * keybinding is used. - */ - meta_topic (META_DEBUG_FOCUS, - "Focus %s event received on %s 0x%lx (%s) " - "mode %s detail %s\n", - event->type == FocusIn ? "in" : - event->type == FocusOut ? "out" : - event->type == UnmapNotify ? "unmap" : - "???", - window->desc, event->xany.window, - event->xany.window == window->xwindow ? - "client window" : - (window->frame && event->xany.window == window->frame->xwindow) ? - "frame window" : - "unknown window", - event->type != UnmapNotify ? - meta_event_mode_to_string (event->xfocus.mode) : "n/a", - event->type != UnmapNotify ? - meta_event_detail_to_string (event->xfocus.detail) : "n/a"); - - /* FIXME our pointer tracking is broken; see how - * gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c - * handle it for the correct way. In brief you need to track - * pointer focus and regular focus, and handle EnterNotify in - * PointerRoot mode with no window manager. However as noted above, - * accurate focus tracking will break things because we want to keep - * windows "focused" when using keybindings on them, and also we - * sometimes "focus" a window by focusing its frame or - * no_focus_window; so this all needs rethinking massively. - * - * My suggestion is to change it so that we clearly separate - * actual keyboard focus tracking using the xterm algorithm, - * and metacity's "pretend" focus window, and go through all - * the code and decide which one should be used in each place; - * a hard bit is deciding on a policy for that. - * - * http://bugzilla.gnome.org/show_bug.cgi?id=90382 - */ - - if ((event->type == FocusIn || - event->type == FocusOut) && - (event->xfocus.mode == NotifyGrab || - event->xfocus.mode == NotifyUngrab || - /* From WindowMaker, ignore all funky pointer root events */ - event->xfocus.detail > NotifyNonlinearVirtual)) - { - meta_topic (META_DEBUG_FOCUS, - "Ignoring focus event generated by a grab or other weirdness\n"); - return TRUE; - } - - if (event->type == FocusIn) - { - if (window != window->display->focus_window) - { - meta_topic (META_DEBUG_FOCUS, - "* Focus --> %s\n", window->desc); - window->display->focus_window = window; - window->has_focus = TRUE; - meta_compositor_set_active_window (window->display->compositor, - window->screen, window); - - /* Move to the front of the focusing workspace's MRU list. - * We should only be "removing" it from the MRU list if it's - * not already there. Note that it's possible that we might - * be processing this FocusIn after we've changed to a - * different workspace; we should therefore update the MRU - * list only if the window is actually on the active - * workspace. - */ - if (window->screen->active_workspace && - meta_window_located_on_workspace (window, - window->screen->active_workspace)) - { - GList* link; - link = g_list_find (window->screen->active_workspace->mru_list, - window); - g_assert (link); - - window->screen->active_workspace->mru_list = - g_list_remove_link (window->screen->active_workspace->mru_list, - link); - g_list_free (link); - - window->screen->active_workspace->mru_list = - g_list_prepend (window->screen->active_workspace->mru_list, - window); - } - - if (window->frame) - meta_frame_queue_draw (window->frame); - - meta_error_trap_push (window->display); - XInstallColormap (window->display->xdisplay, - window->colormap); - meta_error_trap_pop (window->display, FALSE); - - /* move into FOCUSED_WINDOW layer */ - meta_window_update_layer (window); - - /* Ungrab click to focus button since the sync grab can interfere - * with some things you might do inside the focused window, by - * causing the client to get funky enter/leave events. - * - * The reason we usually have a passive grab on the window is - * so that we can intercept clicks and raise the window in - * response. For click-to-focus we don't need that since the - * focused window is already raised. When raise_on_click is - * FALSE we also don't need that since we don't do anything - * when the window is clicked. - * - * There is dicussion in bugs 102209, 115072, and 461577 - */ - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK || - !meta_prefs_get_raise_on_click()) - meta_display_ungrab_focus_window_button (window->display, window); - } - } - else if (event->type == FocusOut || - event->type == UnmapNotify) - { - if (event->type == FocusOut && - event->xfocus.detail == NotifyInferior) - { - /* This event means the client moved focus to a subwindow */ - meta_topic (META_DEBUG_FOCUS, - "Ignoring focus out on %s with NotifyInferior\n", - window->desc); - return TRUE; - } - - if (window == window->display->focus_window) - { - meta_topic (META_DEBUG_FOCUS, - "%s is now the previous focus window due to being focused out or unmapped\n", - window->desc); - - meta_topic (META_DEBUG_FOCUS, - "* Focus --> NULL (was %s)\n", window->desc); - - window->display->focus_window = NULL; - window->has_focus = FALSE; - if (window->frame) - meta_frame_queue_draw (window->frame); - - meta_compositor_set_active_window (window->display->compositor, - window->screen, NULL); - - meta_error_trap_push (window->display); - XUninstallColormap (window->display->xdisplay, - window->colormap); - meta_error_trap_pop (window->display, FALSE); - - /* move out of FOCUSED_WINDOW layer */ - meta_window_update_layer (window); - - /* Re-grab for click to focus and raise-on-click, if necessary */ - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK || - !meta_prefs_get_raise_on_click ()) - meta_display_grab_focus_window_button (window->display, window); - } - } - - /* Now set _NET_ACTIVE_WINDOW hint */ - meta_display_update_active_window_hint (window->display); - - return FALSE; -} - -static gboolean -process_property_notify (MetaWindow *window, - XPropertyEvent *event) -{ - /* First, property notifies to ignore because we shouldn't honor - * new values - */ - if (event->atom == window->display->atom__NET_WM_STATE) - { - meta_verbose ("Property notify on %s for _NET_WM_STATE, ignoring (we should be the one who set the property in the first place)\n", - window->desc); - return TRUE; - } - - /* Second, property notifies we want to use. - * FIXME once we move entirely to the window-props.h framework, we - * can just call reload on the property in the event and get rid of - * this if-else chain. - */ - - if (meta_is_verbose ()) /* avoid looking up the name if we don't have to */ - { - char *property_name = XGetAtomName (window->display->xdisplay, - event->atom); - - meta_verbose ("Property notify on %s for %s\n", - window->desc, property_name); - XFree (property_name); - } - - if (event->atom == XA_WM_NAME) - { - /* don't bother reloading WM_NAME if using _NET_WM_NAME already */ - if (!window->using_net_wm_name) - meta_window_reload_property (window, XA_WM_NAME); - } - else if (event->atom == window->display->atom__NET_WM_NAME) - { - meta_window_reload_property (window, window->display->atom__NET_WM_NAME); - - /* if _NET_WM_NAME was unset, reload WM_NAME */ - if (!window->using_net_wm_name) - meta_window_reload_property (window, XA_WM_NAME); - } - else if (event->atom == XA_WM_ICON_NAME) - { - /* don't bother reloading WM_ICON_NAME if using _NET_WM_ICON_NAME already */ - if (!window->using_net_wm_icon_name) - meta_window_reload_property (window, XA_WM_ICON_NAME); - } - else if (event->atom == window->display->atom__NET_WM_ICON_NAME) - { - meta_window_reload_property (window, window->display->atom__NET_WM_ICON_NAME); - - /* if _NET_WM_ICON_NAME was unset, reload WM_ICON_NAME */ - if (!window->using_net_wm_icon_name) - meta_window_reload_property (window, XA_WM_ICON_NAME); - } - else if (event->atom == XA_WM_NORMAL_HINTS) - { - meta_window_reload_property (window, XA_WM_NORMAL_HINTS); - - /* See if we need to constrain current size */ - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); - } - else if (event->atom == window->display->atom_WM_PROTOCOLS) - { - meta_window_reload_property (window, window->display->atom_WM_PROTOCOLS); - } - else if (event->atom == XA_WM_HINTS) - { - meta_window_reload_property (window, XA_WM_HINTS); - } - else if (event->atom == window->display->atom__MOTIF_WM_HINTS) - { - meta_window_reload_property (window, - window->display->atom__MOTIF_WM_HINTS); - } - else if (event->atom == XA_WM_CLASS) - { - meta_window_reload_property (window, XA_WM_CLASS); - } - else if (event->atom == XA_WM_TRANSIENT_FOR) - { - meta_window_reload_property (window, XA_WM_TRANSIENT_FOR); - } - else if (event->atom == - window->display->atom_WM_WINDOW_ROLE) - { - update_role (window); - } - else if (event->atom == - window->display->atom_WM_CLIENT_LEADER || - event->atom == - window->display->atom_SM_CLIENT_ID) - { - meta_warning ("Broken client! Window %s changed client leader window or SM client ID\n", window->desc); - } - else if (event->atom == - window->display->atom__NET_WM_WINDOW_TYPE) - { - update_net_wm_type (window); - } - else if (event->atom == window->display->atom__NET_WM_ICON) - { - meta_icon_cache_property_changed (&window->icon_cache, - window->display, - event->atom); - meta_window_queue(window, META_QUEUE_UPDATE_ICON); - } - else if (event->atom == window->display->atom__KWM_WIN_ICON) - { - meta_icon_cache_property_changed (&window->icon_cache, - window->display, - event->atom); - meta_window_queue(window, META_QUEUE_UPDATE_ICON); - } - else if ((event->atom == window->display->atom__NET_WM_STRUT) || - (event->atom == window->display->atom__NET_WM_STRUT_PARTIAL)) - { - meta_window_update_struts (window); - } - else if (event->atom == window->display->atom__NET_STARTUP_ID) - { - meta_window_reload_property (window, - window->display->atom__NET_STARTUP_ID); - } - else if (event->atom == window->display->atom__NET_WM_SYNC_REQUEST_COUNTER) - { - meta_window_reload_property (window, - window->display->atom__NET_WM_SYNC_REQUEST_COUNTER); - } - else if (event->atom == window->display->atom__NET_WM_USER_TIME) - { - Window xid; - Atom atom__NET_WM_USER_TIME; - - atom__NET_WM_USER_TIME = window->display->atom__NET_WM_USER_TIME; - if (window->user_time_window) - xid = window->user_time_window; - else - xid = window->xwindow; - meta_window_reload_property_from_xwindow (window, - xid, - atom__NET_WM_USER_TIME); - } - - return TRUE; -} - -static void -send_configure_notify (MetaWindow *window) -{ - XEvent event; - - /* from twm */ - - event.type = ConfigureNotify; - event.xconfigure.display = window->display->xdisplay; - event.xconfigure.event = window->xwindow; - event.xconfigure.window = window->xwindow; - event.xconfigure.x = window->rect.x - window->border_width; - event.xconfigure.y = window->rect.y - window->border_width; - if (window->frame) - { - if (window->withdrawn) - { - /* WARNING: x & y need to be set to whatever the XReparentWindow - * call in meta_window_destroy_frame will use so that the window - * has the right coordinates. Currently, that means no change to - * x & y. - */ - } - else - { - /* Need to be in root window coordinates */ - event.xconfigure.x += window->frame->rect.x; - event.xconfigure.y += window->frame->rect.y; - } - } - event.xconfigure.width = window->rect.width; - event.xconfigure.height = window->rect.height; - event.xconfigure.border_width = window->border_width; /* requested not actual */ - event.xconfigure.above = None; /* FIXME */ - event.xconfigure.override_redirect = False; - - meta_topic (META_DEBUG_GEOMETRY, - "Sending synthetic configure notify to %s with x: %d y: %d w: %d h: %d\n", - window->desc, - event.xconfigure.x, event.xconfigure.y, - event.xconfigure.width, event.xconfigure.height); - - meta_error_trap_push (window->display); - XSendEvent (window->display->xdisplay, - window->xwindow, - False, StructureNotifyMask, &event); - meta_error_trap_pop (window->display, FALSE); -} - -gboolean -meta_window_get_icon_geometry (MetaWindow *window, - MetaRectangle *rect) -{ - gulong *geometry = NULL; - int nitems; - - if (meta_prop_get_cardinal_list (window->display, - window->xwindow, - window->display->atom__NET_WM_ICON_GEOMETRY, - &geometry, &nitems)) - { - if (nitems != 4) - { - meta_verbose ("_NET_WM_ICON_GEOMETRY on %s has %d values instead of 4\n", - window->desc, nitems); - meta_XFree (geometry); - return FALSE; - } - - if (rect) - { - rect->x = geometry[0]; - rect->y = geometry[1]; - rect->width = geometry[2]; - rect->height = geometry[3]; - } - - meta_XFree (geometry); - - return TRUE; - } - - return FALSE; -} - -static Window -read_client_leader (MetaDisplay *display, - Window xwindow) -{ - Window retval = None; - - meta_prop_get_window (display, xwindow, - display->atom_WM_CLIENT_LEADER, - &retval); - - return retval; -} - -typedef struct -{ - Window leader; -} ClientLeaderData; - -static gboolean -find_client_leader_func (MetaWindow *ancestor, - void *data) -{ - ClientLeaderData *d; - - d = data; - - d->leader = read_client_leader (ancestor->display, - ancestor->xwindow); - - /* keep going if no client leader found */ - return d->leader == None; -} - -static void -update_sm_hints (MetaWindow *window) -{ - Window leader; - - window->xclient_leader = None; - window->sm_client_id = NULL; - - /* If not on the current window, we can get the client - * leader from transient parents. If we find a client - * leader, we read the SM_CLIENT_ID from it. - */ - leader = read_client_leader (window->display, window->xwindow); - if (leader == None) - { - ClientLeaderData d; - d.leader = None; - meta_window_foreach_ancestor (window, find_client_leader_func, - &d); - leader = d.leader; - } - - if (leader != None) - { - char *str; - - window->xclient_leader = leader; - - if (meta_prop_get_latin1_string (window->display, leader, - window->display->atom_SM_CLIENT_ID, - &str)) - { - window->sm_client_id = g_strdup (str); - meta_XFree (str); - } - } - else - { - meta_verbose ("Didn't find a client leader for %s\n", window->desc); - - if (!meta_prefs_get_disable_workarounds ()) - { - /* Some broken apps (kdelibs fault?) set SM_CLIENT_ID on the app - * instead of the client leader - */ - char *str; - - str = NULL; - if (meta_prop_get_latin1_string (window->display, window->xwindow, - window->display->atom_SM_CLIENT_ID, - &str)) - { - if (window->sm_client_id == NULL) /* first time through */ - meta_warning (_("Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n"), - window->desc); - - window->sm_client_id = g_strdup (str); - meta_XFree (str); - } - } - } - - meta_verbose ("Window %s client leader: 0x%lx SM_CLIENT_ID: '%s'\n", - window->desc, window->xclient_leader, - window->sm_client_id ? window->sm_client_id : "none"); -} - -static void -update_role (MetaWindow *window) -{ - char *str; - - if (window->role) - g_free (window->role); - window->role = NULL; - - if (meta_prop_get_latin1_string (window->display, window->xwindow, - window->display->atom_WM_WINDOW_ROLE, - &str)) - { - window->role = g_strdup (str); - meta_XFree (str); - } - - meta_verbose ("Updated role of %s to '%s'\n", - window->desc, window->role ? window->role : "null"); -} - -static void -update_net_wm_type (MetaWindow *window) -{ - int n_atoms; - Atom *atoms; - int i; - - window->type_atom = None; - n_atoms = 0; - atoms = NULL; - - meta_prop_get_atom_list (window->display, window->xwindow, - window->display->atom__NET_WM_WINDOW_TYPE, - &atoms, &n_atoms); - - i = 0; - while (i < n_atoms) - { - /* We break as soon as we find one we recognize, - * supposed to prefer those near the front of the list - */ - if (atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_DESKTOP || - atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_DOCK || - atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_TOOLBAR || - atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_MENU || - atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_DIALOG || - atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_NORMAL || - atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_UTILITY || - atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_SPLASH) - { - window->type_atom = atoms[i]; - break; - } - - ++i; - } - - meta_XFree (atoms); - - if (meta_is_verbose ()) - { - char *str; - - str = NULL; - if (window->type_atom != None) - { - meta_error_trap_push (window->display); - str = XGetAtomName (window->display->xdisplay, window->type_atom); - meta_error_trap_pop (window->display, TRUE); - } - - meta_verbose ("Window %s type atom %s\n", window->desc, - str ? str : "(none)"); - - if (str) - meta_XFree (str); - } - - recalc_window_type (window); -} - -static void -redraw_icon (MetaWindow *window) -{ - /* We could probably be smart and just redraw the icon here, - * instead of the whole frame. - */ - if (window->frame && (window->mapped || window->frame->mapped)) - meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow); -} - -void -meta_window_update_icon_now (MetaWindow *window) -{ - GdkPixbuf *icon; - GdkPixbuf *mini_icon; - - icon = NULL; - mini_icon = NULL; - - if (meta_read_icons (window->screen, - window->xwindow, - &window->icon_cache, - window->wm_hints_pixmap, - window->wm_hints_mask, - &icon, - META_ICON_WIDTH, META_ICON_HEIGHT, - &mini_icon, - META_MINI_ICON_WIDTH, - META_MINI_ICON_HEIGHT)) - { - if (window->icon) - g_object_unref (G_OBJECT (window->icon)); - - if (window->mini_icon) - g_object_unref (G_OBJECT (window->mini_icon)); - - window->icon = icon; - window->mini_icon = mini_icon; - - redraw_icon (window); - } - - g_assert (window->icon); - g_assert (window->mini_icon); -} - -static gboolean -idle_update_icon (gpointer data) -{ - GSList *tmp; - GSList *copy; - guint queue_index = GPOINTER_TO_INT (data); - - meta_topic (META_DEBUG_GEOMETRY, "Clearing the update_icon queue\n"); - - /* Work with a copy, for reentrancy. The allowed reentrancy isn't - * complete; destroying a window while we're in here would result in - * badness. But it's OK to queue/unqueue update_icons. - */ - copy = g_slist_copy (queue_pending[queue_index]); - g_slist_free (queue_pending[queue_index]); - queue_pending[queue_index] = NULL; - queue_idle[queue_index] = 0; - - destroying_windows_disallowed += 1; - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - meta_window_update_icon_now (window); - window->is_in_queues &= ~META_QUEUE_UPDATE_ICON; - - tmp = tmp->next; - } - - g_slist_free (copy); - - destroying_windows_disallowed -= 1; - - return FALSE; -} - -GList* -meta_window_get_workspaces (MetaWindow *window) -{ - if (window->on_all_workspaces) - return window->screen->workspaces; - else - return window->workspace->list_containing_self; -} - -static void -invalidate_work_areas (MetaWindow *window) -{ - GList *tmp; - - tmp = meta_window_get_workspaces (window); - - while (tmp != NULL) - { - meta_workspace_invalidate_work_area (tmp->data); - tmp = tmp->next; - } -} - -void -meta_window_update_struts (MetaWindow *window) -{ - GSList *old_struts; - GSList *new_struts; - GSList *old_iter, *new_iter; - gulong *struts = NULL; - int nitems; - gboolean changed; - - meta_verbose ("Updating struts for %s\n", window->desc); - - old_struts = window->struts; - new_struts = NULL; - - if (meta_prop_get_cardinal_list (window->display, - window->xwindow, - window->display->atom__NET_WM_STRUT_PARTIAL, - &struts, &nitems)) - { - if (nitems != 12) - meta_verbose ("_NET_WM_STRUT_PARTIAL on %s has %d values instead " - "of 12\n", - window->desc, nitems); - else - { - /* Pull out the strut info for each side in the hint */ - int i; - for (i=0; i<4; i++) - { - MetaStrut *temp; - int thickness, strut_begin, strut_end; - - thickness = struts[i]; - if (thickness == 0) - continue; - strut_begin = struts[4+(i*2)]; - strut_end = struts[4+(i*2)+1]; - - temp = g_new (MetaStrut, 1); - temp->side = 1 << i; /* See MetaDirection def. Matches nicely, eh? */ - temp->rect = window->screen->rect; - switch (temp->side) - { - case META_SIDE_RIGHT: - temp->rect.x = BOX_RIGHT(temp->rect) - thickness; - /* Intentionally fall through without breaking */ - case META_SIDE_LEFT: - temp->rect.width = thickness; - temp->rect.y = strut_begin; - temp->rect.height = strut_end - strut_begin + 1; - break; - case META_SIDE_BOTTOM: - temp->rect.y = BOX_BOTTOM(temp->rect) - thickness; - /* Intentionally fall through without breaking */ - case META_SIDE_TOP: - temp->rect.height = thickness; - temp->rect.x = strut_begin; - temp->rect.width = strut_end - strut_begin + 1; - break; - default: - g_assert_not_reached (); - } - - new_struts = g_slist_prepend (new_struts, temp); - } - - meta_verbose ("_NET_WM_STRUT_PARTIAL struts %lu %lu %lu %lu for " - "window %s\n", - struts[0], struts[1], struts[2], struts[3], - window->desc); - } - meta_XFree (struts); - } - else - { - meta_verbose ("No _NET_WM_STRUT property for %s\n", - window->desc); - } - - if (!new_struts && - meta_prop_get_cardinal_list (window->display, - window->xwindow, - window->display->atom__NET_WM_STRUT, - &struts, &nitems)) - { - if (nitems != 4) - meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n", - window->desc, nitems); - else - { - /* Pull out the strut info for each side in the hint */ - int i; - for (i=0; i<4; i++) - { - MetaStrut *temp; - int thickness; - - thickness = struts[i]; - if (thickness == 0) - continue; - - temp = g_new (MetaStrut, 1); - temp->side = 1 << i; - temp->rect = window->screen->rect; - switch (temp->side) - { - case META_SIDE_RIGHT: - temp->rect.x = BOX_RIGHT(temp->rect) - thickness; - /* Intentionally fall through without breaking */ - case META_SIDE_LEFT: - temp->rect.width = thickness; - break; - case META_SIDE_BOTTOM: - temp->rect.y = BOX_BOTTOM(temp->rect) - thickness; - /* Intentionally fall through without breaking */ - case META_SIDE_TOP: - temp->rect.height = thickness; - break; - default: - g_assert_not_reached (); - } - - new_struts = g_slist_prepend (new_struts, temp); - } - - meta_verbose ("_NET_WM_STRUT struts %lu %lu %lu %lu for window %s\n", - struts[0], struts[1], struts[2], struts[3], - window->desc); - } - meta_XFree (struts); - } - else if (!new_struts) - { - meta_verbose ("No _NET_WM_STRUT property for %s\n", - window->desc); - } - - /* Determine whether old_struts and new_struts are the same */ - old_iter = old_struts; - new_iter = new_struts; - while (old_iter && new_iter) - { - MetaStrut *old_strut = (MetaStrut*) old_iter->data; - MetaStrut *new_strut = (MetaStrut*) new_iter->data; - - if (old_strut->side != new_strut->side || - !meta_rectangle_equal (&old_strut->rect, &new_strut->rect)) - break; - - old_iter = old_iter->next; - new_iter = new_iter->next; - } - changed = (old_iter != NULL || new_iter != NULL); - - /* Update appropriately */ - meta_free_gslist_and_elements (old_struts); - window->struts = new_struts; - if (changed) - { - meta_topic (META_DEBUG_WORKAREA, - "Invalidating work areas of window %s due to struts update\n", - window->desc); - invalidate_work_areas (window); - } - else - { - meta_topic (META_DEBUG_WORKAREA, - "Struts on %s were unchanged\n", window->desc); - } -} - -void -meta_window_recalc_window_type (MetaWindow *window) -{ - recalc_window_type (window); -} - -static void -recalc_window_type (MetaWindow *window) -{ - MetaWindowType old_type; - - old_type = window->type; - - if (window->type_atom != None) - { - if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DESKTOP) - window->type = META_WINDOW_DESKTOP; - else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DOCK) - window->type = META_WINDOW_DOCK; - else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_TOOLBAR) - window->type = META_WINDOW_TOOLBAR; - else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_MENU) - window->type = META_WINDOW_MENU; - else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DIALOG) - window->type = META_WINDOW_DIALOG; - else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_NORMAL) - window->type = META_WINDOW_NORMAL; - else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_UTILITY) - window->type = META_WINDOW_UTILITY; - else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_SPLASH) - window->type = META_WINDOW_SPLASHSCREEN; - else - meta_bug ("Set a type atom for %s that wasn't handled in recalc_window_type\n", - window->desc); - } - else if (window->xtransient_for != None) - { - window->type = META_WINDOW_DIALOG; - } - else - { - window->type = META_WINDOW_NORMAL; - } - - if (window->type == META_WINDOW_DIALOG && - window->wm_state_modal) - window->type = META_WINDOW_MODAL_DIALOG; - - meta_verbose ("Calculated type %u for %s, old type %u\n", - window->type, window->desc, old_type); - - if (old_type != window->type) - { - recalc_window_features (window); - - set_net_wm_state (window); - - /* Update frame */ - if (window->decorated) - meta_window_ensure_frame (window); - else - meta_window_destroy_frame (window); - - /* update stacking constraints */ - meta_window_update_layer (window); - - meta_window_grab_keys (window); - } -} - -static void -set_allowed_actions_hint (MetaWindow *window) -{ -#define MAX_N_ACTIONS 12 - unsigned long data[MAX_N_ACTIONS]; - int i; - - i = 0; - if (window->has_move_func) - { - data[i] = window->display->atom__NET_WM_ACTION_MOVE; - ++i; - } - if (window->has_resize_func) - { - data[i] = window->display->atom__NET_WM_ACTION_RESIZE; - ++i; - } - if (window->has_fullscreen_func) - { - data[i] = window->display->atom__NET_WM_ACTION_FULLSCREEN; - ++i; - } - if (window->has_minimize_func) - { - data[i] = window->display->atom__NET_WM_ACTION_MINIMIZE; - ++i; - } - if (window->has_shade_func) - { - data[i] = window->display->atom__NET_WM_ACTION_SHADE; - ++i; - } - /* sticky according to EWMH is different from metacity's sticky; - * metacity doesn't support EWMH sticky - */ - if (window->has_maximize_func) - { - data[i] = window->display->atom__NET_WM_ACTION_MAXIMIZE_HORZ; - ++i; - data[i] = window->display->atom__NET_WM_ACTION_MAXIMIZE_VERT; - ++i; - } - /* We always allow this */ - data[i] = window->display->atom__NET_WM_ACTION_CHANGE_DESKTOP; - ++i; - if (window->has_close_func) - { - data[i] = window->display->atom__NET_WM_ACTION_CLOSE; - ++i; - } - - /* I guess we always allow above/below operations */ - data[i] = window->display->atom__NET_WM_ACTION_ABOVE; - ++i; - data[i] = window->display->atom__NET_WM_ACTION_BELOW; - ++i; - - g_assert (i <= MAX_N_ACTIONS); - - meta_verbose ("Setting _NET_WM_ALLOWED_ACTIONS with %d atoms\n", i); - - meta_error_trap_push (window->display); - XChangeProperty (window->display->xdisplay, window->xwindow, - window->display->atom__NET_WM_ALLOWED_ACTIONS, - XA_ATOM, - 32, PropModeReplace, (guchar*) data, i); - meta_error_trap_pop (window->display, FALSE); -#undef MAX_N_ACTIONS -} - -void -meta_window_recalc_features (MetaWindow *window) -{ - recalc_window_features (window); -} - -static void -recalc_window_features (MetaWindow *window) -{ - gboolean old_has_close_func; - gboolean old_has_minimize_func; - gboolean old_has_move_func; - gboolean old_has_resize_func; - gboolean old_has_shade_func; - gboolean old_always_sticky; - - old_has_close_func = window->has_close_func; - old_has_minimize_func = window->has_minimize_func; - old_has_move_func = window->has_move_func; - old_has_resize_func = window->has_resize_func; - old_has_shade_func = window->has_shade_func; - old_always_sticky = window->always_sticky; - - /* Use MWM hints initially */ - window->decorated = window->mwm_decorated; - window->border_only = window->mwm_border_only; - window->has_close_func = window->mwm_has_close_func; - window->has_minimize_func = window->mwm_has_minimize_func; - window->has_maximize_func = window->mwm_has_maximize_func; - window->has_move_func = window->mwm_has_move_func; - - window->has_resize_func = TRUE; - - /* If min_size == max_size, then don't allow resize */ - if (window->size_hints.min_width == window->size_hints.max_width && - window->size_hints.min_height == window->size_hints.max_height) - window->has_resize_func = FALSE; - else if (!window->mwm_has_resize_func) - { - /* We ignore mwm_has_resize_func because WM_NORMAL_HINTS is the - * authoritative source for that info. Some apps such as mplayer or - * xine disable resize via MWM but not WM_NORMAL_HINTS, but that - * leads to e.g. us not fullscreening their windows. Apps that set - * MWM but not WM_NORMAL_HINTS are basically broken. We complain - * about these apps but make them work. - */ - - meta_warning (_("Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.\n"), - window->desc, - window->size_hints.min_width, - window->size_hints.min_height, - window->size_hints.max_width, - window->size_hints.max_height); - } - - window->has_shade_func = TRUE; - window->has_fullscreen_func = TRUE; - - window->always_sticky = FALSE; - - /* Semantic category overrides the MWM hints */ - if (window->type == META_WINDOW_TOOLBAR) - window->decorated = FALSE; - - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK) - window->always_sticky = TRUE; - - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->type == META_WINDOW_SPLASHSCREEN) - { - window->decorated = FALSE; - window->has_close_func = FALSE; - window->has_shade_func = FALSE; - - /* FIXME this keeps panels and things from using - * NET_WM_MOVERESIZE; the problem is that some - * panels (edge panels) have fixed possible locations, - * and others ("floating panels") do not. - * - * Perhaps we should require edge panels to explicitly - * disable movement? - */ - window->has_move_func = FALSE; - window->has_resize_func = FALSE; - } - - if (window->type != META_WINDOW_NORMAL) - { - window->has_minimize_func = FALSE; - window->has_maximize_func = FALSE; - window->has_fullscreen_func = FALSE; - } - - if (!window->has_resize_func) - { - window->has_maximize_func = FALSE; - - /* don't allow fullscreen if we can't resize, unless the size - * is entire screen size (kind of broken, because we - * actually fullscreen to xinerama head size not screen size) - */ - if (window->size_hints.min_width == window->screen->rect.width && - window->size_hints.min_height == window->screen->rect.height) - ; /* leave fullscreen available */ - else - window->has_fullscreen_func = FALSE; - } - - /* We leave fullscreen windows decorated, just push the frame outside - * the screen. This avoids flickering to unparent them. - * - * Note that setting has_resize_func = FALSE here must come after the - * above code that may disable fullscreen, because if the window - * is not resizable purely due to fullscreen, we don't want to - * disable fullscreen mode. - */ - if (window->fullscreen) - { - window->has_shade_func = FALSE; - window->has_move_func = FALSE; - window->has_resize_func = FALSE; - window->has_maximize_func = FALSE; - } - - meta_topic (META_DEBUG_WINDOW_OPS, - "Window %s fullscreen = %d not resizable, maximizable = %d fullscreenable = %d min size %dx%d max size %dx%d\n", - window->desc, - window->fullscreen, - window->has_maximize_func, window->has_fullscreen_func, - window->size_hints.min_width, - window->size_hints.min_height, - window->size_hints.max_width, - window->size_hints.max_height); - - /* no shading if not decorated */ - if (!window->decorated || window->border_only) - window->has_shade_func = FALSE; - - window->skip_taskbar = FALSE; - window->skip_pager = FALSE; - - if (window->wm_state_skip_taskbar) - window->skip_taskbar = TRUE; - - if (window->wm_state_skip_pager) - window->skip_pager = TRUE; - - switch (window->type) - { - /* Force skip taskbar/pager on these window types */ - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_MENU: - case META_WINDOW_UTILITY: - case META_WINDOW_SPLASHSCREEN: - window->skip_taskbar = TRUE; - window->skip_pager = TRUE; - break; - - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - /* only skip taskbar if we have a real transient parent */ - if (window->xtransient_for != None && - window->xtransient_for != window->screen->xroot) - window->skip_taskbar = TRUE; - break; - - case META_WINDOW_NORMAL: - break; - } - - meta_topic (META_DEBUG_WINDOW_OPS, - "Window %s decorated = %d border_only = %d has_close = %d has_minimize = %d has_maximize = %d has_move = %d has_shade = %d skip_taskbar = %d skip_pager = %d\n", - window->desc, - window->decorated, - window->border_only, - window->has_close_func, - window->has_minimize_func, - window->has_maximize_func, - window->has_move_func, - window->has_shade_func, - window->skip_taskbar, - window->skip_pager); - - /* FIXME: - * Lame workaround for recalc_window_features - * being used overzealously. The fix is to - * only recalc_window_features when something - * has actually changed. - */ - if (window->constructing || - old_has_close_func != window->has_close_func || - old_has_minimize_func != window->has_minimize_func || - old_has_move_func != window->has_move_func || - old_has_resize_func != window->has_resize_func || - old_has_shade_func != window->has_shade_func || - old_always_sticky != window->always_sticky) - set_allowed_actions_hint (window); - - /* FIXME perhaps should ensure if we don't have a shade func, - * we aren't shaded, etc. - */ -} - -static void -menu_callback (MetaWindowMenu *menu, - Display *xdisplay, - Window client_xwindow, - guint32 timestamp, - MetaMenuOp op, - int workspace_index, - gpointer data) -{ - MetaDisplay *display; - MetaWindow *window; - MetaWorkspace *workspace; - - display = meta_display_for_x_display (xdisplay); - window = meta_display_lookup_x_window (display, client_xwindow); - workspace = NULL; - - if (window != NULL) /* window can be NULL */ - { - meta_verbose ("Menu op %u on %s\n", op, window->desc); - - /* op can be 0 for none */ - switch (op) - { - case META_MENU_OP_DELETE: - meta_window_delete (window, timestamp); - break; - - case META_MENU_OP_MINIMIZE: - meta_window_minimize (window); - break; - - case META_MENU_OP_UNMAXIMIZE: - meta_window_unmaximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - break; - - case META_MENU_OP_MAXIMIZE: - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - break; - - case META_MENU_OP_UNSHADE: - meta_window_unshade (window, timestamp); - break; - - case META_MENU_OP_SHADE: - meta_window_shade (window, timestamp); - break; - - case META_MENU_OP_MOVE_LEFT: - workspace = meta_workspace_get_neighbor (window->screen->active_workspace, - META_MOTION_LEFT); - break; - - case META_MENU_OP_MOVE_RIGHT: - workspace = meta_workspace_get_neighbor (window->screen->active_workspace, - META_MOTION_RIGHT); - break; - - case META_MENU_OP_MOVE_UP: - workspace = meta_workspace_get_neighbor (window->screen->active_workspace, - META_MOTION_UP); - break; - - case META_MENU_OP_MOVE_DOWN: - workspace = meta_workspace_get_neighbor (window->screen->active_workspace, - META_MOTION_DOWN); - break; - - case META_MENU_OP_WORKSPACES: - workspace = meta_screen_get_workspace_by_index (window->screen, - workspace_index); - break; - - case META_MENU_OP_STICK: - meta_window_stick (window); - break; - - case META_MENU_OP_UNSTICK: - meta_window_unstick (window); - break; - - case META_MENU_OP_ABOVE: - case META_MENU_OP_UNABOVE: - if (window->wm_state_above == FALSE) - meta_window_make_above (window); - else - meta_window_unmake_above (window); - break; - - case META_MENU_OP_MOVE: - meta_window_begin_grab_op (window, - META_GRAB_OP_KEYBOARD_MOVING, - TRUE, - timestamp); - break; - - case META_MENU_OP_RESIZE: - meta_window_begin_grab_op (window, - META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, - TRUE, - timestamp); - break; - - case META_MENU_OP_RECOVER: - meta_window_shove_titlebar_onscreen (window); - break; - - case 0: - /* nothing */ - break; - - default: - meta_warning (G_STRLOC": Unknown window op\n"); - break; - } - - if (workspace) - { - meta_window_change_workspace (window, - workspace); -#if 0 - meta_workspace_activate (workspace); - meta_window_raise (window); -#endif - } - } - else - { - meta_verbose ("Menu callback on nonexistent window\n"); - } - - if (display->window_menu == menu) - { - display->window_menu = NULL; - display->window_with_menu = NULL; - } - - meta_ui_window_menu_free (menu); -} - -void -meta_window_show_menu (MetaWindow *window, - int root_x, - int root_y, - int button, - guint32 timestamp) -{ - MetaMenuOp ops; - MetaMenuOp insensitive; - MetaWindowMenu *menu; - MetaWorkspaceLayout layout; - int n_workspaces; - gboolean ltr; - - if (window->display->window_menu) - { - meta_ui_window_menu_free (window->display->window_menu); - window->display->window_menu = NULL; - window->display->window_with_menu = NULL; - } - - ops = 0; - insensitive = 0; - - ops |= (META_MENU_OP_DELETE | META_MENU_OP_MINIMIZE | META_MENU_OP_MOVE | META_MENU_OP_RESIZE); - - if (!meta_window_titlebar_is_onscreen (window) && - window->type != META_WINDOW_DOCK && - window->type != META_WINDOW_DESKTOP) - ops |= META_MENU_OP_RECOVER; - - n_workspaces = meta_screen_get_n_workspaces (window->screen); - - if (n_workspaces > 1) - ops |= META_MENU_OP_WORKSPACES; - - meta_screen_calc_workspace_layout (window->screen, - n_workspaces, - meta_workspace_index ( window->screen->active_workspace), - &layout); - - if (!window->on_all_workspaces) - { - ltr = meta_ui_get_direction() == META_UI_DIRECTION_LTR; - - if (layout.current_col > 0) - ops |= ltr ? META_MENU_OP_MOVE_LEFT : META_MENU_OP_MOVE_RIGHT; - if ((layout.current_col < layout.cols - 1) && - (layout.current_row * layout.cols + (layout.current_col + 1) < n_workspaces)) - ops |= ltr ? META_MENU_OP_MOVE_RIGHT : META_MENU_OP_MOVE_LEFT; - if (layout.current_row > 0) - ops |= META_MENU_OP_MOVE_UP; - if ((layout.current_row < layout.rows - 1) && - ((layout.current_row + 1) * layout.cols + layout.current_col < n_workspaces)) - ops |= META_MENU_OP_MOVE_DOWN; - } - - meta_screen_free_workspace_layout (&layout); - - if (META_WINDOW_MAXIMIZED (window)) - ops |= META_MENU_OP_UNMAXIMIZE; - else - ops |= META_MENU_OP_MAXIMIZE; - -#if 0 - if (window->shaded) - ops |= META_MENU_OP_UNSHADE; - else - ops |= META_MENU_OP_SHADE; -#endif - - ops |= META_MENU_OP_UNSTICK; - ops |= META_MENU_OP_STICK; - - if (window->wm_state_above) - ops |= META_MENU_OP_UNABOVE; - else - ops |= META_MENU_OP_ABOVE; - - if (!window->has_maximize_func) - insensitive |= META_MENU_OP_UNMAXIMIZE | META_MENU_OP_MAXIMIZE; - - if (!window->has_minimize_func) - insensitive |= META_MENU_OP_MINIMIZE; - - if (!window->has_close_func) - insensitive |= META_MENU_OP_DELETE; - - if (!window->has_shade_func) - insensitive |= META_MENU_OP_SHADE | META_MENU_OP_UNSHADE; - - if (!META_WINDOW_ALLOWS_MOVE (window)) - insensitive |= META_MENU_OP_MOVE; - - if (!META_WINDOW_ALLOWS_RESIZE (window)) - insensitive |= META_MENU_OP_RESIZE; - - if (window->always_sticky) - insensitive |= META_MENU_OP_STICK | META_MENU_OP_UNSTICK | META_MENU_OP_WORKSPACES; - - if ((window->type == META_WINDOW_DESKTOP) || - (window->type == META_WINDOW_DOCK) || - (window->type == META_WINDOW_SPLASHSCREEN)) - insensitive |= META_MENU_OP_ABOVE | META_MENU_OP_UNABOVE; - - /* If all operations are disabled, just quit without showing the menu. - * This is the case, for example, with META_WINDOW_DESKTOP windows. - */ - if ((ops & ~insensitive) == 0) - return; - - menu = - meta_ui_window_menu_new (window->screen->ui, - window->xwindow, - ops, - insensitive, - meta_window_get_net_wm_desktop (window), - meta_screen_get_n_workspaces (window->screen), - menu_callback, - NULL); - - window->display->window_menu = menu; - window->display->window_with_menu = window; - - meta_verbose ("Popping up window menu for %s\n", window->desc); - - meta_ui_window_menu_popup (menu, root_x, root_y, button, timestamp); -} - -void -meta_window_shove_titlebar_onscreen (MetaWindow *window) -{ - MetaRectangle outer_rect; - GList *onscreen_region; - int horiz_amount, vert_amount; - int newx, newy; - - /* If there's no titlebar, don't bother */ - if (!window->frame) - return; - - /* Get the basic info we need */ - meta_window_get_outer_rect (window, &outer_rect); - onscreen_region = window->screen->active_workspace->screen_region; - - /* Extend the region (just in case the window is too big to fit on the - * screen), then shove the window on screen, then return the region to - * normal. - */ - horiz_amount = outer_rect.width; - vert_amount = outer_rect.height; - meta_rectangle_expand_region (onscreen_region, - horiz_amount, - horiz_amount, - 0, - vert_amount); - meta_rectangle_shove_into_region(onscreen_region, - FIXED_DIRECTION_X, - &outer_rect); - meta_rectangle_expand_region (onscreen_region, - -horiz_amount, - -horiz_amount, - 0, - -vert_amount); - - newx = outer_rect.x + window->frame->child_x; - newy = outer_rect.y + window->frame->child_y; - meta_window_move_resize (window, - FALSE, - newx, - newy, - window->rect.width, - window->rect.height); -} - -gboolean -meta_window_titlebar_is_onscreen (MetaWindow *window) -{ - MetaRectangle titlebar_rect; - GList *onscreen_region; - int titlebar_size; - gboolean is_onscreen; - - const int min_height_needed = 8; - const int min_width_percent = 0.5; - const int min_width_absolute = 50; - - /* Titlebar can't be offscreen if there is no titlebar... */ - if (!window->frame) - return FALSE; - - /* Get the rectangle corresponding to the titlebar */ - meta_window_get_outer_rect (window, &titlebar_rect); - titlebar_rect.height = window->frame->child_y; - titlebar_size = meta_rectangle_area (&titlebar_rect); - - /* Run through the spanning rectangles for the screen and see if one of - * them overlaps with the titlebar sufficiently to consider it onscreen. - */ - is_onscreen = FALSE; - onscreen_region = window->screen->active_workspace->screen_region; - while (onscreen_region) - { - MetaRectangle *spanning_rect = onscreen_region->data; - MetaRectangle overlap; - - meta_rectangle_intersect (&titlebar_rect, spanning_rect, &overlap); - if (overlap.height > MIN (titlebar_rect.height, min_height_needed) && - overlap.width > MIN (titlebar_rect.width * min_width_percent, - min_width_absolute)) - { - is_onscreen = TRUE; - break; - } - - onscreen_region = onscreen_region->next; - } - - return is_onscreen; -} - -static double -timeval_to_ms (const GTimeVal *timeval) -{ - return (timeval->tv_sec * G_USEC_PER_SEC + timeval->tv_usec) / 1000.0; -} - -static double -time_diff (const GTimeVal *first, - const GTimeVal *second) -{ - double first_ms = timeval_to_ms (first); - double second_ms = timeval_to_ms (second); - - return first_ms - second_ms; -} - -static gboolean -check_moveresize_frequency (MetaWindow *window, - gdouble *remaining) -{ - GTimeVal current_time; - - g_get_current_time (¤t_time); - -#ifdef HAVE_XSYNC - if (!window->disable_sync && - window->display->grab_sync_request_alarm != None) - { - if (window->sync_request_time.tv_sec != 0 || - window->sync_request_time.tv_usec != 0) - { - double elapsed = - time_diff (¤t_time, &window->sync_request_time); - - if (elapsed < 1000.0) - { - /* We want to be sure that the timeout happens at - * a time where elapsed will definitely be - * greater than 1000, so we can disable sync - */ - if (remaining) - *remaining = 1000.0 - elapsed + 100; - - return FALSE; - } - else - { - /* We have now waited for more than a second for the - * application to respond to the sync request - */ - window->disable_sync = TRUE; - return TRUE; - } - } - else - { - /* No outstanding sync requests. Go ahead and resize - */ - return TRUE; - } - } - else -#endif /* HAVE_XSYNC */ - { - const double max_resizes_per_second = 25.0; - const double ms_between_resizes = 1000.0 / max_resizes_per_second; - double elapsed; - - elapsed = time_diff (¤t_time, &window->display->grab_last_moveresize_time); - - if (elapsed >= 0.0 && elapsed < ms_between_resizes) - { - meta_topic (META_DEBUG_RESIZING, - "Delaying move/resize as only %g of %g ms elapsed\n", - elapsed, ms_between_resizes); - - if (remaining) - *remaining = (ms_between_resizes - elapsed); - - return FALSE; - } - - meta_topic (META_DEBUG_RESIZING, - " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)\n", - elapsed / 1000.0, 1.0 / max_resizes_per_second); - - return TRUE; - } -} - -static gboolean -update_move_timeout (gpointer data) -{ - MetaWindow *window = data; - - update_move (window, - window->display->grab_last_user_action_was_snap, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y); - - return FALSE; -} - -static void -update_move (MetaWindow *window, - gboolean snap, - int x, - int y) -{ - int dx, dy; - int new_x, new_y; - MetaRectangle old; - int shake_threshold; - MetaDisplay *display = window->display; - - display->grab_latest_motion_x = x; - display->grab_latest_motion_y = y; - - dx = x - display->grab_anchor_root_x; - dy = y - display->grab_anchor_root_y; - - new_x = display->grab_anchor_window_pos.x + dx; - new_y = display->grab_anchor_window_pos.y + dy; - - meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d\n", - x, y, - display->grab_anchor_root_x, - display->grab_anchor_root_y, - display->grab_anchor_window_pos.x, - display->grab_anchor_window_pos.y, - dx, dy); - - /* Don't bother doing anything if no move has been specified. (This - * happens often, even in keyboard moving, due to the warping of the - * pointer. - */ - if (dx == 0 && dy == 0) - return; - - /* shake loose (unmaximize) maximized window if dragged beyond the threshold - * in the Y direction. You can't pull a window loose via X motion. - */ - -#define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 6 - shake_threshold = meta_ui_get_drag_threshold (window->screen->ui) * - DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR; - - if (META_WINDOW_MAXIMIZED (window) && ABS (dy) >= shake_threshold) - { - double prop; - - /* Shake loose */ - window->shaken_loose = TRUE; - - /* move the unmaximized window to the cursor */ - prop = - ((double)(x - display->grab_initial_window_pos.x)) / - ((double)display->grab_initial_window_pos.width); - - display->grab_initial_window_pos.x = - x - window->saved_rect.width * prop; - display->grab_initial_window_pos.y = y; - - if (window->frame) - { - display->grab_initial_window_pos.y += window->frame->child_y / 2; - } - - window->saved_rect.x = display->grab_initial_window_pos.x; - window->saved_rect.y = display->grab_initial_window_pos.y; - display->grab_anchor_root_x = x; - display->grab_anchor_root_y = y; - - meta_window_unmaximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - - return; - } - /* remaximize window on an other xinerama monitor if window has - * been shaken loose or it is still maximized (then move straight) - */ - else if (window->shaken_loose || META_WINDOW_MAXIMIZED (window)) - { - const MetaXineramaScreenInfo *wxinerama; - MetaRectangle work_area; - int monitor; - - wxinerama = meta_screen_get_xinerama_for_window (window->screen, window); - - for (monitor = 0; monitor < window->screen->n_xinerama_infos; monitor++) - { - meta_window_get_work_area_for_xinerama (window, monitor, &work_area); - - /* check if cursor is near the top of a xinerama work area */ - if (x >= work_area.x && - x < (work_area.x + work_area.width) && - y >= work_area.y && - y < (work_area.y + shake_threshold)) - { - /* move the saved rect if window will become maximized on an - * other monitor so user isn't surprised on a later unmaximize - */ - if (wxinerama->number != monitor) - { - window->saved_rect.x = work_area.x; - window->saved_rect.y = work_area.y; - - if (window->frame) - { - window->saved_rect.x += window->frame->child_x; - window->saved_rect.y += window->frame->child_y; - } - - window->user_rect.x = window->saved_rect.x; - window->user_rect.y = window->saved_rect.y; - - meta_window_unmaximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - } - - display->grab_initial_window_pos = work_area; - display->grab_anchor_root_x = x; - display->grab_anchor_root_y = y; - window->shaken_loose = FALSE; - - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); - - return; - } - } - } - - if (display->grab_wireframe_active) - old = display->grab_wireframe_rect; - else - meta_window_get_client_root_coords (window, &old); - - /* Don't allow movement in the maximized directions */ - if (window->maximized_horizontally) - new_x = old.x; - if (window->maximized_vertically) - new_y = old.y; - - /* Do any edge resistance/snapping */ - meta_window_edge_resistance_for_move (window, - old.x, - old.y, - &new_x, - &new_y, - update_move_timeout, - snap, - FALSE); - - if (display->compositor) - { - int root_x = new_x - display->grab_anchor_window_pos.x + display->grab_anchor_root_x; - int root_y = new_y - display->grab_anchor_window_pos.y + display->grab_anchor_root_y; - - meta_compositor_update_move (display->compositor, - window, root_x, root_y); - } - - if (display->grab_wireframe_active) - meta_window_update_wireframe (window, new_x, new_y, - display->grab_wireframe_rect.width, - display->grab_wireframe_rect.height); - else - meta_window_move (window, TRUE, new_x, new_y); -} - -static gboolean -update_resize_timeout (gpointer data) -{ - MetaWindow *window = data; - - update_resize (window, - window->display->grab_last_user_action_was_snap, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y, - TRUE); - return FALSE; -} - -static void -update_resize (MetaWindow *window, - gboolean snap, - int x, int y, - gboolean force) -{ - int dx, dy; - int new_w, new_h; - int gravity; - MetaRectangle old; - int new_x, new_y; - double remaining; - - window->display->grab_latest_motion_x = x; - window->display->grab_latest_motion_y = y; - - dx = x - window->display->grab_anchor_root_x; - dy = y - window->display->grab_anchor_root_y; - - new_w = window->display->grab_anchor_window_pos.width; - new_h = window->display->grab_anchor_window_pos.height; - - /* Don't bother doing anything if no move has been specified. (This - * happens often, even in keyboard resizing, due to the warping of the - * pointer. - */ - if (dx == 0 && dy == 0) - return; - - /* FIXME this is only used in wireframe mode */ - new_x = window->display->grab_anchor_window_pos.x; - new_y = window->display->grab_anchor_window_pos.y; - - if (window->display->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN) - { - if ((dx > 0) && (dy > 0)) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE; - meta_window_update_keyboard_resize (window, TRUE); - } - else if ((dx < 0) && (dy > 0)) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW; - meta_window_update_keyboard_resize (window, TRUE); - } - else if ((dx > 0) && (dy < 0)) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE; - meta_window_update_keyboard_resize (window, TRUE); - } - else if ((dx < 0) && (dy < 0)) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW; - meta_window_update_keyboard_resize (window, TRUE); - } - else if (dx < 0) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - meta_window_update_keyboard_resize (window, TRUE); - } - else if (dx > 0) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - meta_window_update_keyboard_resize (window, TRUE); - } - else if (dy > 0) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - meta_window_update_keyboard_resize (window, TRUE); - } - else if (dy < 0) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; - meta_window_update_keyboard_resize (window, TRUE); - } - } - - /* FIXME: This stupidity only needed because of wireframe mode and - * the fact that wireframe isn't making use of - * meta_rectangle_resize_with_gravity(). If we were to use that, we - * could just increment new_w and new_h by dx and dy in all cases. - */ - switch (window->display->grab_op) - { - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - new_w += dx; - break; - - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - new_w -= dx; - new_x += dx; - break; - - default: - break; - } - - switch (window->display->grab_op) - { - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - new_h += dy; - break; - - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - new_h -= dy; - new_y += dy; - break; - default: - break; - } - - if (!check_moveresize_frequency (window, &remaining) && !force) - { - /* we are ignoring an event here, so we schedule a - * compensation event when we would otherwise not ignore - * an event. Otherwise we can become stuck if the user never - * generates another event. - */ - if (!window->display->grab_resize_timeout_id) - { - window->display->grab_resize_timeout_id = - g_timeout_add ((int)remaining, update_resize_timeout, window); - } - - return; - } - - /* If we get here, it means the client should have redrawn itself */ - if (window->display->compositor) - meta_compositor_set_updates (window->display->compositor, window, TRUE); - - /* Remove any scheduled compensation events */ - if (window->display->grab_resize_timeout_id) - { - g_source_remove (window->display->grab_resize_timeout_id); - window->display->grab_resize_timeout_id = 0; - } - - if (window->display->grab_wireframe_active) - old = window->display->grab_wireframe_rect; - else - old = window->rect; /* Don't actually care about x,y */ - - /* One sided resizing ought to actually be one-sided, despite the fact that - * aspect ratio windows don't interact nicely with the above stuff. So, - * to avoid some nasty flicker, we enforce that. - */ - switch (window->display->grab_op) - { - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_N: - new_w = old.width; - break; - - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_RESIZING_W: - new_h = old.height; - break; - - default: - break; - } - - /* compute gravity of client during operation */ - gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); - g_assert (gravity >= 0); - - /* Do any edge resistance/snapping */ - meta_window_edge_resistance_for_resize (window, - old.width, - old.height, - &new_w, - &new_h, - gravity, - update_resize_timeout, - snap, - FALSE); - - if (window->display->grab_wireframe_active) - { - if ((new_x + new_w <= new_x) || (new_y + new_h <= new_y)) - return; - - /* FIXME This is crap. For example, the wireframe isn't - * constrained in the way that a real resize would be. An - * obvious elegant solution is to unmap the window during - * wireframe, but still resize it; however, that probably - * confuses broken clients that have problems with opaque - * resize, they probably don't track their visibility. - */ - meta_window_update_wireframe (window, new_x, new_y, new_w, new_h); - } - else - { - /* We don't need to update unless the specified width and height - * are actually different from what we had before. - */ - if (old.width != new_w || old.height != new_h) - meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); - } - - /* Store the latest resize time, if we actually resized. */ - if (window->rect.width != old.width || window->rect.height != old.height) - g_get_current_time (&window->display->grab_last_moveresize_time); -} - -typedef struct -{ - const XEvent *current_event; - int count; - guint32 last_time; -} EventScannerData; - -static Bool -find_last_time_predicate (Display *display, - XEvent *xevent, - XPointer arg) -{ - EventScannerData *esd = (void*) arg; - - if (esd->current_event->type == xevent->type && - esd->current_event->xany.window == xevent->xany.window) - { - esd->count += 1; - esd->last_time = xevent->xmotion.time; - } - - return False; -} - -static gboolean -check_use_this_motion_notify (MetaWindow *window, - XEvent *event) -{ - EventScannerData esd; - XEvent useless; - - /* This code is copied from Owen's GDK code. */ - - if (window->display->grab_motion_notify_time != 0) - { - /* == is really the right test, but I'm all for paranoia */ - if (window->display->grab_motion_notify_time <= - event->xmotion.time) - { - meta_topic (META_DEBUG_RESIZING, - "Arrived at event with time %u (waiting for %u), using it\n", - (unsigned int)event->xmotion.time, - window->display->grab_motion_notify_time); - window->display->grab_motion_notify_time = 0; - return TRUE; - } - else - return FALSE; /* haven't reached the saved timestamp yet */ - } - - esd.current_event = event; - esd.count = 0; - esd.last_time = 0; - - /* "useless" isn't filled in because the predicate never returns True */ - XCheckIfEvent (window->display->xdisplay, - &useless, - find_last_time_predicate, - (XPointer) &esd); - - if (esd.count > 0) - meta_topic (META_DEBUG_RESIZING, - "Will skip %d motion events and use the event with time %u\n", - esd.count, (unsigned int) esd.last_time); - - if (esd.last_time == 0) - return TRUE; - else - { - /* Save this timestamp, and ignore all motion notify - * until we get to the one with this stamp. - */ - window->display->grab_motion_notify_time = esd.last_time; - return FALSE; - } -} - -void -meta_window_handle_mouse_grab_op_event (MetaWindow *window, - XEvent *event) -{ -#ifdef HAVE_XSYNC - if (event->type == (window->display->xsync_event_base + XSyncAlarmNotify)) - { - meta_topic (META_DEBUG_RESIZING, - "Alarm event received last motion x = %d y = %d\n", - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y); - - /* If sync was previously disabled, turn it back on and hope - * the application has come to its senses (maybe it was just - * busy with a pagefault or a long computation). - */ - window->disable_sync = FALSE; - window->sync_request_time.tv_sec = 0; - window->sync_request_time.tv_usec = 0; - - /* This means we are ready for another configure. */ - switch (window->display->grab_op) - { - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - /* no pointer round trip here, to keep in sync */ - update_resize (window, - window->display->grab_last_user_action_was_snap, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y, - TRUE); - break; - - default: - break; - } - } -#endif /* HAVE_XSYNC */ - - switch (event->type) - { - case ButtonRelease: - meta_display_check_threshold_reached (window->display, - event->xbutton.x_root, - event->xbutton.y_root); - /* If the user was snap moving then ignore the button release - * because they may have let go of shift before releasing the - * mouse button and they almost certainly do not want a - * non-snapped movement to occur from the button release. - */ - if (!window->display->grab_last_user_action_was_snap) - { - if (meta_grab_op_is_moving (window->display->grab_op)) - { - if (event->xbutton.root == window->screen->xroot) - update_move (window, event->xbutton.state & ShiftMask, - event->xbutton.x_root, event->xbutton.y_root); - } - else if (meta_grab_op_is_resizing (window->display->grab_op)) - { - if (event->xbutton.root == window->screen->xroot) - update_resize (window, - event->xbutton.state & ShiftMask, - event->xbutton.x_root, - event->xbutton.y_root, - TRUE); - if (window->display->compositor) - meta_compositor_set_updates (window->display->compositor, window, TRUE); - } - } - - meta_display_end_grab_op (window->display, event->xbutton.time); - break; - - case MotionNotify: - meta_display_check_threshold_reached (window->display, - event->xmotion.x_root, - event->xmotion.y_root); - if (meta_grab_op_is_moving (window->display->grab_op)) - { - if (event->xmotion.root == window->screen->xroot) - { - if (check_use_this_motion_notify (window, - event)) - update_move (window, - event->xmotion.state & ShiftMask, - event->xmotion.x_root, - event->xmotion.y_root); - } - } - else if (meta_grab_op_is_resizing (window->display->grab_op)) - { - if (event->xmotion.root == window->screen->xroot) - { - if (check_use_this_motion_notify (window, - event)) - update_resize (window, - event->xmotion.state & ShiftMask, - event->xmotion.x_root, - event->xmotion.y_root, - FALSE); - } - } - break; - - default: - break; - } -} - -void -meta_window_set_gravity (MetaWindow *window, - int gravity) -{ - XSetWindowAttributes attrs; - - meta_verbose ("Setting gravity of %s to %d\n", window->desc, gravity); - - attrs.win_gravity = gravity; - - meta_error_trap_push (window->display); - - XChangeWindowAttributes (window->display->xdisplay, - window->xwindow, - CWWinGravity, - &attrs); - - meta_error_trap_pop (window->display, FALSE); -} - -static void -get_work_area_xinerama (MetaWindow *window, - MetaRectangle *area, - int which_xinerama) -{ - GList *tmp; - - g_assert (which_xinerama >= 0); - - /* Initialize to the whole xinerama */ - *area = window->screen->xinerama_infos[which_xinerama].rect; - - tmp = meta_window_get_workspaces (window); - while (tmp != NULL) - { - MetaRectangle workspace_work_area; - meta_workspace_get_work_area_for_xinerama (tmp->data, - which_xinerama, - &workspace_work_area); - meta_rectangle_intersect (area, - &workspace_work_area, - area); - tmp = tmp->next; - } - - meta_topic (META_DEBUG_WORKAREA, - "Window %s xinerama %d has work area %d,%d %d x %d\n", - window->desc, which_xinerama, - area->x, area->y, area->width, area->height); -} - -void -meta_window_get_work_area_current_xinerama (MetaWindow *window, - MetaRectangle *area) -{ - const MetaXineramaScreenInfo *xinerama = NULL; - xinerama = meta_screen_get_xinerama_for_window (window->screen, - window); - - meta_window_get_work_area_for_xinerama (window, - xinerama->number, - area); -} - -void -meta_window_get_work_area_for_xinerama (MetaWindow *window, - int which_xinerama, - MetaRectangle *area) -{ - g_return_if_fail (which_xinerama >= 0); - - get_work_area_xinerama (window, - area, - which_xinerama); -} - -void -meta_window_get_work_area_all_xineramas (MetaWindow *window, - MetaRectangle *area) -{ - GList *tmp; - - /* Initialize to the whole screen */ - *area = window->screen->rect; - - tmp = meta_window_get_workspaces (window); - while (tmp != NULL) - { - MetaRectangle workspace_work_area; - meta_workspace_get_work_area_all_xineramas (tmp->data, - &workspace_work_area); - meta_rectangle_intersect (area, - &workspace_work_area, - area); - tmp = tmp->next; - } - - meta_topic (META_DEBUG_WORKAREA, - "Window %s has whole-screen work area %d,%d %d x %d\n", - window->desc, area->x, area->y, area->width, area->height); -} - - -gboolean -meta_window_same_application (MetaWindow *window, - MetaWindow *other_window) -{ - MetaGroup *group = meta_window_get_group (window); - MetaGroup *other_group = meta_window_get_group (other_window); - - return - group!=NULL && - other_group!=NULL && - group==other_group; -} - -void -meta_window_refresh_resize_popup (MetaWindow *window) -{ - if (window->display->grab_op == META_GRAB_OP_NONE) - return; - - if (window->display->grab_window != window) - return; - - /* We shouldn't ever get called when the wireframe is active - * because that's handled by a different code path in effects.c - */ - if (window->display->grab_wireframe_active) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "refresh_resize_popup called when wireframe active\n"); - return; - } - - switch (window->display->grab_op) - { - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - break; - - default: - /* Not resizing */ - return; - } - - if (window->display->grab_resize_popup == NULL) - { - if (window->size_hints.width_inc > 1 || - window->size_hints.height_inc > 1) - window->display->grab_resize_popup = - meta_ui_resize_popup_new (window->display->xdisplay, - window->screen->number); - } - - if (window->display->grab_resize_popup != NULL) - { - MetaRectangle rect; - - if (window->display->grab_wireframe_active) - rect = window->display->grab_wireframe_rect; - else - meta_window_get_client_root_coords (window, &rect); - - meta_ui_resize_popup_set (window->display->grab_resize_popup, - rect, - window->size_hints.base_width, - window->size_hints.base_height, - window->size_hints.width_inc, - window->size_hints.height_inc); - - meta_ui_resize_popup_set_showing (window->display->grab_resize_popup, - TRUE); - } -} - -void -meta_window_foreach_transient (MetaWindow *window, - MetaWindowForeachFunc func, - void *data) -{ - GSList *windows; - GSList *tmp; - - windows = meta_display_list_windows (window->display); - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *transient = tmp->data; - - if (meta_window_is_ancestor_of_transient (window, transient)) - { - if (!(* func) (transient, data)) - break; - } - - tmp = tmp->next; - } - - g_slist_free (windows); -} - -void -meta_window_foreach_ancestor (MetaWindow *window, - MetaWindowForeachFunc func, - void *data) -{ - MetaWindow *w; - MetaWindow *tortoise; - - w = window; - tortoise = window; - while (TRUE) - { - if (w->xtransient_for == None || - w->transient_parent_is_root_window) - break; - - w = meta_display_lookup_x_window (w->display, w->xtransient_for); - - if (w == NULL || w == tortoise) - break; - - if (!(* func) (w, data)) - break; - - if (w->xtransient_for == None || - w->transient_parent_is_root_window) - break; - - w = meta_display_lookup_x_window (w->display, w->xtransient_for); - - if (w == NULL || w == tortoise) - break; - - if (!(* func) (w, data)) - break; - - tortoise = meta_display_lookup_x_window (tortoise->display, - tortoise->xtransient_for); - - /* "w" should have already covered all ground covered by the - * tortoise, so the following must hold. - */ - g_assert (tortoise != NULL); - g_assert (tortoise->xtransient_for != None); - g_assert (!tortoise->transient_parent_is_root_window); - } -} - -typedef struct -{ - MetaWindow *ancestor; - gboolean found; -} FindAncestorData; - -static gboolean -find_ancestor_func (MetaWindow *window, - void *data) -{ - FindAncestorData *d = data; - - if (window == d->ancestor) - { - d->found = TRUE; - return FALSE; - } - - return TRUE; -} - -gboolean -meta_window_is_ancestor_of_transient (MetaWindow *window, - MetaWindow *transient) -{ - FindAncestorData d; - - d.ancestor = window; - d.found = FALSE; - - meta_window_foreach_ancestor (transient, find_ancestor_func, &d); - - return d.found; -} - -/* Warp pointer to location appropriate for grab, - * return root coordinates where pointer ended up. - */ -static gboolean -warp_grab_pointer (MetaWindow *window, - MetaGrabOp grab_op, - int *x, - int *y) -{ - MetaRectangle rect; - MetaDisplay *display; - - display = window->display; - - /* We may not have done begin_grab_op yet, i.e. may not be in a grab - */ - - if (window == display->grab_window && display->grab_wireframe_active) - { - meta_window_get_xor_rect (window, &display->grab_wireframe_rect, &rect); - } - else - { - meta_window_get_outer_rect (window, &rect); - } - - switch (grab_op) - { - case META_GRAB_OP_KEYBOARD_MOVING: - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - *x = rect.width / 2; - *y = rect.height / 2; - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_S: - *x = rect.width / 2; - *y = rect.height - 1; - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_N: - *x = rect.width / 2; - *y = 0; - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_W: - *x = 0; - *y = rect.height / 2; - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_E: - *x = rect.width - 1; - *y = rect.height / 2; - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - *x = rect.width - 1; - *y = rect.height - 1; - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - *x = rect.width - 1; - *y = 0; - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - *x = 0; - *y = rect.height - 1; - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - *x = 0; - *y = 0; - break; - - default: - return FALSE; - } - - *x += rect.x; - *y += rect.y; - - /* Avoid weird bouncing at the screen edge; see bug 154706 */ - *x = CLAMP (*x, 0, window->screen->rect.width-1); - *y = CLAMP (*y, 0, window->screen->rect.height-1); - - meta_error_trap_push_with_return (display); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Warping pointer to %d,%d with window at %d,%d\n", - *x, *y, rect.x, rect.y); - - /* Need to update the grab positions so that the MotionNotify and other - * events generated by the XWarpPointer() call below don't cause complete - * funkiness. See bug 124582 and bug 122670. - */ - display->grab_anchor_root_x = *x; - display->grab_anchor_root_y = *y; - display->grab_latest_motion_x = *x; - display->grab_latest_motion_y = *y; - if (display->grab_wireframe_active) - display->grab_anchor_window_pos = display->grab_wireframe_rect; - else - meta_window_get_client_root_coords (window, - &display->grab_anchor_window_pos); - - XWarpPointer (display->xdisplay, - None, - window->screen->xroot, - 0, 0, 0, 0, - *x, *y); - - if (meta_error_trap_pop_with_return (display, FALSE) != Success) - { - meta_verbose ("Failed to warp pointer for window %s\n", - window->desc); - return FALSE; - } - - return TRUE; -} - -void -meta_window_begin_grab_op (MetaWindow *window, - MetaGrabOp op, - gboolean frame_action, - guint32 timestamp) -{ - int x, y; - - warp_grab_pointer (window, - op, &x, &y); - - meta_display_begin_grab_op (window->display, - window->screen, - window, - op, - FALSE, - frame_action, - 0 /* button */, - 0, - timestamp, - x, y); -} - -void -meta_window_update_keyboard_resize (MetaWindow *window, - gboolean update_cursor) -{ - int x, y; - - warp_grab_pointer (window, - window->display->grab_op, - &x, &y); - - if (update_cursor) - { - guint32 timestamp; - /* FIXME: Using CurrentTime is really bad mojo */ - timestamp = CurrentTime; - meta_display_set_grab_op_cursor (window->display, - NULL, - window->display->grab_op, - TRUE, - window->display->grab_xwindow, - timestamp); - } -} - -void -meta_window_update_keyboard_move (MetaWindow *window) -{ - int x, y; - - warp_grab_pointer (window, - window->display->grab_op, - &x, &y); -} - -void -meta_window_update_layer (MetaWindow *window) -{ - MetaGroup *group; - - meta_stack_freeze (window->screen->stack); - group = meta_window_get_group (window); - if (group) - meta_group_update_layers (group); - else - meta_stack_update_layer (window->screen->stack, window); - meta_stack_thaw (window->screen->stack); -} - -/* ensure_mru_position_after ensures that window appears after - * below_this_one in the active_workspace's mru_list (i.e. it treats - * window as having been less recently used than below_this_one) - */ -static void -ensure_mru_position_after (MetaWindow *window, - MetaWindow *after_this_one) -{ - /* This is sort of slow since it runs through the entire list more - * than once (especially considering the fact that we expect the - * windows of interest to be the first two elements in the list), - * but it doesn't matter while we're only using it on new window - * map. - */ - - GList* active_mru_list; - GList* window_position; - GList* after_this_one_position; - - active_mru_list = window->screen->active_workspace->mru_list; - window_position = g_list_find (active_mru_list, window); - after_this_one_position = g_list_find (active_mru_list, after_this_one); - - /* after_this_one_position is NULL when we switch workspaces, but in - * that case we don't need to do any MRU shuffling so we can simply - * return. - */ - if (after_this_one_position == NULL) - return; - - if (g_list_length (window_position) > g_list_length (after_this_one_position)) - { - window->screen->active_workspace->mru_list = - g_list_delete_link (window->screen->active_workspace->mru_list, - window_position); - - window->screen->active_workspace->mru_list = - g_list_insert_before (window->screen->active_workspace->mru_list, - after_this_one_position->next, - window); - } -} - -void -meta_window_stack_just_below (MetaWindow *window, - MetaWindow *below_this_one) -{ - g_return_if_fail (window != NULL); - g_return_if_fail (below_this_one != NULL); - - if (window->stack_position > below_this_one->stack_position) - { - meta_topic (META_DEBUG_STACK, - "Setting stack position of window %s to %d (making it below window %s).\n", - window->desc, - below_this_one->stack_position, - below_this_one->desc); - meta_window_set_stack_position (window, below_this_one->stack_position); - } - else - { - meta_topic (META_DEBUG_STACK, - "Window %s was already below window %s.\n", - window->desc, below_this_one->desc); - } -} - -void -meta_window_set_user_time (MetaWindow *window, - guint32 timestamp) -{ - /* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow - * us to sanity check the timestamp here and ensure it doesn't correspond to - * a future time. - */ - - /* Only update the time if this timestamp is newer... */ - if (window->net_wm_user_time_set && - XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time)) - { - meta_topic (META_DEBUG_STARTUP, - "Window %s _NET_WM_USER_TIME not updated to %u, because it " - "is less than %u\n", - window->desc, timestamp, window->net_wm_user_time); - } - else - { - meta_topic (META_DEBUG_STARTUP, - "Window %s has _NET_WM_USER_TIME of %u\n", - window->desc, timestamp); - window->net_wm_user_time_set = TRUE; - window->net_wm_user_time = timestamp; - if (XSERVER_TIME_IS_BEFORE (window->display->last_user_time, timestamp)) - window->display->last_user_time = timestamp; - - /* If this is a terminal, user interaction with it means the user likely - * doesn't want to have focus transferred for now due to new windows. - */ - if (meta_prefs_get_focus_new_windows () == - META_FOCUS_NEW_WINDOWS_STRICT && - __window_is_terminal (window)) - window->display->allow_terminal_deactivation = FALSE; - } -} - -/* Sets the demands_attention hint on a window, but only - * if it's at least partially obscured (see #305882). - */ -void -meta_window_set_demands_attention (MetaWindow *window) -{ - MetaRectangle candidate_rect, other_rect; - GList *stack = window->screen->stack->sorted; - MetaWindow *other_window; - gboolean obscured = FALSE; - - MetaWorkspace *workspace = window->screen->active_workspace; - if (workspace!=window->workspace) - { - /* windows on other workspaces are necessarily obscured */ - obscured = TRUE; - } - else if (window->minimized) - { - obscured = TRUE; - } - else - { - meta_window_get_outer_rect (window, &candidate_rect); - - /* The stack is sorted with the top windows first. */ - - while (stack != NULL && stack->data != window) - { - other_window = stack->data; - stack = stack->next; - - if (other_window->on_all_workspaces || - window->on_all_workspaces || - other_window->workspace == window->workspace) - { - meta_window_get_outer_rect (other_window, &other_rect); - - if (meta_rectangle_overlap (&candidate_rect, &other_rect)) - { - obscured = TRUE; - break; - } - } - } - } - - if (obscured) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Marking %s as needing attention\n", - window->desc); - - window->wm_state_demands_attention = TRUE; - set_net_wm_state (window); - } - else - { - /* If the window's in full view, there's no point setting the flag. */ - - meta_topic (META_DEBUG_WINDOW_OPS, - "Not marking %s as needing attention because " - "it's in full view\n", - window->desc); - } -} - -void -meta_window_unset_demands_attention (MetaWindow *window) -{ - meta_topic (META_DEBUG_WINDOW_OPS, - "Marking %s as not needing attention\n", window->desc); - - window->wm_state_demands_attention = FALSE; - set_net_wm_state (window); -} - -MetaFrame * -meta_window_get_frame (MetaWindow *window) -{ - return window->frame; -} - -gboolean -meta_window_has_focus (MetaWindow *window) -{ - return window->has_focus; -} - -gboolean -meta_window_is_shaded (MetaWindow *window) -{ - return window->shaded; -} - -MetaRectangle * -meta_window_get_rect (MetaWindow *window) -{ - return &window->rect; -} - -MetaScreen * -meta_window_get_screen (MetaWindow *window) -{ - return window->screen; -} - -MetaDisplay * -meta_window_get_display (MetaWindow *window) -{ - return window->display; -} - -Window -meta_window_get_xwindow (MetaWindow *window) -{ - return window->xwindow; -} diff --git a/src/core/workspace.c b/src/core/workspace.c deleted file mode 100644 index ddb2541f..00000000 --- a/src/core/workspace.c +++ /dev/null @@ -1,976 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity Workspaces */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004, 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "workspace.h" -#include "errors.h" -#include "prefs.h" -#include <X11/Xatom.h> -#include <string.h> - -void meta_workspace_queue_calc_showing (MetaWorkspace *workspace); -static void set_active_space_hint (MetaScreen *screen); -static void focus_ancestor_or_mru_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp); -static void free_this (gpointer candidate, - gpointer dummy); -static void workspace_free_struts (MetaWorkspace *workspace); - -static void -maybe_add_to_list (MetaScreen *screen, MetaWindow *window, gpointer data) -{ - GList **mru_list = data; - - if (window->on_all_workspaces) - *mru_list = g_list_prepend (*mru_list, window); -} - -MetaWorkspace* -meta_workspace_new (MetaScreen *screen) -{ - MetaWorkspace *workspace; - - workspace = g_new (MetaWorkspace, 1); - - workspace->screen = screen; - workspace->screen->workspaces = - g_list_append (workspace->screen->workspaces, workspace); - workspace->windows = NULL; - workspace->mru_list = NULL; - meta_screen_foreach_window (screen, maybe_add_to_list, &workspace->mru_list); - - workspace->work_areas_invalid = TRUE; - workspace->work_area_xinerama = NULL; - workspace->work_area_screen.x = 0; - workspace->work_area_screen.y = 0; - workspace->work_area_screen.width = 0; - workspace->work_area_screen.height = 0; - - workspace->screen_region = NULL; - workspace->xinerama_region = NULL; - workspace->screen_edges = NULL; - workspace->xinerama_edges = NULL; - workspace->list_containing_self = g_list_prepend (NULL, workspace); - - workspace->all_struts = NULL; - - workspace->showing_desktop = FALSE; - - return workspace; -} - -/** Foreach function for workspace_free_struts() */ -static void -free_this (gpointer candidate, gpointer dummy) -{ - g_free (candidate); -} - -/** - * Frees the struts list of a workspace. - * - * \param workspace The workspace. - */ -static void -workspace_free_struts (MetaWorkspace *workspace) -{ - if (workspace->all_struts == NULL) - return; - - g_slist_foreach (workspace->all_struts, free_this, NULL); - g_slist_free (workspace->all_struts); - workspace->all_struts = NULL; -} - -void -meta_workspace_free (MetaWorkspace *workspace) -{ - GList *tmp; - MetaScreen *screen; - int i; - - g_return_if_fail (workspace != workspace->screen->active_workspace); - - /* Here we assume all the windows are already on another workspace - * as well, so they won't be "orphaned" - */ - - tmp = workspace->windows; - while (tmp != NULL) - { - GList *next; - MetaWindow *window = tmp->data; - next = tmp->next; - - /* pop front of list we're iterating over */ - meta_workspace_remove_window (workspace, window); - g_assert (window->workspace != NULL); - - tmp = next; - } - - g_assert (workspace->windows == NULL); - - screen = workspace->screen; - - workspace->screen->workspaces = - g_list_remove (workspace->screen->workspaces, workspace); - - g_free (workspace->work_area_xinerama); - - g_list_free (workspace->mru_list); - g_list_free (workspace->list_containing_self); - - /* screen.c:update_num_workspaces(), which calls us, removes windows from - * workspaces first, which can cause the workareas on the workspace to be - * invalidated (and hence for struts/regions/edges to be freed). - * So, no point trying to double free it; that causes a crash - * anyway. #361804. - */ - - if (!workspace->work_areas_invalid) - { - workspace_free_struts (workspace); - for (i = 0; i < screen->n_xinerama_infos; i++) - meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]); - g_free (workspace->xinerama_region); - meta_rectangle_free_list_and_elements (workspace->screen_region); - meta_rectangle_free_list_and_elements (workspace->screen_edges); - meta_rectangle_free_list_and_elements (workspace->xinerama_edges); - } - - g_free (workspace); - - /* don't bother to reset names, pagers can just ignore - * extra ones - */ -} - -void -meta_workspace_add_window (MetaWorkspace *workspace, - MetaWindow *window) -{ - g_return_if_fail (window->workspace == NULL); - - /* If the window is on all workspaces, we want to add it to all mru - * lists, otherwise just add it to this workspaces mru list - */ - if (window->on_all_workspaces) - { - if (window->workspace == NULL) - { - GList* tmp = window->screen->workspaces; - while (tmp) - { - MetaWorkspace* work = (MetaWorkspace*) tmp->data; - if (!g_list_find (work->mru_list, window)) - work->mru_list = g_list_prepend (work->mru_list, window); - - tmp = tmp->next; - } - } - } - else - { - g_assert (g_list_find (workspace->mru_list, window) == NULL); - workspace->mru_list = g_list_prepend (workspace->mru_list, window); - } - - workspace->windows = g_list_prepend (workspace->windows, window); - window->workspace = workspace; - - meta_window_set_current_workspace_hint (window); - - if (window->struts) - { - meta_topic (META_DEBUG_WORKAREA, - "Invalidating work area of workspace %d since we're adding window %s to it\n", - meta_workspace_index (workspace), window->desc); - meta_workspace_invalidate_work_area (workspace); - } - - /* queue a move_resize since changing workspaces may change - * the relevant struts - */ - meta_window_queue (window, META_QUEUE_CALC_SHOWING|META_QUEUE_MOVE_RESIZE); -} - -void -meta_workspace_remove_window (MetaWorkspace *workspace, - MetaWindow *window) -{ - g_return_if_fail (window->workspace == workspace); - - workspace->windows = g_list_remove (workspace->windows, window); - window->workspace = NULL; - - /* If the window is on all workspaces, we don't want to remove it - * from the MRU list unless this causes it to be removed from all - * workspaces - */ - if (window->on_all_workspaces) - { - GList* tmp = window->screen->workspaces; - while (tmp) - { - MetaWorkspace* work = (MetaWorkspace*) tmp->data; - work->mru_list = g_list_remove (work->mru_list, window); - - tmp = tmp->next; - } - } - else - { - workspace->mru_list = g_list_remove (workspace->mru_list, window); - g_assert (g_list_find (workspace->mru_list, window) == NULL); - } - - meta_window_set_current_workspace_hint (window); - - if (window->struts) - { - meta_topic (META_DEBUG_WORKAREA, - "Invalidating work area of workspace %d since we're removing window %s from it\n", - meta_workspace_index (workspace), window->desc); - meta_workspace_invalidate_work_area (workspace); - } - - /* queue a move_resize since changing workspaces may change - * the relevant struts - */ - meta_window_queue (window, META_QUEUE_CALC_SHOWING|META_QUEUE_MOVE_RESIZE); -} - -void -meta_workspace_relocate_windows (MetaWorkspace *workspace, - MetaWorkspace *new_home) -{ - GList *tmp; - GList *copy; - - g_return_if_fail (workspace != new_home); - - /* can't modify list we're iterating over */ - copy = g_list_copy (workspace->windows); - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - meta_workspace_remove_window (workspace, window); - meta_workspace_add_window (new_home, window); - - tmp = tmp->next; - } - - g_list_free (copy); - - g_assert (workspace->windows == NULL); -} - -void -meta_workspace_queue_calc_showing (MetaWorkspace *workspace) -{ - GList *tmp; - - tmp = workspace->windows; - while (tmp != NULL) - { - meta_window_queue (tmp->data, META_QUEUE_CALC_SHOWING); - - tmp = tmp->next; - } -} - -void -meta_workspace_activate_with_focus (MetaWorkspace *workspace, - MetaWindow *focus_this, - guint32 timestamp) -{ - MetaWorkspace *old; - MetaWindow *move_window; - - meta_verbose ("Activating workspace %d\n", - meta_workspace_index (workspace)); - - if (workspace->screen->active_workspace == workspace) - return; - - /* Note that old can be NULL; e.g. when starting up */ - old = workspace->screen->active_workspace; - - workspace->screen->active_workspace = workspace; - - set_active_space_hint (workspace->screen); - - /* If the "show desktop" mode is active for either the old workspace - * or the new one *but not both*, then update the - * _net_showing_desktop hint - */ - if (old && (old->showing_desktop ^ workspace->showing_desktop)) - meta_screen_update_showing_desktop_hint (workspace->screen); - - if (old == NULL) - return; - - move_window = NULL; - if (workspace->screen->display->grab_op == META_GRAB_OP_MOVING || - workspace->screen->display->grab_op == META_GRAB_OP_KEYBOARD_MOVING) - move_window = workspace->screen->display->grab_window; - - if (move_window != NULL) - { - if (move_window->on_all_workspaces) - move_window = NULL; /* don't move it after all */ - - /* We put the window on the new workspace, flip spaces, - * then remove from old workspace, so the window - * never gets unmapped and we maintain the button grab - * on it. - * - * \bug This comment appears to be the reverse of what happens - */ - if (move_window && (move_window->workspace != workspace)) - { - meta_workspace_remove_window (old, move_window); - meta_workspace_add_window (workspace, move_window); - } - } - - meta_workspace_queue_calc_showing (old); - meta_workspace_queue_calc_showing (workspace); - - /* FIXME: Why do we need this?!? Isn't it handled in the lines above? */ - if (move_window) - /* Removes window from other spaces */ - meta_window_change_workspace (move_window, workspace); - - if (focus_this) - { - meta_window_focus (focus_this, timestamp); - meta_window_raise (focus_this); - } - else if (move_window) - { - meta_window_raise (move_window); - } - else - { - meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n"); - meta_workspace_focus_default_window (workspace, NULL, timestamp); - } -} - -void -meta_workspace_activate (MetaWorkspace *workspace, - guint32 timestamp) -{ - meta_workspace_activate_with_focus (workspace, NULL, timestamp); -} - -int -meta_workspace_index (MetaWorkspace *workspace) -{ - int ret; - - ret = g_list_index (workspace->screen->workspaces, workspace); - - if (ret < 0) - meta_bug ("Workspace does not exist to index!\n"); - - return ret; -} - -/* get windows contained on workspace, including workspace->windows - * and also sticky windows. - */ -GList* -meta_workspace_list_windows (MetaWorkspace *workspace) -{ - GSList *display_windows; - GSList *tmp; - GList *workspace_windows; - - display_windows = meta_display_list_windows (workspace->screen->display); - - workspace_windows = NULL; - tmp = display_windows; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (meta_window_located_on_workspace (window, workspace)) - workspace_windows = g_list_prepend (workspace_windows, - window); - - tmp = tmp->next; - } - - g_slist_free (display_windows); - - return workspace_windows; -} - -static void -set_active_space_hint (MetaScreen *screen) -{ - unsigned long data[1]; - - /* this is because we destroy the spaces in order, - * so we always end up setting a current desktop of - * 0 when closing a screen, so lose the current desktop - * on restart. By doing this we keep the current - * desktop on restart. - */ - if (screen->closing > 0) - return; - - data[0] = meta_workspace_index (screen->active_workspace); - - meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu\n", data[0]); - - meta_error_trap_push (screen->display); - XChangeProperty (screen->display->xdisplay, screen->xroot, - screen->display->atom__NET_CURRENT_DESKTOP, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - meta_error_trap_pop (screen->display, FALSE); -} - -void -meta_workspace_invalidate_work_area (MetaWorkspace *workspace) -{ - GList *tmp; - GList *windows; - int i; - - if (workspace->work_areas_invalid) - { - meta_topic (META_DEBUG_WORKAREA, - "Work area for workspace %d is already invalid\n", - meta_workspace_index (workspace)); - return; - } - - meta_topic (META_DEBUG_WORKAREA, - "Invalidating work area for workspace %d\n", - meta_workspace_index (workspace)); - - g_free (workspace->work_area_xinerama); - workspace->work_area_xinerama = NULL; - - workspace_free_struts (workspace); - - for (i = 0; i < workspace->screen->n_xinerama_infos; i++) - meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]); - g_free (workspace->xinerama_region); - meta_rectangle_free_list_and_elements (workspace->screen_region); - meta_rectangle_free_list_and_elements (workspace->screen_edges); - meta_rectangle_free_list_and_elements (workspace->xinerama_edges); - workspace->xinerama_region = NULL; - workspace->screen_region = NULL; - workspace->screen_edges = NULL; - workspace->xinerama_edges = NULL; - - workspace->work_areas_invalid = TRUE; - - /* redo the size/position constraints on all windows */ - windows = meta_workspace_list_windows (workspace); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - meta_window_queue (w, META_QUEUE_MOVE_RESIZE); - - tmp = tmp->next; - } - - g_list_free (windows); - - meta_screen_queue_workarea_recalc (workspace->screen); -} - -static void -ensure_work_areas_validated (MetaWorkspace *workspace) -{ - GList *windows; - GList *tmp; - MetaRectangle work_area; - int i; /* C89 absolutely sucks... */ - - if (!workspace->work_areas_invalid) - return; - - g_assert (workspace->all_struts == NULL); - g_assert (workspace->xinerama_region == NULL); - g_assert (workspace->screen_region == NULL); - g_assert (workspace->screen_edges == NULL); - g_assert (workspace->xinerama_edges == NULL); - - /* STEP 1: Get the list of struts */ - windows = meta_workspace_list_windows (workspace); - for (tmp = windows; tmp != NULL; tmp = tmp->next) - { - MetaWindow *win = tmp->data; - GSList *s_iter; - - for (s_iter = win->struts; s_iter != NULL; s_iter = s_iter->next) { - MetaStrut *cpy = g_new (MetaStrut, 1); - *cpy = *((MetaStrut *)s_iter->data); - workspace->all_struts = g_slist_prepend (workspace->all_struts, - cpy); - } - } - g_list_free (windows); - - /* STEP 2: Get the maximal/spanning rects for the onscreen and - * on-single-xinerama regions - */ - g_assert (workspace->xinerama_region == NULL); - g_assert (workspace->screen_region == NULL); - - workspace->xinerama_region = g_new (GList*, - workspace->screen->n_xinerama_infos); - for (i = 0; i < workspace->screen->n_xinerama_infos; i++) - { - workspace->xinerama_region[i] = - meta_rectangle_get_minimal_spanning_set_for_region ( - &workspace->screen->xinerama_infos[i].rect, - workspace->all_struts); - } - workspace->screen_region = - meta_rectangle_get_minimal_spanning_set_for_region ( - &workspace->screen->rect, - workspace->all_struts); - - /* STEP 3: Get the work areas (region-to-maximize-to) for the screen and - * xineramas. - */ - work_area = workspace->screen->rect; /* start with the screen */ - if (workspace->screen_region == NULL) - work_area = meta_rect (0, 0, -1, -1); - else - meta_rectangle_clip_to_region (workspace->screen_region, - FIXED_DIRECTION_NONE, - &work_area); - - /* Lots of paranoia checks, forcing work_area_screen to be sane */ -#define MIN_SANE_AREA 100 - if (work_area.width < MIN_SANE_AREA) - { - meta_warning ("struts occupy an unusually large percentage of the screen; " - "available remaining width = %d < %d", - work_area.width, MIN_SANE_AREA); - if (work_area.width < 1) - { - work_area.x = (workspace->screen->rect.width - MIN_SANE_AREA)/2; - work_area.width = MIN_SANE_AREA; - } - else - { - int amount = (MIN_SANE_AREA - work_area.width)/2; - work_area.x -= amount; - work_area.width += 2*amount; - } - } - if (work_area.height < MIN_SANE_AREA) - { - meta_warning ("struts occupy an unusually large percentage of the screen; " - "available remaining height = %d < %d", - work_area.height, MIN_SANE_AREA); - if (work_area.height < 1) - { - work_area.y = (workspace->screen->rect.height - MIN_SANE_AREA)/2; - work_area.height = MIN_SANE_AREA; - } - else - { - int amount = (MIN_SANE_AREA - work_area.height)/2; - work_area.y -= amount; - work_area.height += 2*amount; - } - } - workspace->work_area_screen = work_area; - meta_topic (META_DEBUG_WORKAREA, - "Computed work area for workspace %d: %d,%d %d x %d\n", - meta_workspace_index (workspace), - workspace->work_area_screen.x, - workspace->work_area_screen.y, - workspace->work_area_screen.width, - workspace->work_area_screen.height); - - /* Now find the work areas for each xinerama */ - g_free (workspace->work_area_xinerama); - workspace->work_area_xinerama = g_new (MetaRectangle, - workspace->screen->n_xinerama_infos); - - for (i = 0; i < workspace->screen->n_xinerama_infos; i++) - { - work_area = workspace->screen->xinerama_infos[i].rect; - - if (workspace->xinerama_region[i] == NULL) - /* FIXME: constraints.c untested with this, but it might be nice for - * a screen reader or magnifier. - */ - work_area = meta_rect (work_area.x, work_area.y, -1, -1); - else - meta_rectangle_clip_to_region (workspace->xinerama_region[i], - FIXED_DIRECTION_NONE, - &work_area); - - workspace->work_area_xinerama[i] = work_area; - meta_topic (META_DEBUG_WORKAREA, - "Computed work area for workspace %d " - "xinerama %d: %d,%d %d x %d\n", - meta_workspace_index (workspace), - i, - workspace->work_area_xinerama[i].x, - workspace->work_area_xinerama[i].y, - workspace->work_area_xinerama[i].width, - workspace->work_area_xinerama[i].height); - } - - /* STEP 4: Make sure the screen_region is nonempty (separate from step 2 - * since it relies on step 3). - */ - if (workspace->screen_region == NULL) - { - MetaRectangle *nonempty_region; - nonempty_region = g_new (MetaRectangle, 1); - *nonempty_region = workspace->work_area_screen; - workspace->screen_region = g_list_prepend (NULL, nonempty_region); - } - - /* STEP 5: Cache screen and xinerama edges for edge resistance and snapping */ - g_assert (workspace->screen_edges == NULL); - g_assert (workspace->xinerama_edges == NULL); - workspace->screen_edges = - meta_rectangle_find_onscreen_edges (&workspace->screen->rect, - workspace->all_struts); - tmp = NULL; - for (i = 0; i < workspace->screen->n_xinerama_infos; i++) - tmp = g_list_prepend (tmp, &workspace->screen->xinerama_infos[i].rect); - workspace->xinerama_edges = - meta_rectangle_find_nonintersected_xinerama_edges (tmp, - workspace->all_struts); - g_list_free (tmp); - - /* We're all done, YAAY! Record that everything has been validated. */ - workspace->work_areas_invalid = FALSE; -} - -void -meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace, - int which_xinerama, - MetaRectangle *area) -{ - g_assert (which_xinerama >= 0); - - ensure_work_areas_validated (workspace); - g_assert (which_xinerama < workspace->screen->n_xinerama_infos); - - *area = workspace->work_area_xinerama[which_xinerama]; -} - -void -meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace, - MetaRectangle *area) -{ - ensure_work_areas_validated (workspace); - - *area = workspace->work_area_screen; -} - -GList* -meta_workspace_get_onscreen_region (MetaWorkspace *workspace) -{ - ensure_work_areas_validated (workspace); - - return workspace->screen_region; -} - -GList* -meta_workspace_get_onxinerama_region (MetaWorkspace *workspace, - int which_xinerama) -{ - ensure_work_areas_validated (workspace); - - return workspace->xinerama_region[which_xinerama]; -} - -#ifdef WITH_VERBOSE_MODE -static char * -meta_motion_direction_to_string (MetaMotionDirection direction) -{ - switch (direction) - { - case META_MOTION_UP: - return "Up"; - case META_MOTION_DOWN: - return "Down"; - case META_MOTION_LEFT: - return "Left"; - case META_MOTION_RIGHT: - return "Right"; - } - - return "Unknown"; -} -#endif /* WITH_VERBOSE_MODE */ - -MetaWorkspace* -meta_workspace_get_neighbor (MetaWorkspace *workspace, - MetaMotionDirection direction) -{ - MetaWorkspaceLayout layout; - int i, current_space, num_workspaces; - gboolean ltr; - - current_space = meta_workspace_index (workspace); - num_workspaces = meta_screen_get_n_workspaces (workspace->screen); - meta_screen_calc_workspace_layout (workspace->screen, num_workspaces, - current_space, &layout); - - meta_verbose ("Getting neighbor of %d in direction %s\n", - current_space, meta_motion_direction_to_string (direction)); - - ltr = meta_ui_get_direction() == META_UI_DIRECTION_LTR; - - switch (direction) - { - case META_MOTION_LEFT: - layout.current_col -= ltr ? 1 : -1; - break; - case META_MOTION_RIGHT: - layout.current_col += ltr ? 1 : -1; - break; - case META_MOTION_UP: - layout.current_row -= 1; - break; - case META_MOTION_DOWN: - layout.current_row += 1; - break; - } - - if (layout.current_col < 0) - layout.current_col = 0; - if (layout.current_col >= layout.cols) - layout.current_col = layout.cols - 1; - if (layout.current_row < 0) - layout.current_row = 0; - if (layout.current_row >= layout.rows) - layout.current_row = layout.rows - 1; - - i = layout.grid[layout.current_row * layout.cols + layout.current_col]; - - if (i < 0) - i = current_space; - - if (i >= num_workspaces) - meta_bug ("calc_workspace_layout left an invalid (too-high) workspace number %d in the grid\n", - i); - - meta_verbose ("Neighbor workspace is %d at row %d col %d\n", - i, layout.current_row, layout.current_col); - - meta_screen_free_workspace_layout (&layout); - - return meta_screen_get_workspace_by_index (workspace->screen, i); -} - -const char* -meta_workspace_get_name (MetaWorkspace *workspace) -{ - return meta_prefs_get_workspace_name (meta_workspace_index (workspace)); -} - -void -meta_workspace_focus_default_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp) -{ - if (timestamp == CurrentTime) - { - meta_warning ("CurrentTime used to choose focus window; " - "focus window may not be correct.\n"); - } - - - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK || - !workspace->screen->display->mouse_mode) - focus_ancestor_or_mru_window (workspace, not_this_one, timestamp); - else - { - MetaWindow * window; - window = meta_screen_get_mouse_window (workspace->screen, not_this_one); - if (window && - window->type != META_WINDOW_DOCK && - window->type != META_WINDOW_DESKTOP) - { - if (timestamp == CurrentTime) - { - - /* We would like for this to never happen. However, if - * it does happen then we kludge since using CurrentTime - * can mean ugly race conditions--and we can avoid these - * by allowing EnterNotify events (which come with - * timestamps) to handle focus. - */ - - meta_topic (META_DEBUG_FOCUS, - "Not focusing mouse window %s because EnterNotify events should handle that\n", window->desc); - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Focusing mouse window %s\n", window->desc); - meta_window_focus (window, timestamp); - } - - if (workspace->screen->display->autoraise_window != window && - meta_prefs_get_auto_raise ()) - { - meta_display_queue_autoraise_callback (workspace->screen->display, - window); - } - } - else if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_SLOPPY) - focus_ancestor_or_mru_window (workspace, not_this_one, timestamp); - else if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_MOUSE) - { - meta_topic (META_DEBUG_FOCUS, - "Setting focus to no_focus_window, since no valid " - "window to focus found.\n"); - meta_display_focus_the_no_focus_window (workspace->screen->display, - workspace->screen, - timestamp); - } - } -} - -static gboolean -record_ancestor (MetaWindow *window, - void *data) -{ - MetaWindow **result = data; - - *result = window; - return FALSE; /* quit with the first ancestor we find */ -} - -/* Focus ancestor of not_this_one if there is one, otherwise focus the MRU - * window on active workspace - */ -static void -focus_ancestor_or_mru_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp) -{ - MetaWindow *window = NULL; - MetaWindow *desktop_window = NULL; - GList *tmp; - - if (not_this_one) - meta_topic (META_DEBUG_FOCUS, - "Focusing MRU window excluding %s\n", not_this_one->desc); - else - meta_topic (META_DEBUG_FOCUS, - "Focusing MRU window\n"); - - /* First, check to see if we need to focus an ancestor of a window */ - if (not_this_one) - { - MetaWindow *ancestor; - ancestor = NULL; - meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor); - if (ancestor != NULL) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing %s, ancestor of %s\n", - ancestor->desc, not_this_one->desc); - - meta_window_focus (ancestor, timestamp); - - /* Also raise the window if in click-to-focus */ - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK) - meta_window_raise (ancestor); - - return; - } - } - - /* No ancestor, look for the MRU window */ - tmp = workspace->mru_list; - - while (tmp) - { - MetaWindow* tmp_window; - tmp_window = ((MetaWindow*) tmp->data); - if (tmp_window != not_this_one && - meta_window_showing_on_its_workspace (tmp_window) && - tmp_window->type != META_WINDOW_DOCK && - tmp_window->type != META_WINDOW_DESKTOP) - { - window = tmp->data; - break; - } - else if (tmp_window != not_this_one && - desktop_window == NULL && - meta_window_showing_on_its_workspace (tmp_window) && - tmp_window->type == META_WINDOW_DESKTOP) - { - /* Found the most recently used desktop window */ - desktop_window = tmp_window; - } - - tmp = tmp->next; - } - - /* If no window was found, default to the MRU desktop-window */ - if (window == NULL) - window = desktop_window; - - if (window) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing workspace MRU window %s\n", window->desc); - - meta_window_focus (window, timestamp); - - /* Also raise the window if in click-to-focus */ - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK) - meta_window_raise (window); - } - else - { - meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found; focusing no_focus_window.\n"); - meta_display_focus_the_no_focus_window (workspace->screen->display, - workspace->screen, - timestamp); - } -} diff --git a/src/core/workspace.h b/src/core/workspace.h deleted file mode 100644 index f4079ebb..00000000 --- a/src/core/workspace.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file workspace.h Workspaces - * - * A workspace is a set of windows which all live on the same - * screen. (You may also see the name "desktop" around the place, - * which is the EWMH's name for the same thing.) Only one workspace - * of a screen may be active at once; all windows on all other workspaces - * are unmapped. - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2004, 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WORKSPACE_H -#define META_WORKSPACE_H - -#include "window-private.h" - -/* Negative to avoid conflicting with real workspace - * numbers - */ -typedef enum -{ - META_MOTION_UP = -1, - META_MOTION_DOWN = -2, - META_MOTION_LEFT = -3, - META_MOTION_RIGHT = -4 -} MetaMotionDirection; - -struct _MetaWorkspace -{ - MetaScreen *screen; - - GList *windows; - GList *mru_list; - - GList *list_containing_self; - - MetaRectangle work_area_screen; - MetaRectangle *work_area_xinerama; - GList *screen_region; - GList **xinerama_region; - GList *screen_edges; - GList *xinerama_edges; - GSList *all_struts; - guint work_areas_invalid : 1; - - guint showing_desktop : 1; -}; - -MetaWorkspace* meta_workspace_new (MetaScreen *screen); -void meta_workspace_free (MetaWorkspace *workspace); -void meta_workspace_add_window (MetaWorkspace *workspace, - MetaWindow *window); -void meta_workspace_remove_window (MetaWorkspace *workspace, - MetaWindow *window); -void meta_workspace_relocate_windows (MetaWorkspace *workspace, - MetaWorkspace *new_home); -void meta_workspace_activate_with_focus (MetaWorkspace *workspace, - MetaWindow *focus_this, - guint32 timestamp); -void meta_workspace_activate (MetaWorkspace *workspace, - guint32 timestamp); -int meta_workspace_index (MetaWorkspace *workspace); -GList* meta_workspace_list_windows (MetaWorkspace *workspace); - -void meta_workspace_invalidate_work_area (MetaWorkspace *workspace); - - -void meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace, - int which_xinerama, - MetaRectangle *area); -void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace, - MetaRectangle *area); -GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace); -GList* meta_workspace_get_onxinerama_region (MetaWorkspace *workspace, - int which_xinerama); -void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace, - MetaRectangle *area); - -void meta_workspace_focus_default_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp); - -MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace, - MetaMotionDirection direction); - -const char* meta_workspace_get_name (MetaWorkspace *workspace); - -#endif - - - - diff --git a/src/core/xprops.c b/src/core/xprops.c deleted file mode 100644 index a39c7b4f..00000000 --- a/src/core/xprops.c +++ /dev/null @@ -1,1238 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X property convenience routines */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat Inc. - * - * Some trivial property-unpacking code from Xlib: - * Copyright 1987, 1988, 1998 The Open Group - * Copyright 1988 by Wyse Technology, Inc., San Jose, Ca, - * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/*********************************************************** -Copyright 1988 by Wyse Technology, Inc., San Jose, Ca, -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL AND WYSE DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -EVENT SHALL DIGITAL OR WYSE BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - -******************************************************************/ - -/* - -Copyright 1987, 1988, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - -*/ - - -#include <config.h> -#include "xprops.h" -#include "errors.h" -#include "util.h" -#include "async-getprop.h" -#include "ui.h" -#include "metacity-Xatomtype.h" -#include <X11/Xatom.h> -#include <string.h> -#include "window-private.h" - -typedef struct -{ - MetaDisplay *display; - Window xwindow; - Atom xatom; - Atom type; - int format; - unsigned long n_items; - unsigned long bytes_after; - unsigned char *prop; -} GetPropertyResults; - -static gboolean -validate_or_free_results (GetPropertyResults *results, - int expected_format, - Atom expected_type, - gboolean must_have_items) -{ - char *type_name; - char *expected_name; - char *prop_name; - const char *title; - const char *res_class; - const char *res_name; - MetaWindow *w; - - if (expected_format == results->format && - expected_type == results->type && - (!must_have_items || results->n_items > 0)) - return TRUE; - - meta_error_trap_push (results->display); - type_name = XGetAtomName (results->display->xdisplay, results->type); - expected_name = XGetAtomName (results->display->xdisplay, expected_type); - prop_name = XGetAtomName (results->display->xdisplay, results->xatom); - meta_error_trap_pop (results->display, TRUE); - - w = meta_display_lookup_x_window (results->display, results->xwindow); - - if (w != NULL) - { - title = w->title; - res_class = w->res_class; - res_name = w->res_name; - } - else - { - title = NULL; - res_class = NULL; - res_name = NULL; - } - - if (title == NULL) - title = "unknown"; - - if (res_class == NULL) - res_class = "unknown"; - - if (res_name == NULL) - res_name = "unknown"; - - meta_warning (_("Window 0x%lx has property %s\nthat was expected to have type %s format %d\nand actually has type %s format %d n_items %d.\nThis is most likely an application bug, not a window manager bug.\nThe window has title=\"%s\" class=\"%s\" name=\"%s\"\n"), - results->xwindow, - prop_name ? prop_name : "(bad atom)", - expected_name ? expected_name : "(bad atom)", - expected_format, - type_name ? type_name : "(bad atom)", - results->format, (int) results->n_items, - title, res_class, res_name); - - if (type_name) - XFree (type_name); - if (expected_name) - XFree (expected_name); - if (prop_name) - XFree (prop_name); - - if (results->prop) - { - XFree (results->prop); - results->prop = NULL; - } - - return FALSE; -} - -static gboolean -get_property (MetaDisplay *display, - Window xwindow, - Atom xatom, - Atom req_type, - GetPropertyResults *results) -{ - results->display = display; - results->xwindow = xwindow; - results->xatom = xatom; - results->prop = NULL; - results->n_items = 0; - results->type = None; - results->bytes_after = 0; - results->format = 0; - - meta_error_trap_push_with_return (display); - if (XGetWindowProperty (display->xdisplay, xwindow, xatom, - 0, G_MAXLONG, - False, req_type, &results->type, &results->format, - &results->n_items, - &results->bytes_after, - &results->prop) != Success || - results->type == None) - { - if (results->prop) - XFree (results->prop); - meta_error_trap_pop_with_return (display, TRUE); - return FALSE; - } - - if (meta_error_trap_pop_with_return (display, TRUE) != Success) - { - if (results->prop) - XFree (results->prop); - return FALSE; - } - - return TRUE; -} - -static gboolean -atom_list_from_results (GetPropertyResults *results, - Atom **atoms_p, - int *n_atoms_p) -{ - if (!validate_or_free_results (results, 32, XA_ATOM, FALSE)) - return FALSE; - - *atoms_p = (Atom*) results->prop; - *n_atoms_p = results->n_items; - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_atom_list (MetaDisplay *display, - Window xwindow, - Atom xatom, - Atom **atoms_p, - int *n_atoms_p) -{ - GetPropertyResults results; - - *atoms_p = NULL; - *n_atoms_p = 0; - - if (!get_property (display, xwindow, xatom, XA_ATOM, - &results)) - return FALSE; - - return atom_list_from_results (&results, atoms_p, n_atoms_p); -} - -static gboolean -cardinal_list_from_results (GetPropertyResults *results, - gulong **cardinals_p, - int *n_cardinals_p) -{ - if (!validate_or_free_results (results, 32, XA_CARDINAL, FALSE)) - return FALSE; - - *cardinals_p = (gulong*) results->prop; - *n_cardinals_p = results->n_items; - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_cardinal_list (MetaDisplay *display, - Window xwindow, - Atom xatom, - gulong **cardinals_p, - int *n_cardinals_p) -{ - GetPropertyResults results; - - *cardinals_p = NULL; - *n_cardinals_p = 0; - - if (!get_property (display, xwindow, xatom, XA_CARDINAL, - &results)) - return FALSE; - - return cardinal_list_from_results (&results, cardinals_p, n_cardinals_p); -} - -static gboolean -motif_hints_from_results (GetPropertyResults *results, - MotifWmHints **hints_p) -{ - int real_size, max_size; -#define MAX_ITEMS sizeof (MotifWmHints)/sizeof (gulong) - - *hints_p = NULL; - - if (results->type == None || results->n_items <= 0) - { - meta_verbose ("Motif hints had unexpected type or n_items\n"); - if (results->prop) - { - XFree (results->prop); - results->prop = NULL; - } - return FALSE; - } - - /* The issue here is that some old crufty code will set a smaller - * MotifWmHints than the one we expect, apparently. I'm not sure of - * the history behind it. See bug #89841 for example. - */ - *hints_p = ag_Xmalloc (sizeof (MotifWmHints)); - if (*hints_p == NULL) - { - if (results->prop) - { - XFree (results->prop); - results->prop = NULL; - } - return FALSE; - } - real_size = results->n_items * sizeof (gulong); - max_size = MAX_ITEMS * sizeof (gulong); - memcpy (*hints_p, results->prop, MIN (real_size, max_size)); - - if (results->prop) - { - XFree (results->prop); - results->prop = NULL; - } - - return TRUE; -} - -gboolean -meta_prop_get_motif_hints (MetaDisplay *display, - Window xwindow, - Atom xatom, - MotifWmHints **hints_p) -{ - GetPropertyResults results; - - *hints_p = NULL; - - if (!get_property (display, xwindow, xatom, AnyPropertyType, - &results)) - return FALSE; - - return motif_hints_from_results (&results, hints_p); -} - -static gboolean -latin1_string_from_results (GetPropertyResults *results, - char **str_p) -{ - *str_p = NULL; - - if (!validate_or_free_results (results, 8, XA_STRING, FALSE)) - return FALSE; - - *str_p = (char*) results->prop; - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_latin1_string (MetaDisplay *display, - Window xwindow, - Atom xatom, - char **str_p) -{ - GetPropertyResults results; - - *str_p = NULL; - - if (!get_property (display, xwindow, xatom, XA_STRING, - &results)) - return FALSE; - - return latin1_string_from_results (&results, str_p); -} - -static gboolean -utf8_string_from_results (GetPropertyResults *results, - char **str_p) -{ - *str_p = NULL; - - if (!validate_or_free_results (results, 8, - results->display->atom_UTF8_STRING, FALSE)) - return FALSE; - - if (results->n_items > 0 && - !g_utf8_validate ((gchar *)results->prop, results->n_items, NULL)) - { - char *name; - - name = XGetAtomName (results->display->xdisplay, results->xatom); - meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8\n"), - name, results->xwindow); - meta_XFree (name); - XFree (results->prop); - results->prop = NULL; - - return FALSE; - } - - *str_p = (char*) results->prop; - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_utf8_string (MetaDisplay *display, - Window xwindow, - Atom xatom, - char **str_p) -{ - GetPropertyResults results; - - *str_p = NULL; - - if (!get_property (display, xwindow, xatom, - display->atom_UTF8_STRING, - &results)) - return FALSE; - - return utf8_string_from_results (&results, str_p); -} - -/* this one freakishly returns g_malloc memory */ -static gboolean -utf8_list_from_results (GetPropertyResults *results, - char ***str_p, - int *n_str_p) -{ - int i; - int n_strings; - char **retval; - const char *p; - - *str_p = NULL; - *n_str_p = 0; - - if (!validate_or_free_results (results, 8, - results->display->atom_UTF8_STRING, FALSE)) - return FALSE; - - /* I'm not sure this is right, but I'm guessing the - * property is nul-separated - */ - i = 0; - n_strings = 0; - while (i < (int) results->n_items) - { - if (results->prop[i] == '\0') - ++n_strings; - ++i; - } - - if (results->prop[results->n_items - 1] != '\0') - ++n_strings; - - /* we're guaranteed that results->prop has a nul on the end - * by XGetWindowProperty - */ - - retval = g_new0 (char*, n_strings + 1); - - p = (char *)results->prop; - i = 0; - while (i < n_strings) - { - if (!g_utf8_validate (p, -1, NULL)) - { - char *name; - - meta_error_trap_push (results->display); - name = XGetAtomName (results->display->xdisplay, results->xatom); - meta_error_trap_pop (results->display, TRUE); - meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"), - name, results->xwindow, i); - meta_XFree (name); - meta_XFree (results->prop); - results->prop = NULL; - - g_strfreev (retval); - return FALSE; - } - - retval[i] = g_strdup (p); - - p = p + strlen (p) + 1; - ++i; - } - - *str_p = retval; - *n_str_p = i; - - meta_XFree (results->prop); - results->prop = NULL; - - return TRUE; -} - -/* returns g_malloc not Xmalloc memory */ -gboolean -meta_prop_get_utf8_list (MetaDisplay *display, - Window xwindow, - Atom xatom, - char ***str_p, - int *n_str_p) -{ - GetPropertyResults results; - - *str_p = NULL; - - if (!get_property (display, xwindow, xatom, - display->atom_UTF8_STRING, - &results)) - return FALSE; - - return utf8_list_from_results (&results, str_p, n_str_p); -} - -void -meta_prop_set_utf8_string_hint (MetaDisplay *display, - Window xwindow, - Atom atom, - const char *val) -{ - meta_error_trap_push (display); - XChangeProperty (display->xdisplay, - xwindow, atom, - display->atom_UTF8_STRING, - 8, PropModeReplace, (guchar*) val, strlen (val)); - meta_error_trap_pop (display, FALSE); -} - -static gboolean -window_from_results (GetPropertyResults *results, - Window *window_p) -{ - if (!validate_or_free_results (results, 32, XA_WINDOW, TRUE)) - return FALSE; - - *window_p = *(Window*) results->prop; - XFree (results->prop); - results->prop = NULL; - - return TRUE; -} - -#ifdef HAVE_XSYNC -static gboolean -counter_from_results (GetPropertyResults *results, - XSyncCounter *counter_p) -{ - if (!validate_or_free_results (results, 32, - XA_CARDINAL, - TRUE)) - return FALSE; - - *counter_p = *(XSyncCounter*) results->prop; - XFree (results->prop); - results->prop = NULL; - - return TRUE; -} -#endif - -gboolean -meta_prop_get_window (MetaDisplay *display, - Window xwindow, - Atom xatom, - Window *window_p) -{ - GetPropertyResults results; - - *window_p = None; - - if (!get_property (display, xwindow, xatom, XA_WINDOW, - &results)) - return FALSE; - - return window_from_results (&results, window_p); -} - -gboolean -meta_prop_get_cardinal (MetaDisplay *display, - Window xwindow, - Atom xatom, - gulong *cardinal_p) -{ - return meta_prop_get_cardinal_with_atom_type (display, xwindow, xatom, - XA_CARDINAL, cardinal_p); -} - -static gboolean -cardinal_with_atom_type_from_results (GetPropertyResults *results, - Atom prop_type, - gulong *cardinal_p) -{ - if (!validate_or_free_results (results, 32, prop_type, TRUE)) - return FALSE; - - *cardinal_p = *(gulong*) results->prop; - XFree (results->prop); - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_cardinal_with_atom_type (MetaDisplay *display, - Window xwindow, - Atom xatom, - Atom prop_type, - gulong *cardinal_p) -{ - GetPropertyResults results; - - *cardinal_p = 0; - - if (!get_property (display, xwindow, xatom, prop_type, - &results)) - return FALSE; - - return cardinal_with_atom_type_from_results (&results, prop_type, cardinal_p); -} - -static gboolean -text_property_from_results (GetPropertyResults *results, - char **utf8_str_p) -{ - XTextProperty tp; - - *utf8_str_p = NULL; - - tp.value = results->prop; - results->prop = NULL; - tp.encoding = results->type; - tp.format = results->format; - tp.nitems = results->n_items; - - *utf8_str_p = meta_text_property_to_utf8 (results->display->xdisplay, - &tp); - - if (tp.value != NULL) - XFree (tp.value); - - return *utf8_str_p != NULL; -} - -gboolean -meta_prop_get_text_property (MetaDisplay *display, - Window xwindow, - Atom xatom, - char **utf8_str_p) -{ - GetPropertyResults results; - - if (!get_property (display, xwindow, xatom, AnyPropertyType, - &results)) - return FALSE; - - return text_property_from_results (&results, utf8_str_p); -} - -/* From Xmd.h */ -#ifndef cvtINT32toInt -#if SIZEOF_VOID_P == 8 -#define cvtINT8toInt(val) ((((unsigned int)val) & 0x00000080) ? (((unsigned int)val) | 0xffffffffffffff00) : ((unsigned int)val)) -#define cvtINT16toInt(val) ((((unsigned int)val) & 0x00008000) ? (((unsigned int)val) | 0xffffffffffff0000) : ((unsigned int)val)) -#define cvtINT32toInt(val) ((((unsigned int)val) & 0x80000000) ? (((unsigned int)val) | 0xffffffff00000000) : ((unsigned int)val)) -#define cvtINT8toShort(val) cvtINT8toInt(val) -#define cvtINT16toShort(val) cvtINT16toInt(val) -#define cvtINT32toShort(val) cvtINT32toInt(val) -#define cvtINT8toLong(val) cvtINT8toInt(val) -#define cvtINT16toLong(val) cvtINT16toInt(val) -#define cvtINT32toLong(val) cvtINT32toInt(val) -#else -#define cvtINT8toInt(val) (val) -#define cvtINT16toInt(val) (val) -#define cvtINT32toInt(val) (val) -#define cvtINT8toShort(val) (val) -#define cvtINT16toShort(val) (val) -#define cvtINT32toShort(val) (val) -#define cvtINT8toLong(val) (val) -#define cvtINT16toLong(val) (val) -#define cvtINT32toLong(val) (val) -#endif /* SIZEOF_VOID_P == 8 */ -#endif /* cvtINT32toInt() */ - -static gboolean -wm_hints_from_results (GetPropertyResults *results, - XWMHints **hints_p) -{ - XWMHints *hints; - xPropWMHints *raw; - - *hints_p = NULL; - - if (!validate_or_free_results (results, 32, XA_WM_HINTS, TRUE)) - return FALSE; - - /* pre-R3 bogusly truncated window_group, don't fail on them */ - if (results->n_items < (NumPropWMHintsElements - 1)) - { - meta_verbose ("WM_HINTS property too short: %d should be %d\n", - (int) results->n_items, NumPropWMHintsElements - 1); - if (results->prop) - { - XFree (results->prop); - results->prop = NULL; - } - return FALSE; - } - - hints = ag_Xmalloc0 (sizeof (XWMHints)); - - raw = (xPropWMHints*) results->prop; - - hints->flags = raw->flags; - hints->input = (raw->input ? True : False); - hints->initial_state = cvtINT32toInt (raw->initialState); - hints->icon_pixmap = raw->iconPixmap; - hints->icon_window = raw->iconWindow; - hints->icon_x = cvtINT32toInt (raw->iconX); - hints->icon_y = cvtINT32toInt (raw->iconY); - hints->icon_mask = raw->iconMask; - if (results->n_items >= NumPropWMHintsElements) - hints->window_group = raw->windowGroup; - else - hints->window_group = 0; - - if (results->prop) - { - XFree (results->prop); - results->prop = NULL; - } - - *hints_p = hints; - - return TRUE; -} - -gboolean -meta_prop_get_wm_hints (MetaDisplay *display, - Window xwindow, - Atom xatom, - XWMHints **hints_p) -{ - GetPropertyResults results; - - *hints_p = NULL; - - if (!get_property (display, xwindow, xatom, XA_WM_HINTS, - &results)) - return FALSE; - - return wm_hints_from_results (&results, hints_p); -} - -static gboolean -class_hint_from_results (GetPropertyResults *results, - XClassHint *class_hint) -{ - int len_name, len_class; - - class_hint->res_class = NULL; - class_hint->res_name = NULL; - - if (!validate_or_free_results (results, 8, XA_STRING, FALSE)) - return FALSE; - - len_name = strlen ((char *) results->prop); - if (! (class_hint->res_name = ag_Xmalloc (len_name+1))) - { - XFree (results->prop); - results->prop = NULL; - return FALSE; - } - - strcpy (class_hint->res_name, (char *)results->prop); - - if (len_name == (int) results->n_items) - len_name--; - - len_class = strlen ((char *)results->prop + len_name + 1); - - if (! (class_hint->res_class = ag_Xmalloc(len_class+1))) - { - XFree(class_hint->res_name); - class_hint->res_name = NULL; - XFree (results->prop); - results->prop = NULL; - return FALSE; - } - - strcpy (class_hint->res_class, (char *)results->prop + len_name + 1); - - XFree (results->prop); - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_class_hint (MetaDisplay *display, - Window xwindow, - Atom xatom, - XClassHint *class_hint) -{ - GetPropertyResults results; - - class_hint->res_class = NULL; - class_hint->res_name = NULL; - - if (!get_property (display, xwindow, xatom, XA_STRING, - &results)) - return FALSE; - - return class_hint_from_results (&results, class_hint); -} - -static gboolean -size_hints_from_results (GetPropertyResults *results, - XSizeHints **hints_p, - gulong *flags_p) -{ - xPropSizeHints *raw; - XSizeHints *hints; - - *hints_p = NULL; - *flags_p = 0; - - if (!validate_or_free_results (results, 32, XA_WM_SIZE_HINTS, FALSE)) - return FALSE; - - if (results->n_items < OldNumPropSizeElements) - return FALSE; - - raw = (xPropSizeHints*) results->prop; - - hints = ag_Xmalloc (sizeof (XSizeHints)); - - /* XSizeHints misdeclares these as int instead of long */ - hints->flags = raw->flags; - hints->x = cvtINT32toInt (raw->x); - hints->y = cvtINT32toInt (raw->y); - hints->width = cvtINT32toInt (raw->width); - hints->height = cvtINT32toInt (raw->height); - hints->min_width = cvtINT32toInt (raw->minWidth); - hints->min_height = cvtINT32toInt (raw->minHeight); - hints->max_width = cvtINT32toInt (raw->maxWidth); - hints->max_height = cvtINT32toInt (raw->maxHeight); - hints->width_inc = cvtINT32toInt (raw->widthInc); - hints->height_inc = cvtINT32toInt (raw->heightInc); - hints->min_aspect.x = cvtINT32toInt (raw->minAspectX); - hints->min_aspect.y = cvtINT32toInt (raw->minAspectY); - hints->max_aspect.x = cvtINT32toInt (raw->maxAspectX); - hints->max_aspect.y = cvtINT32toInt (raw->maxAspectY); - - *flags_p = (USPosition | USSize | PAllHints); - if (results->n_items >= NumPropSizeElements) - { - hints->base_width= cvtINT32toInt (raw->baseWidth); - hints->base_height= cvtINT32toInt (raw->baseHeight); - hints->win_gravity= cvtINT32toInt (raw->winGravity); - *flags_p |= (PBaseSize | PWinGravity); - } - - hints->flags &= (*flags_p); /* get rid of unwanted bits */ - - XFree (results->prop); - results->prop = NULL; - - *hints_p = hints; - - return TRUE; -} - -gboolean -meta_prop_get_size_hints (MetaDisplay *display, - Window xwindow, - Atom xatom, - XSizeHints **hints_p, - gulong *flags_p) -{ - GetPropertyResults results; - - *hints_p = NULL; - *flags_p = 0; - - if (!get_property (display, xwindow, xatom, XA_WM_SIZE_HINTS, - &results)) - return FALSE; - - return size_hints_from_results (&results, hints_p, flags_p); -} - -static AgGetPropertyTask* -get_task (MetaDisplay *display, - Window xwindow, - Atom xatom, - Atom req_type) -{ - return ag_task_create (display->xdisplay, - xwindow, - xatom, 0, G_MAXLONG, - False, req_type); -} - -static char* -latin1_to_utf8 (const char *text) -{ - GString *str; - const char *p; - - str = g_string_new (""); - - p = text; - while (*p) - { - g_string_append_unichar (str, *p); - ++p; - } - - return g_string_free (str, FALSE); -} - -void -meta_prop_get_values (MetaDisplay *display, - Window xwindow, - MetaPropValue *values, - int n_values) -{ - int i; - AgGetPropertyTask **tasks; - - meta_verbose ("Requesting %d properties of 0x%lx at once\n", - n_values, xwindow); - - if (n_values == 0) - return; - - tasks = g_new0 (AgGetPropertyTask*, n_values); - - /* Start up tasks. The "values" array can have values - * with atom == None, which means to ignore that element. - */ - i = 0; - while (i < n_values) - { - if (values[i].required_type == None) - { - switch (values[i].type) - { - case META_PROP_VALUE_INVALID: - /* This means we don't really want a value, e.g. got - * property notify on an atom we don't care about. - */ - if (values[i].atom != None) - meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", G_STRFUNC); - break; - case META_PROP_VALUE_UTF8_LIST: - case META_PROP_VALUE_UTF8: - values[i].required_type = display->atom_UTF8_STRING; - break; - case META_PROP_VALUE_STRING: - case META_PROP_VALUE_STRING_AS_UTF8: - values[i].required_type = XA_STRING; - break; - case META_PROP_VALUE_MOTIF_HINTS: - values[i].required_type = AnyPropertyType; - break; - case META_PROP_VALUE_CARDINAL_LIST: - case META_PROP_VALUE_CARDINAL: - values[i].required_type = XA_CARDINAL; - break; - case META_PROP_VALUE_WINDOW: - values[i].required_type = XA_WINDOW; - break; - case META_PROP_VALUE_ATOM_LIST: - values[i].required_type = XA_ATOM; - break; - case META_PROP_VALUE_TEXT_PROPERTY: - values[i].required_type = AnyPropertyType; - break; - case META_PROP_VALUE_WM_HINTS: - values[i].required_type = XA_WM_HINTS; - break; - case META_PROP_VALUE_CLASS_HINT: - values[i].required_type = XA_STRING; - break; - case META_PROP_VALUE_SIZE_HINTS: - values[i].required_type = XA_WM_SIZE_HINTS; - break; - case META_PROP_VALUE_SYNC_COUNTER: - values[i].required_type = XA_CARDINAL; - break; - } - } - - if (values[i].atom != None) - tasks[i] = get_task (display, xwindow, - values[i].atom, values[i].required_type); - - ++i; - } - - /* Get replies for all our tasks */ - meta_topic (META_DEBUG_SYNC, "Syncing to get %d GetProperty replies in %s\n", - n_values, G_STRFUNC); - XSync (display->xdisplay, False); - - /* Collect results, should arrive in order requested */ - i = 0; - while (i < n_values) - { - AgGetPropertyTask *task; - GetPropertyResults results; - - if (tasks[i] == NULL) - { - /* Probably values[i].type was None, or ag_task_create() - * returned NULL. - */ - values[i].type = META_PROP_VALUE_INVALID; - goto next; - } - - task = ag_get_next_completed_task (display->xdisplay); - g_assert (task != NULL); - g_assert (ag_task_have_reply (task)); - - results.display = display; - results.xwindow = xwindow; - results.xatom = values[i].atom; - results.prop = NULL; - results.n_items = 0; - results.type = None; - results.bytes_after = 0; - results.format = 0; - - if (ag_task_get_reply_and_free (task, - &results.type, &results.format, - &results.n_items, - &results.bytes_after, - &results.prop) != Success || - results.type == None) - { - values[i].type = META_PROP_VALUE_INVALID; - if (results.prop) - { - XFree (results.prop); - results.prop = NULL; - } - goto next; - } - - switch (values[i].type) - { - case META_PROP_VALUE_INVALID: - g_assert_not_reached (); - break; - case META_PROP_VALUE_UTF8_LIST: - if (!utf8_list_from_results (&results, - &values[i].v.string_list.strings, - &values[i].v.string_list.n_strings)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_UTF8: - if (!utf8_string_from_results (&results, - &values[i].v.str)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_STRING: - if (!latin1_string_from_results (&results, - &values[i].v.str)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_STRING_AS_UTF8: - if (!latin1_string_from_results (&results, - &values[i].v.str)) - values[i].type = META_PROP_VALUE_INVALID; - else - { - char *new_str; - char *xmalloc_new_str; - - new_str = latin1_to_utf8 (values[i].v.str); - xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1); - if (xmalloc_new_str != NULL) - { - strcpy (xmalloc_new_str, new_str); - meta_XFree (values[i].v.str); - values[i].v.str = xmalloc_new_str; - } - - g_free (new_str); - } - break; - case META_PROP_VALUE_MOTIF_HINTS: - if (!motif_hints_from_results (&results, - &values[i].v.motif_hints)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_CARDINAL_LIST: - if (!cardinal_list_from_results (&results, - &values[i].v.cardinal_list.cardinals, - &values[i].v.cardinal_list.n_cardinals)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_CARDINAL: - if (!cardinal_with_atom_type_from_results (&results, - values[i].required_type, - &values[i].v.cardinal)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_WINDOW: - if (!window_from_results (&results, - &values[i].v.xwindow)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_ATOM_LIST: - if (!atom_list_from_results (&results, - &values[i].v.atom_list.atoms, - &values[i].v.atom_list.n_atoms)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_TEXT_PROPERTY: - if (!text_property_from_results (&results, &values[i].v.str)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_WM_HINTS: - if (!wm_hints_from_results (&results, &values[i].v.wm_hints)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_CLASS_HINT: - if (!class_hint_from_results (&results, &values[i].v.class_hint)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_SIZE_HINTS: - if (!size_hints_from_results (&results, - &values[i].v.size_hints.hints, - &values[i].v.size_hints.flags)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_SYNC_COUNTER: -#ifdef HAVE_XSYNC - if (!counter_from_results (&results, - &values[i].v.xcounter)) - values[i].type = META_PROP_VALUE_INVALID; -#else - values[i].type = META_PROP_VALUE_INVALID; - if (results.prop) - { - XFree (results.prop); - results.prop = NULL; - } -#endif - break; - } - - next: - ++i; - } - - g_free (tasks); -} - -static void -free_value (MetaPropValue *value) -{ - switch (value->type) - { - case META_PROP_VALUE_INVALID: - break; - case META_PROP_VALUE_UTF8: - case META_PROP_VALUE_STRING: - case META_PROP_VALUE_STRING_AS_UTF8: - meta_XFree (value->v.str); - break; - case META_PROP_VALUE_MOTIF_HINTS: - meta_XFree (value->v.motif_hints); - break; - case META_PROP_VALUE_CARDINAL: - break; - case META_PROP_VALUE_WINDOW: - break; - case META_PROP_VALUE_ATOM_LIST: - meta_XFree (value->v.atom_list.atoms); - break; - case META_PROP_VALUE_TEXT_PROPERTY: - meta_XFree (value->v.str); - break; - case META_PROP_VALUE_WM_HINTS: - meta_XFree (value->v.wm_hints); - break; - case META_PROP_VALUE_CLASS_HINT: - meta_XFree (value->v.class_hint.res_class); - meta_XFree (value->v.class_hint.res_name); - break; - case META_PROP_VALUE_SIZE_HINTS: - meta_XFree (value->v.size_hints.hints); - break; - case META_PROP_VALUE_UTF8_LIST: - g_strfreev (value->v.string_list.strings); - break; - case META_PROP_VALUE_CARDINAL_LIST: - meta_XFree (value->v.cardinal_list.cardinals); - break; - case META_PROP_VALUE_SYNC_COUNTER: - break; - } -} - -void -meta_prop_free_values (MetaPropValue *values, - int n_values) -{ - int i; - - i = 0; - while (i < n_values) - { - free_value (&values[i]); - ++i; - } - - /* Zero the whole thing to quickly detect breakage */ - memset (values, '\0', sizeof (MetaPropValue) * n_values); -} diff --git a/src/default_icon.png b/src/default_icon.png Binary files differdeleted file mode 100644 index 5aad8798..00000000 --- a/src/default_icon.png +++ /dev/null diff --git a/src/include/all-keybindings.h b/src/include/all-keybindings.h deleted file mode 100644 index aa509576..00000000 --- a/src/include/all-keybindings.h +++ /dev/null @@ -1,386 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Thomas Thurman - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** - * A list of screen keybinding information. - * - * Each action which can have a keystroke bound to it is listed below. - * To use this file, define keybind() to be a seven-argument macro (you can - * throw any of the arguments you please away), include this file, - * and then undefine the macro again. - * - * (If you aren't familiar with this technique, sometimes called "x-macros", - * see DDJ of May 2001: <http://www.ddj.com/cpp/184401387>.) - * - * This makes it possible to keep all information about all the keybindings - * in the same place. The only exception is the code to run when an action - * is actually invoked; while we *could* have put that in this file, it would - * have made debugging ridiculously difficult. Instead, each action should - * have a corresponding static function named handle_<name>() in - * keybindings.c. - * - * The arguments to keybind() are: - * 1) the name of the binding; a bareword identifier - * (it's fine if it happens to clash with a C reserved word) - * 2) the name of the function which implements it. - * Clearly we could have guessed this from the binding very often, - * but we choose to write it in full for the benefit of grep. - * 3) an integer parameter to pass to the handler - * 4) a set of boolean flags, ORed together: - * BINDING_PER_WINDOW - this is a window-based binding. - * It is only valid if there is a - * current window, and will operate in - * some way on that window. - * BINDING_REVERSES - the binding can reverse if you hold down Shift - * BINDING_IS_REVERSED - the same, but the senses are reversed from the - * handler's point of view (let me know if I should - * explain this better) - * or 0 if no flag applies. - * - * 5) a string representing the default binding. - * If this is NULL, the action is unbound by default. - * Please use NULL and not "disabled". - * 6) a short description. - * It must be marked translatable (i.e. inside "_(...)"). - * - * Don't try to do XML entity escaping anywhere in the strings. - */ - -#ifndef keybind -#error "keybind () must be defined when you include screen-bindings.h" -#endif - -/***********************************/ - -#ifndef _BINDINGS_DEFINED_CONSTANTS -#define _BINDINGS_DEFINED_CONSTANTS 1 - -#define BINDING_PER_WINDOW 0x01 -#define BINDING_REVERSES 0x02 -#define BINDING_IS_REVERSED 0x04 - -#endif /* _BINDINGS_DEFINED_CONSTANTS */ - -/***********************************/ - -/* convenience, since in this file they must always be set together */ -#define REVERSES_AND_REVERSED (BINDING_REVERSES | BINDING_IS_REVERSED) - -keybind (switch_to_workspace_1, handle_switch_to_workspace, 0, 0, NULL, - _("Switch to workspace 1")) -keybind (switch_to_workspace_2, handle_switch_to_workspace, 1, 0, NULL, - _("Switch to workspace 2")) -keybind (switch_to_workspace_3, handle_switch_to_workspace, 2, 0, NULL, - _("Switch to workspace 3")) -keybind (switch_to_workspace_4, handle_switch_to_workspace, 3, 0, NULL, - _("Switch to workspace 4")) -keybind (switch_to_workspace_5, handle_switch_to_workspace, 4, 0, NULL, - _("Switch to workspace 5")) -keybind (switch_to_workspace_6, handle_switch_to_workspace, 5, 0, NULL, - _("Switch to workspace 6")) -keybind (switch_to_workspace_7, handle_switch_to_workspace, 6, 0, NULL, - _("Switch to workspace 7")) -keybind (switch_to_workspace_8, handle_switch_to_workspace, 7, 0, NULL, - _("Switch to workspace 8")) -keybind (switch_to_workspace_9, handle_switch_to_workspace, 8, 0, NULL, - _("Switch to workspace 9")) -keybind (switch_to_workspace_10, handle_switch_to_workspace, 9, 0, NULL, - _("Switch to workspace 10")) -keybind (switch_to_workspace_11, handle_switch_to_workspace, 10, 0, NULL, - _("Switch to workspace 11")) -keybind (switch_to_workspace_12, handle_switch_to_workspace, 11, 0, NULL, - _("Switch to workspace 12")) - -/* META_MOTION_* are negative, and so distinct from workspace numbers, - * which are always zero or positive. - * If you make use of these constants, you will need to include workspace.h - * (which you're probably using already for other reasons anyway). - * If your definition of keybind() throws them away, you don't need to include - * workspace.h, of course. - */ - -keybind (switch_to_workspace_left, handle_switch_to_workspace, - META_MOTION_LEFT, 0, "<Control><Alt>Left", - _("Switch to workspace on the left of the current workspace")) - -keybind (switch_to_workspace_right, handle_switch_to_workspace, - META_MOTION_RIGHT, 0, "<Control><Alt>Right", - _("Switch to workspace on the right of the current workspace")) - -keybind (switch_to_workspace_up, handle_switch_to_workspace, - META_MOTION_UP, 0, "<Control><Alt>Up", - _("Switch to workspace above the current workspace")) - -keybind (switch_to_workspace_down, handle_switch_to_workspace, - META_MOTION_DOWN, 0, "<Control><Alt>Down", - _("Switch to workspace below the current workspace")) - -/***********************************/ - -/* The ones which have inverses. These can't be bound to any keystroke - * containing Shift because Shift will invert their "backward" state. - * - * TODO: "NORMAL" and "DOCKS" should be renamed to the same name as their - * action, for obviousness. - * - * TODO: handle_switch and handle_cycle should probably really be the - * same function checking a bit in the parameter for difference. - */ - -keybind (switch_group, handle_switch, META_TAB_LIST_GROUP, - BINDING_REVERSES, NULL, - _("Move between windows of an application, using a popup window")) -keybind (switch_group_backward, handle_switch, META_TAB_LIST_GROUP, - REVERSES_AND_REVERSED, NULL, - _("Move backward between windows of an application, " - "using a popup window")) -keybind (switch_windows, handle_switch, META_TAB_LIST_NORMAL, - BINDING_REVERSES, "<Alt>Tab", - _("Move between windows, using a popup window")) -keybind (switch_windows_backward, handle_switch, META_TAB_LIST_NORMAL, - REVERSES_AND_REVERSED, NULL, - _("Move backward between windows, using a popup window")) -keybind (switch_panels, handle_switch, META_TAB_LIST_DOCKS, - BINDING_REVERSES, "<Control><Alt>Tab", - _("Move between panels and the desktop, using a popup window")) -keybind (switch_panels_backward, handle_switch, META_TAB_LIST_DOCKS, - REVERSES_AND_REVERSED, NULL, - _("Move backward between panels and the desktop, " - "using a popup window")) - -keybind (cycle_group, handle_cycle, META_TAB_LIST_GROUP, - BINDING_REVERSES, "<Alt>F6", - _("Move between windows of an application immediately")) -keybind (cycle_group_backward, handle_cycle, META_TAB_LIST_GROUP, - REVERSES_AND_REVERSED, NULL, - _("Move backward between windows of an application immediately")) -keybind (cycle_windows, handle_cycle, META_TAB_LIST_NORMAL, - BINDING_REVERSES, "<Alt>Escape", - _("Move between windows immediately")) -keybind (cycle_windows_backward, handle_cycle, META_TAB_LIST_NORMAL, - REVERSES_AND_REVERSED, NULL, - _("Move backward between windows immediately")) -keybind (cycle_panels, handle_cycle, META_TAB_LIST_DOCKS, - BINDING_REVERSES, "<Control><Alt>Escape", - _("Move between panels and the desktop immediately")) -keybind (cycle_panels_backward, handle_cycle, META_TAB_LIST_DOCKS, - REVERSES_AND_REVERSED, NULL, - _("Move backward between panels and the desktop immediately")) - -/***********************************/ - -keybind (show_desktop, handle_show_desktop, 0, 0, "<Control><Alt>d", - _("Hide all normal windows and set focus to the desktop background")) -keybind (panel_main_menu, handle_panel, - META_KEYBINDING_ACTION_PANEL_MAIN_MENU, 0, "<Alt>F1", - _("Show the panel's main menu")) -keybind (panel_run_dialog, handle_panel, - META_KEYBINDING_ACTION_PANEL_RUN_DIALOG, 0, "<Alt>F2", - _("Show the panel's \"Run Application\" dialog box")) - -/* Yes, the param is offset by one. Historical reasons. (Maybe worth fixing - * at some point.) The description is NULL here because the stanza is - * irregularly shaped in metacity.schemas.in. This will probably be fixed - * as well. - */ -keybind (run_command_1, handle_run_command, 0, 0, NULL, NULL) -keybind (run_command_2, handle_run_command, 1, 0, NULL, NULL) -keybind (run_command_3, handle_run_command, 2, 0, NULL, NULL) -keybind (run_command_4, handle_run_command, 3, 0, NULL, NULL) -keybind (run_command_5, handle_run_command, 4, 0, NULL, NULL) -keybind (run_command_6, handle_run_command, 5, 0, NULL, NULL) -keybind (run_command_7, handle_run_command, 6, 0, NULL, NULL) -keybind (run_command_8, handle_run_command, 7, 0, NULL, NULL) -keybind (run_command_9, handle_run_command, 8, 0, NULL, NULL) -keybind (run_command_10, handle_run_command, 9, 0, NULL, NULL) -keybind (run_command_11, handle_run_command, 10, 0, NULL, NULL) -keybind (run_command_12, handle_run_command, 11, 0, NULL, NULL) -keybind (run_command_13, handle_run_command, 12, 0, NULL, NULL) -keybind (run_command_14, handle_run_command, 13, 0, NULL, NULL) -keybind (run_command_15, handle_run_command, 14, 0, NULL, NULL) -keybind (run_command_16, handle_run_command, 15, 0, NULL, NULL) -keybind (run_command_17, handle_run_command, 16, 0, NULL, NULL) -keybind (run_command_18, handle_run_command, 17, 0, NULL, NULL) -keybind (run_command_19, handle_run_command, 18, 0, NULL, NULL) -keybind (run_command_20, handle_run_command, 19, 0, NULL, NULL) -keybind (run_command_21, handle_run_command, 20, 0, NULL, NULL) -keybind (run_command_22, handle_run_command, 21, 0, NULL, NULL) -keybind (run_command_23, handle_run_command, 22, 0, NULL, NULL) -keybind (run_command_24, handle_run_command, 23, 0, NULL, NULL) -keybind (run_command_25, handle_run_command, 24, 0, NULL, NULL) -keybind (run_command_26, handle_run_command, 25, 0, NULL, NULL) -keybind (run_command_27, handle_run_command, 26, 0, NULL, NULL) -keybind (run_command_28, handle_run_command, 27, 0, NULL, NULL) -keybind (run_command_29, handle_run_command, 28, 0, NULL, NULL) -keybind (run_command_30, handle_run_command, 29, 0, NULL, NULL) -keybind (run_command_31, handle_run_command, 30, 0, NULL, NULL) -keybind (run_command_32, handle_run_command, 31, 0, NULL, NULL) - -keybind (run_command_screenshot, handle_run_command, 32, 0, "Print", - _("Take a screenshot")) -keybind (run_command_window_screenshot, handle_run_command, 33, 0,"<Alt>Print", - _("Take a screenshot of a window")) - -keybind (run_command_terminal, handle_run_terminal, 0, 0, NULL, _("Run a terminal")) - -/* No description because this is undocumented */ -keybind (set_spew_mark, handle_set_spew_mark, 0, 0, NULL, NULL) - -#undef REVERSES_AND_REVERSED - -/************************ PER WINDOW BINDINGS ************************/ - -/* These take a window as an extra parameter; they have no effect - * if no window is active. - */ - -keybind (activate_window_menu, handle_activate_window_menu, 0, - BINDING_PER_WINDOW, "<Alt>space", - _("Activate the window menu")) -keybind (toggle_fullscreen, handle_toggle_fullscreen, 0, BINDING_PER_WINDOW, - NULL, - _("Toggle fullscreen mode")) -keybind (toggle_maximized, handle_toggle_maximized, 0, BINDING_PER_WINDOW, "<Alt>F10", - _("Toggle maximization state")) -keybind (toggle_above, handle_toggle_above, 0, BINDING_PER_WINDOW, NULL, - _("Toggle whether a window will always be visible over other windows")) -keybind (maximize, handle_maximize, 0, BINDING_PER_WINDOW, NULL, - _("Maximize window")) -keybind (unmaximize, handle_unmaximize, 0, BINDING_PER_WINDOW, "<Alt>F5", - _("Restore window")) -keybind (toggle_shaded, handle_toggle_shaded, 0, BINDING_PER_WINDOW, NULL, - _("Toggle shaded state")) -keybind (minimize, handle_minimize, 0, BINDING_PER_WINDOW, "<Alt>F9", - _("Minimize window")) -keybind (close, handle_close, 0, BINDING_PER_WINDOW, "<Alt>F4", - _("Close window")) -keybind (begin_move, handle_begin_move, 0, BINDING_PER_WINDOW, "<Alt>F7", - _("Move window")) -keybind (begin_resize, handle_begin_resize, 0, BINDING_PER_WINDOW, "<Alt>F8", - _("Resize window")) -keybind (toggle_on_all_workspaces, handle_toggle_on_all_workspaces, 0, - BINDING_PER_WINDOW, NULL, - _("Toggle whether window is on all workspaces or just one")) - -keybind (move_to_workspace_1, handle_move_to_workspace, 0, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 1")) -keybind (move_to_workspace_2, handle_move_to_workspace, 1, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 2")) -keybind (move_to_workspace_3, handle_move_to_workspace, 2, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 3")) -keybind (move_to_workspace_4, handle_move_to_workspace, 3, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 4")) -keybind (move_to_workspace_5, handle_move_to_workspace, 4, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 5")) -keybind (move_to_workspace_6, handle_move_to_workspace, 5, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 6")) -keybind (move_to_workspace_7, handle_move_to_workspace, 6, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 7")) -keybind (move_to_workspace_8, handle_move_to_workspace, 7, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 8")) -keybind (move_to_workspace_9, handle_move_to_workspace, 8, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 9")) -keybind (move_to_workspace_10, handle_move_to_workspace, 9, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 10")) -keybind (move_to_workspace_11, handle_move_to_workspace, 10, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 11")) -keybind (move_to_workspace_12, handle_move_to_workspace, 11, BINDING_PER_WINDOW, - NULL, - _("Move window to workspace 12")) - -/* META_MOTION_* are negative, and so distinct from workspace numbers, - * which are always zero or positive. - * If you make use of these constants, you will need to include workspace.h - * (which you're probably using already for other reasons anyway). - * If your definition of keybind() throws them away, you don't need to include - * workspace.h, of course. - */ - -keybind (move_to_workspace_left, handle_move_to_workspace, - META_MOTION_LEFT, BINDING_PER_WINDOW, "<Control><Shift><Alt>Left", - _("Move window one workspace to the left")) -keybind (move_to_workspace_right, handle_move_to_workspace, - META_MOTION_RIGHT, BINDING_PER_WINDOW, "<Control><Shift><Alt>Right", - _("Move window one workspace to the right")) -keybind (move_to_workspace_up, handle_move_to_workspace, - META_MOTION_UP, BINDING_PER_WINDOW, "<Control><Shift><Alt>Up", - _("Move window one workspace up")) -keybind (move_to_workspace_down, handle_move_to_workspace, - META_MOTION_DOWN, BINDING_PER_WINDOW, "<Control><Shift><Alt>Down", - _("Move window one workspace down")) - -keybind (raise_or_lower, handle_raise_or_lower, 0, BINDING_PER_WINDOW, NULL, - _("Raise window if it's covered by another window, otherwise lower it")) -keybind (raise, handle_raise, 0, BINDING_PER_WINDOW, NULL, - _("Raise window above other windows")) -keybind (lower, handle_lower, 0, BINDING_PER_WINDOW, NULL, - _("Lower window below other windows")) - -keybind (maximize_vertically, handle_maximize_vertically, 0, - BINDING_PER_WINDOW, NULL, - _("Maximize window vertically")) - -keybind (maximize_horizontally, handle_maximize_horizontally, 0, - BINDING_PER_WINDOW, NULL, - _("Maximize window horizontally")) - -keybind (move_to_corner_nw, handle_move_to_corner_nw, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to north-west (top left) corner")) -keybind (move_to_corner_ne, handle_move_to_corner_ne, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to north-east (top right) corner")) -keybind (move_to_corner_sw, handle_move_to_corner_sw, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to south-west (bottom left) corner")) -keybind (move_to_corner_se, handle_move_to_corner_se, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to south-east (bottom right) corner")) - -keybind (move_to_side_n, handle_move_to_side_n, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to north (top) side of screen")) -keybind (move_to_side_s, handle_move_to_side_s, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to south (bottom) side of screen")) -keybind (move_to_side_e, handle_move_to_side_e, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to east (right) side of screen")) -keybind (move_to_side_w, handle_move_to_side_w, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to west (left) side of screen")) -keybind (move_to_center, handle_move_to_center, 0, - BINDING_PER_WINDOW, NULL, - _("Move window to center of screen")) - -/* eof all-keybindings.h */ - diff --git a/src/include/boxes.h b/src/include/boxes.h deleted file mode 100644 index 54b94ea9..00000000 --- a/src/include/boxes.h +++ /dev/null @@ -1,290 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Simple box operations */ - -/* - * Copyright (C) 2005, 2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_BOXES_H -#define META_BOXES_H - -#include <glib.h> -#include "common.h" - -typedef struct _MetaRectangle MetaRectangle; -struct _MetaRectangle -{ - int x; - int y; - int width; - int height; -}; - -typedef struct _MetaStrut MetaStrut; -struct _MetaStrut -{ - MetaRectangle rect; - MetaDirection side; -}; - -#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */ -#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */ -#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */ -#define BOX_BOTTOM(box) ((box).y + (box).height) /* One pixel past bottom */ - -typedef enum -{ - FIXED_DIRECTION_NONE = 0, - FIXED_DIRECTION_X = 1 << 0, - FIXED_DIRECTION_Y = 1 << 1, -} FixedDirections; - -typedef enum -{ - META_EDGE_WINDOW, - META_EDGE_XINERAMA, - META_EDGE_SCREEN -} MetaEdgeType; - -typedef struct _MetaEdge MetaEdge; -struct _MetaEdge -{ - MetaRectangle rect; /* width or height should be 1 */ - MetaDirection side_type; /* should only have 1 of the 4 directions set */ - MetaEdgeType edge_type; -}; - -/* Output functions -- note that the output buffer had better be big enough: - * rect_to_string: RECT_LENGTH - * region_to_string: (RECT_LENGTH+strlen(separator_string)) * - * g_list_length (region) - * edge_to_string: EDGE_LENGTH - * edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) * - * g_list_length (edge_list) - */ -#define RECT_LENGTH 27 -#define EDGE_LENGTH 37 -char* meta_rectangle_to_string (const MetaRectangle *rect, - char *output); -char* meta_rectangle_region_to_string (GList *region, - const char *separator_string, - char *output); -char* meta_rectangle_edge_to_string (const MetaEdge *edge, - char *output); -char* meta_rectangle_edge_list_to_string ( - GList *edge_list, - const char *separator_string, - char *output); - -/* Function to make initializing a rect with a single line of code easy */ -MetaRectangle meta_rect (int x, int y, int width, int height); - -/* Basic comparison functions */ -int meta_rectangle_area (const MetaRectangle *rect); -gboolean meta_rectangle_intersect (const MetaRectangle *src1, - const MetaRectangle *src2, - MetaRectangle *dest); -gboolean meta_rectangle_equal (const MetaRectangle *src1, - const MetaRectangle *src2); - -/* Find the bounding box of the union of two rectangles */ -void meta_rectangle_union (const MetaRectangle *rect1, - const MetaRectangle *rect2, - MetaRectangle *dest); - -/* overlap is similar to intersect but doesn't provide location of - * intersection information. - */ -gboolean meta_rectangle_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2); - -/* vert_overlap means ignore the horizontal location and ask if the - * vertical parts overlap. An alternate way to think of it is "Does there - * exist a way to shift either rect horizontally so that the two rects - * overlap?" horiz_overlap is similar. - */ -gboolean meta_rectangle_vert_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2); -gboolean meta_rectangle_horiz_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2); - -/* could_fit_rect determines whether "outer_rect" is big enough to contain - * inner_rect. contains_rect checks whether it actually contains it. - */ -gboolean meta_rectangle_could_fit_rect (const MetaRectangle *outer_rect, - const MetaRectangle *inner_rect); -gboolean meta_rectangle_contains_rect (const MetaRectangle *outer_rect, - const MetaRectangle *inner_rect); - -/* Resize old_rect to the given new_width and new_height, but store the - * result in rect. NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR - * A MOVERESIZE OPERATION (that simplies the routine a little bit as it - * means there's no difference between NorthWestGravity and StaticGravity. - * Also, I lied a little bit--technically, you could use it in a MoveResize - * operation if you muck with old_rect just right). - */ -void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect, - MetaRectangle *rect, - int gravity, - int new_width, - int new_height); - -/* find a list of rectangles with the property that a window is contained - * in the given region if and only if it is contained in one of the - * rectangles in the list. - * - * In this case, the region is given by taking basic_rect, removing from - * it the intersections with all the rectangles in the all_struts list, - * then expanding all the rectangles in the resulting list by the given - * amounts on each side. - * - * See boxes.c for more details. - */ -GList* meta_rectangle_get_minimal_spanning_set_for_region ( - const MetaRectangle *basic_rect, - const GSList *all_struts); - -/* Expand all rectangles in region by the given amount on each side */ -GList* meta_rectangle_expand_region (GList *region, - const int left_expand, - const int right_expand, - const int top_expand, - const int bottom_expand); -/* Same as for meta_rectangle_expand_region except that rectangles not at - * least min_x or min_y in size are not expanded in that direction - */ -GList* meta_rectangle_expand_region_conditionally ( - GList *region, - const int left_expand, - const int right_expand, - const int top_expand, - const int bottom_expand, - const int min_x, - const int min_y); - -/* Expand rect in direction to the size of expand_to, and then clip out any - * overlapping struts oriented orthognal to the expansion direction. (Think - * horizontal or vertical maximization) - */ -void meta_rectangle_expand_to_avoiding_struts ( - MetaRectangle *rect, - const MetaRectangle *expand_to, - const MetaDirection direction, - const GSList *all_struts); - -/* Free the list created by - * meta_rectangle_get_minimal_spanning_set_for_region() - * or - * meta_rectangle_find_onscreen_edges () - * or - * meta_rectangle_find_nonintersected_xinerama_edges() - */ -void meta_rectangle_free_list_and_elements (GList *filled_list); - -/* could_fit_in_region determines whether one of the spanning_rects is - * big enough to contain rect. contained_in_region checks whether one - * actually contains it. - */ -gboolean meta_rectangle_could_fit_in_region ( - const GList *spanning_rects, - const MetaRectangle *rect); -gboolean meta_rectangle_contained_in_region ( - const GList *spanning_rects, - const MetaRectangle *rect); -gboolean meta_rectangle_overlaps_with_region ( - const GList *spanning_rects, - const MetaRectangle *rect); - -/* Make the rectangle small enough to fit into one of the spanning_rects, - * but make it no smaller than min_size. - */ -void meta_rectangle_clamp_to_fit_into_region ( - const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect, - const MetaRectangle *min_size); - -/* Clip the rectangle so that it fits into one of the spanning_rects, assuming - * it overlaps with at least one of them - */ -void meta_rectangle_clip_to_region (const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect); - -/* Shove the rectangle into one of the spanning_rects, assuming it fits in - * one of them. - */ -void meta_rectangle_shove_into_region( - const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect); - -/* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest - * to (px, py). Useful for finding an optimal rectangle size when given a - * range between two sizes that are all candidates. - */ -void meta_rectangle_find_linepoint_closest_to_point (double x1, double y1, - double x2, double y2, - double px, double py, - double *valx, double *valy); - -/***************************************************************************/ -/* */ -/* Switching gears to code for edges instead of just rectangles */ -/* */ -/***************************************************************************/ - -/* Return whether an edge overlaps or is adjacent to the rectangle in the - * nonzero-width dimension of the edge. - */ -gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect, - const MetaEdge *edge); - -/* Compare two edges, so that sorting functions can put a list of edges in - * canonical order. - */ -gint meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b); - -/* Compare two edges, so that sorting functions can put a list of edges in - * order. This function doesn't separate left edges first, then right edges, - * etc., but rather compares only upon location. - */ -gint meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b); - -/* Removes an parts of edges in the given list that intersect any box in the - * given rectangle list. Returns the result. - */ -GList* meta_rectangle_remove_intersections_with_boxes_from_edges ( - GList *edges, - const GSList *rectangles); - -/* Finds all the edges of an onscreen region, returning a GList* of - * MetaEdgeRect's. - */ -GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect, - const GSList *all_struts); - -/* Finds edges between adjacent xineramas which are not covered by the given - * struts. - */ -GList* meta_rectangle_find_nonintersected_xinerama_edges ( - const GList *xinerama_rects, - const GSList *all_struts); - -#endif /* META_BOXES_H */ diff --git a/src/include/common.h b/src/include/common.h deleted file mode 100644 index 9d6a98c5..00000000 --- a/src/include/common.h +++ /dev/null @@ -1,292 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity common types shared by core.h and ui.h */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_COMMON_H -#define META_COMMON_H - -/* Don't include GTK or core headers here */ -#include <X11/Xlib.h> -#include <glib.h> - -typedef struct _MetaResizePopup MetaResizePopup; - -typedef enum -{ - META_FRAME_ALLOWS_DELETE = 1 << 0, - META_FRAME_ALLOWS_MENU = 1 << 1, - META_FRAME_ALLOWS_MINIMIZE = 1 << 2, - META_FRAME_ALLOWS_MAXIMIZE = 1 << 3, - META_FRAME_ALLOWS_VERTICAL_RESIZE = 1 << 4, - META_FRAME_ALLOWS_HORIZONTAL_RESIZE = 1 << 5, - META_FRAME_HAS_FOCUS = 1 << 6, - META_FRAME_SHADED = 1 << 7, - META_FRAME_STUCK = 1 << 8, - META_FRAME_MAXIMIZED = 1 << 9, - META_FRAME_ALLOWS_SHADE = 1 << 10, - META_FRAME_ALLOWS_MOVE = 1 << 11, - META_FRAME_FULLSCREEN = 1 << 12, - META_FRAME_IS_FLASHING = 1 << 13, - META_FRAME_ABOVE = 1 << 14 -} MetaFrameFlags; - -typedef enum -{ - META_MENU_OP_DELETE = 1 << 0, - META_MENU_OP_MINIMIZE = 1 << 1, - META_MENU_OP_UNMAXIMIZE = 1 << 2, - META_MENU_OP_MAXIMIZE = 1 << 3, - META_MENU_OP_UNSHADE = 1 << 4, - META_MENU_OP_SHADE = 1 << 5, - META_MENU_OP_UNSTICK = 1 << 6, - META_MENU_OP_STICK = 1 << 7, - META_MENU_OP_WORKSPACES = 1 << 8, - META_MENU_OP_MOVE = 1 << 9, - META_MENU_OP_RESIZE = 1 << 10, - META_MENU_OP_ABOVE = 1 << 11, - META_MENU_OP_UNABOVE = 1 << 12, - META_MENU_OP_MOVE_LEFT = 1 << 13, - META_MENU_OP_MOVE_RIGHT = 1 << 14, - META_MENU_OP_MOVE_UP = 1 << 15, - META_MENU_OP_MOVE_DOWN = 1 << 16, - META_MENU_OP_RECOVER = 1 << 17 -} MetaMenuOp; - -typedef struct _MetaWindowMenu MetaWindowMenu; - -typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu, - Display *xdisplay, - Window client_xwindow, - guint32 timestamp, - MetaMenuOp op, - int workspace, - gpointer data); - -/* when changing this enum, there are various switch statements - * you have to update - */ -typedef enum -{ - META_GRAB_OP_NONE, - - /* Mouse ops */ - META_GRAB_OP_MOVING, - META_GRAB_OP_RESIZING_SE, - META_GRAB_OP_RESIZING_S, - META_GRAB_OP_RESIZING_SW, - META_GRAB_OP_RESIZING_N, - META_GRAB_OP_RESIZING_NE, - META_GRAB_OP_RESIZING_NW, - META_GRAB_OP_RESIZING_W, - META_GRAB_OP_RESIZING_E, - - /* Keyboard ops */ - META_GRAB_OP_KEYBOARD_MOVING, - META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, - META_GRAB_OP_KEYBOARD_RESIZING_S, - META_GRAB_OP_KEYBOARD_RESIZING_N, - META_GRAB_OP_KEYBOARD_RESIZING_W, - META_GRAB_OP_KEYBOARD_RESIZING_E, - META_GRAB_OP_KEYBOARD_RESIZING_SE, - META_GRAB_OP_KEYBOARD_RESIZING_NE, - META_GRAB_OP_KEYBOARD_RESIZING_SW, - META_GRAB_OP_KEYBOARD_RESIZING_NW, - - /* Alt+Tab */ - META_GRAB_OP_KEYBOARD_TABBING_NORMAL, - META_GRAB_OP_KEYBOARD_TABBING_DOCK, - - /* Alt+Esc */ - META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL, - META_GRAB_OP_KEYBOARD_ESCAPING_DOCK, - - META_GRAB_OP_KEYBOARD_ESCAPING_GROUP, - - /* Alt+F6 */ - META_GRAB_OP_KEYBOARD_TABBING_GROUP, - - META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING, - - /* Frame button ops */ - META_GRAB_OP_CLICKING_MINIMIZE, - META_GRAB_OP_CLICKING_MAXIMIZE, - META_GRAB_OP_CLICKING_UNMAXIMIZE, - META_GRAB_OP_CLICKING_DELETE, - META_GRAB_OP_CLICKING_MENU, - META_GRAB_OP_CLICKING_SHADE, - META_GRAB_OP_CLICKING_UNSHADE, - META_GRAB_OP_CLICKING_ABOVE, - META_GRAB_OP_CLICKING_UNABOVE, - META_GRAB_OP_CLICKING_STICK, - META_GRAB_OP_CLICKING_UNSTICK -} MetaGrabOp; - -typedef enum -{ - META_CURSOR_DEFAULT, - META_CURSOR_NORTH_RESIZE, - META_CURSOR_SOUTH_RESIZE, - META_CURSOR_WEST_RESIZE, - META_CURSOR_EAST_RESIZE, - META_CURSOR_SE_RESIZE, - META_CURSOR_SW_RESIZE, - META_CURSOR_NE_RESIZE, - META_CURSOR_NW_RESIZE, - META_CURSOR_MOVE_OR_RESIZE_WINDOW, - META_CURSOR_BUSY - -} MetaCursor; - -typedef enum -{ - META_FOCUS_MODE_CLICK, - META_FOCUS_MODE_SLOPPY, - META_FOCUS_MODE_MOUSE -} MetaFocusMode; - -typedef enum -{ - META_FOCUS_NEW_WINDOWS_SMART, - META_FOCUS_NEW_WINDOWS_STRICT -} MetaFocusNewWindows; - -typedef enum -{ - META_ACTION_TITLEBAR_TOGGLE_SHADE, - META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE, - META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_HORIZONTALLY, - META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_VERTICALLY, - META_ACTION_TITLEBAR_MINIMIZE, - META_ACTION_TITLEBAR_NONE, - META_ACTION_TITLEBAR_LOWER, - META_ACTION_TITLEBAR_MENU, - META_ACTION_TITLEBAR_LAST -} MetaActionTitlebar; - -typedef enum -{ - META_FRAME_TYPE_NORMAL, - META_FRAME_TYPE_DIALOG, - META_FRAME_TYPE_MODAL_DIALOG, - META_FRAME_TYPE_UTILITY, - META_FRAME_TYPE_MENU, - META_FRAME_TYPE_BORDER, - META_FRAME_TYPE_LAST -} MetaFrameType; - -typedef enum -{ - /* Create gratuitous divergence from regular - * X mod bits, to be sure we find bugs - */ - META_VIRTUAL_SHIFT_MASK = 1 << 5, - META_VIRTUAL_CONTROL_MASK = 1 << 6, - META_VIRTUAL_ALT_MASK = 1 << 7, - META_VIRTUAL_META_MASK = 1 << 8, - META_VIRTUAL_SUPER_MASK = 1 << 9, - META_VIRTUAL_HYPER_MASK = 1 << 10, - META_VIRTUAL_MOD2_MASK = 1 << 11, - META_VIRTUAL_MOD3_MASK = 1 << 12, - META_VIRTUAL_MOD4_MASK = 1 << 13, - META_VIRTUAL_MOD5_MASK = 1 << 14 -} MetaVirtualModifier; - -/* Relative directions or sides seem to come up all over the place... */ -/* FIXME: Replace - * screen.[ch]:MetaScreenDirection, - * workspace.[ch]:MetaMotionDirection, - * with the use of MetaDirection. - */ -typedef enum -{ - META_DIRECTION_LEFT = 1 << 0, - META_DIRECTION_RIGHT = 1 << 1, - META_DIRECTION_TOP = 1 << 2, - META_DIRECTION_BOTTOM = 1 << 3, - - /* Some aliases for making code more readable for various circumstances. */ - META_DIRECTION_UP = META_DIRECTION_TOP, - META_DIRECTION_DOWN = META_DIRECTION_BOTTOM, - - /* A few more definitions using aliases */ - META_DIRECTION_HORIZONTAL = META_DIRECTION_LEFT | META_DIRECTION_RIGHT, - META_DIRECTION_VERTICAL = META_DIRECTION_UP | META_DIRECTION_DOWN, - - /* And a few more aliases */ - META_SIDE_LEFT = META_DIRECTION_LEFT, - META_SIDE_RIGHT = META_DIRECTION_RIGHT, - META_SIDE_TOP = META_DIRECTION_TOP, - META_SIDE_BOTTOM = META_DIRECTION_BOTTOM -} MetaDirection; - -/* Function a window button can have. Note, you can't add stuff here - * without extending the theme format to draw a new function and - * breaking all existing themes. - */ -typedef enum -{ - META_BUTTON_FUNCTION_MENU, - META_BUTTON_FUNCTION_MINIMIZE, - META_BUTTON_FUNCTION_MAXIMIZE, - META_BUTTON_FUNCTION_CLOSE, - META_BUTTON_FUNCTION_SHADE, - META_BUTTON_FUNCTION_ABOVE, - META_BUTTON_FUNCTION_STICK, - META_BUTTON_FUNCTION_UNSHADE, - META_BUTTON_FUNCTION_UNABOVE, - META_BUTTON_FUNCTION_UNSTICK, - META_BUTTON_FUNCTION_LAST -} MetaButtonFunction; - -#define MAX_BUTTONS_PER_CORNER META_BUTTON_FUNCTION_LAST - -typedef struct _MetaButtonLayout MetaButtonLayout; -struct _MetaButtonLayout -{ - /* buttons in the group on the left side */ - MetaButtonFunction left_buttons[MAX_BUTTONS_PER_CORNER]; - gboolean left_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; - - /* buttons in the group on the right side */ - MetaButtonFunction right_buttons[MAX_BUTTONS_PER_CORNER]; - gboolean right_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; -}; - -/* should investigate changing these to whatever most apps use */ -#define META_ICON_WIDTH 32 -#define META_ICON_HEIGHT 32 -#define META_MINI_ICON_WIDTH 16 -#define META_MINI_ICON_HEIGHT 16 - -#define META_DEFAULT_ICON_NAME "window" - -#define META_PRIORITY_PREFS_NOTIFY (G_PRIORITY_DEFAULT_IDLE + 10) -#define META_PRIORITY_WORK_AREA_HINT (G_PRIORITY_DEFAULT_IDLE + 15) - -#define POINT_IN_RECT(xcoord, ycoord, rect) \ - ((xcoord) >= (rect).x && \ - (xcoord) < ((rect).x + (rect).width) && \ - (ycoord) >= (rect).y && \ - (ycoord) < ((rect).y + (rect).height)) - -#endif diff --git a/src/include/compositor.h b/src/include/compositor.h deleted file mode 100644 index a7f9bf1f..00000000 --- a/src/include/compositor.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_COMPOSITOR_H -#define META_COMPOSITOR_H - -#include <glib.h> -#include <X11/Xlib.h> - -#include "types.h" -#include "boxes.h" - -MetaCompositor *meta_compositor_new (MetaDisplay *display); -void meta_compositor_destroy (MetaCompositor *compositor); - -void meta_compositor_manage_screen (MetaCompositor *compositor, - MetaScreen *screen); -void meta_compositor_unmanage_screen (MetaCompositor *compositor, - MetaScreen *screen); - -void meta_compositor_add_window (MetaCompositor *compositor, - MetaWindow *window, - Window xwindow, - XWindowAttributes *attrs); -void meta_compositor_remove_window (MetaCompositor *compositor, - Window xwindow); - -void meta_compositor_set_updates (MetaCompositor *compositor, - MetaWindow *window, - gboolean updates); - -void meta_compositor_process_event (MetaCompositor *compositor, - XEvent *event, - MetaWindow *window); -Pixmap meta_compositor_get_window_pixmap (MetaCompositor *compositor, - MetaWindow *window); -void meta_compositor_set_active_window (MetaCompositor *compositor, - MetaScreen *screen, - MetaWindow *window); - -void meta_compositor_begin_move (MetaCompositor *compositor, - MetaWindow *window, - MetaRectangle *initial, - int grab_x, int grab_y); -void meta_compositor_update_move (MetaCompositor *compositor, - MetaWindow *window, - int x, int y); -void meta_compositor_end_move (MetaCompositor *compositor, - MetaWindow *window); -void meta_compositor_free_window (MetaCompositor *compositor, - MetaWindow *window); - -#endif - - - - - diff --git a/src/include/core.h b/src/include/core.h deleted file mode 100644 index 0c518e74..00000000 --- a/src/include/core.h +++ /dev/null @@ -1,208 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity interface used by GTK+ UI to talk to core */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_CORE_H -#define META_CORE_H - -/* Don't include core headers here */ -#include <gdk/gdkx.h> -#include "common.h" - -typedef enum -{ - META_CORE_GET_END = 0, - META_CORE_WINDOW_HAS_FRAME, - META_CORE_GET_CLIENT_WIDTH, - META_CORE_GET_CLIENT_HEIGHT, - META_CORE_IS_TITLEBAR_ONSCREEN, - META_CORE_GET_CLIENT_XWINDOW, - META_CORE_GET_FRAME_FLAGS, - META_CORE_GET_FRAME_TYPE, - META_CORE_GET_MINI_ICON, - META_CORE_GET_ICON, - META_CORE_GET_X, - META_CORE_GET_Y, - META_CORE_GET_FRAME_WORKSPACE, - META_CORE_GET_FRAME_X, - META_CORE_GET_FRAME_Y, - META_CORE_GET_FRAME_WIDTH, - META_CORE_GET_FRAME_HEIGHT, - META_CORE_GET_SCREEN_WIDTH, - META_CORE_GET_SCREEN_HEIGHT, -} MetaCoreGetType; - -/* General information function about the given window. Pass in a sequence of - * pairs of MetaCoreGetTypes and pointers to variables; the variables will be - * filled with the requested values. End the list with META_CORE_GET_END. - * For example: - * - * meta_core_get (my_display, my_window, - * META_CORE_GET_X, &x, - * META_CORE_GET_Y, &y, - * META_CORE_GET_END); - * - * If the window doesn't have a frame, this will raise a meta_bug. To suppress - * this behaviour, ask META_CORE_WINDOW_HAS_FRAME as the *first* question in - * the list. If the window has no frame, the answer to this question will be - * False, and anything else you asked will be undefined. Otherwise, the answer - * will be True. The answer will necessarily be True if you ask the question - * in any other position. The positions of all other questions don't matter. - * - * The reason for this function is that some parts of the program don't know - * about MetaWindows. But they *can* see core.h. So we used to have a whole - * load of functions which took a display and an X window, looked up the - * relevant MetaWindow, and returned information about it. The trouble with - * that is that looking up the MetaWindow is a nontrivial operation, and - * consolidating the calls in this way makes (for example) frame exposes - * 33% faster, according to valgrind. - * - * This function would perhaps be slightly better if the questions were - * represented by pointers, perhaps gchar*s, because then we could take - * advantage of gcc's automatic sentinel checking. On the other hand, this - * immediately suggests string comparison, and that's slow. - * - * Another possible improvement is that core.h still has a bunch of - * functions which can't be described by the formula "give a display and - * an X window, get a single value" (meta_core_user_move, for example), but - * which could theoretically be handled by this function if we relaxed the - * requirement that all questions should have exactly one argument. - */ -void meta_core_get (Display *xdisplay, - Window window, - ...); - -void meta_core_queue_frame_resize (Display *xdisplay, - Window frame_xwindow); - -/* Move as a result of user operation */ -void meta_core_user_move (Display *xdisplay, - Window frame_xwindow, - int x, - int y); -void meta_core_user_resize (Display *xdisplay, - Window frame_xwindow, - int gravity, - int width, - int height); - -void meta_core_user_raise (Display *xdisplay, - Window frame_xwindow); -void meta_core_user_lower_and_unfocus (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp); - -void meta_core_user_focus (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp); - -void meta_core_minimize (Display *xdisplay, - Window frame_xwindow); -void meta_core_toggle_maximize (Display *xdisplay, - Window frame_xwindow); -void meta_core_toggle_maximize_horizontally (Display *xdisplay, - Window frame_xwindow); -void meta_core_toggle_maximize_vertically (Display *xdisplay, - Window frame_xwindow); -void meta_core_unmaximize (Display *xdisplay, - Window frame_xwindow); -void meta_core_maximize (Display *xdisplay, - Window frame_xwindow); -void meta_core_delete (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp); -void meta_core_unshade (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp); -void meta_core_shade (Display *xdisplay, - Window frame_xwindow, - guint32 timestamp); -void meta_core_unstick (Display *xdisplay, - Window frame_xwindow); -void meta_core_stick (Display *xdisplay, - Window frame_xwindow); -void meta_core_unmake_above (Display *xdisplay, - Window frame_xwindow); -void meta_core_make_above (Display *xdisplay, - Window frame_xwindow); -void meta_core_change_workspace (Display *xdisplay, - Window frame_xwindow, - int new_workspace); - -int meta_core_get_num_workspaces (Screen *xscreen); -int meta_core_get_active_workspace (Screen *xscreen); -int meta_core_get_frame_workspace (Display *xdisplay, - Window frame_xwindow); -const char* meta_core_get_workspace_name_with_index (Display *xdisplay, - Window xroot, - int index); - -void meta_core_show_window_menu (Display *xdisplay, - Window frame_xwindow, - int root_x, - int root_y, - int button, - guint32 timestamp); - -void meta_core_get_menu_accelerator (MetaMenuOp menu_op, - int workspace, - unsigned int *keysym, - MetaVirtualModifier *modifiers); - -gboolean meta_core_begin_grab_op (Display *xdisplay, - Window frame_xwindow, - MetaGrabOp op, - gboolean pointer_already_grabbed, - gboolean frame_action, - int button, - gulong modmask, - guint32 timestamp, - int root_x, - int root_y); -void meta_core_end_grab_op (Display *xdisplay, - guint32 timestamp); -MetaGrabOp meta_core_get_grab_op (Display *xdisplay); -Window meta_core_get_grab_frame (Display *xdisplay); -int meta_core_get_grab_button (Display *xdisplay); - - -void meta_core_grab_buttons (Display *xdisplay, - Window frame_xwindow); - -void meta_core_set_screen_cursor (Display *xdisplay, - Window frame_on_screen, - MetaCursor cursor); - -/* Used because we ignore EnterNotify when a window is unmapped that - * really shouldn't cause focus changes, by comparing the event serial - * of the EnterNotify and the UnmapNotify. - */ -void meta_core_increment_event_serial (Display *display); - -void meta_invalidate_default_icons (void); - -#endif - - - - diff --git a/src/include/display.h b/src/include/display.h deleted file mode 100644 index 53dd9d75..00000000 --- a/src/include/display.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_DISPLAY_H -#define META_DISPLAY_H - -#include <glib.h> -#include <X11/Xlib.h> - -#include "types.h" - -#define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0) - -void meta_display_get_compositor_version (MetaDisplay *display, - int *major, - int *minor); -Display *meta_display_get_xdisplay (MetaDisplay *display); -MetaCompositor *meta_display_get_compositor (MetaDisplay *display); -GSList *meta_display_get_screens (MetaDisplay *display); - -gboolean meta_display_has_shape (MetaDisplay *display); - -MetaScreen *meta_display_screen_for_root (MetaDisplay *display, - Window xroot); -MetaWindow *meta_display_get_focus_window (MetaDisplay *display); - -int meta_display_get_damage_event_base (MetaDisplay *display); -int meta_display_get_shape_event_base (MetaDisplay *display); - -#endif diff --git a/src/include/errors.h b/src/include/errors.h deleted file mode 100644 index 8278948a..00000000 --- a/src/include/errors.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X error handling */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_ERRORS_H -#define META_ERRORS_H - -#include <X11/Xlib.h> - -#include "util.h" -#include "display.h" - -typedef void (* ErrorHandler) (Display *dpy, - XErrorEvent *error, - gpointer data); - -void meta_errors_init (void); -void meta_errors_register_foreign_display (Display *foreign_dpy, - ErrorHandler handler, - gpointer data); - -void meta_error_trap_push (MetaDisplay *display); -void meta_error_trap_pop (MetaDisplay *display, - gboolean last_request_was_roundtrip); - -void meta_error_trap_push_with_return (MetaDisplay *display); -/* returns X error code, or 0 for no error */ -int meta_error_trap_pop_with_return (MetaDisplay *display, - gboolean last_request_was_roundtrip); - - -#endif diff --git a/src/include/frame.h b/src/include/frame.h deleted file mode 100644 index eeb57263..00000000 --- a/src/include/frame.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_FRAME_H -#define META_FRAME_H - -#include <X11/Xlib.h> - -#include "types.h" - -Window meta_frame_get_xwindow (MetaFrame *frame); - -#endif diff --git a/src/include/main.h b/src/include/main.h deleted file mode 100644 index 62106e16..00000000 --- a/src/include/main.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity main */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_MAIN_H -#define META_MAIN_H - -#include <glib.h> - -typedef enum -{ - META_EXIT_SUCCESS, - META_EXIT_ERROR -} MetaExitCode; - -/* exit immediately */ -void meta_exit (MetaExitCode code); - -/* g_main_loop_quit() then fall out of main() */ -void meta_quit (MetaExitCode code); - -void meta_restart (void); - -#endif diff --git a/src/include/prefs.h b/src/include/prefs.h deleted file mode 100644 index 5acad233..00000000 --- a/src/include/prefs.h +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity preferences */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_PREFS_H -#define META_PREFS_H - -/* This header is a "common" one between the UI and core side */ -#include "common.h" -#include <pango/pango-font.h> - -typedef enum -{ - META_PREF_MOUSE_BUTTON_MODS, - META_PREF_FOCUS_MODE, - META_PREF_FOCUS_NEW_WINDOWS, - META_PREF_RAISE_ON_CLICK, - META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR, - META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR, - META_PREF_ACTION_RIGHT_CLICK_TITLEBAR, - META_PREF_AUTO_RAISE, - META_PREF_AUTO_RAISE_DELAY, - META_PREF_THEME, - META_PREF_TITLEBAR_FONT, - META_PREF_NUM_WORKSPACES, - META_PREF_APPLICATION_BASED, - META_PREF_KEYBINDINGS, - META_PREF_DISABLE_WORKAROUNDS, - META_PREF_COMMANDS, - META_PREF_TERMINAL_COMMAND, - META_PREF_BUTTON_LAYOUT, - META_PREF_WORKSPACE_NAMES, - META_PREF_VISUAL_BELL, - META_PREF_AUDIBLE_BELL, - META_PREF_VISUAL_BELL_TYPE, - META_PREF_REDUCED_RESOURCES, - META_PREF_GNOME_ACCESSIBILITY, - META_PREF_GNOME_ANIMATIONS, - META_PREF_CURSOR_THEME, - META_PREF_CURSOR_SIZE, - META_PREF_COMPOSITING_MANAGER -} MetaPreference; - -typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, - gpointer data); - -void meta_prefs_add_listener (MetaPrefsChangedFunc func, - gpointer data); -void meta_prefs_remove_listener (MetaPrefsChangedFunc func, - gpointer data); - -void meta_prefs_init (void); -const char* meta_preference_to_string (MetaPreference pref); - -MetaVirtualModifier meta_prefs_get_mouse_button_mods (void); -MetaFocusMode meta_prefs_get_focus_mode (void); -MetaFocusNewWindows meta_prefs_get_focus_new_windows (void); -gboolean meta_prefs_get_raise_on_click (void); -const char* meta_prefs_get_theme (void); -/* returns NULL if GTK default should be used */ -const PangoFontDescription* meta_prefs_get_titlebar_font (void); -int meta_prefs_get_num_workspaces (void); -gboolean meta_prefs_get_application_based (void); -gboolean meta_prefs_get_disable_workarounds (void); -gboolean meta_prefs_get_auto_raise (void); -int meta_prefs_get_auto_raise_delay (void); -gboolean meta_prefs_get_reduced_resources (void); -gboolean meta_prefs_get_gnome_accessibility (void); -gboolean meta_prefs_get_gnome_animations (void); - -const char* meta_prefs_get_command (int i); - -char* meta_prefs_get_gconf_key_for_command (int i); - -const char* meta_prefs_get_terminal_command (void); -const char* meta_prefs_get_gconf_key_for_terminal_command (void); - -void meta_prefs_get_button_layout (MetaButtonLayout *button_layout); - -/* Double, right, middle click can be configured to any titlebar meta-action */ -MetaActionTitlebar meta_prefs_get_action_double_click_titlebar (void); -MetaActionTitlebar meta_prefs_get_action_middle_click_titlebar (void); -MetaActionTitlebar meta_prefs_get_action_right_click_titlebar (void); - -void meta_prefs_set_num_workspaces (int n_workspaces); - -const char* meta_prefs_get_workspace_name (int i); -void meta_prefs_change_workspace_name (int i, - const char *name); - -const char* meta_prefs_get_cursor_theme (void); -int meta_prefs_get_cursor_size (void); -gboolean meta_prefs_get_compositing_manager (void); - -/** - * Sets whether the compositor is turned on. - * - * \param whether TRUE to turn on, FALSE to turn off - */ -void meta_prefs_set_compositing_manager (gboolean whether); - -/* XXX FIXME This should be x-macroed, but isn't yet because it would be - * difficult (or perhaps impossible) to add the suffixes using the current - * system. It needs some more thought, perhaps after the current system - * evolves a little. - */ -typedef enum _MetaKeyBindingAction -{ - META_KEYBINDING_ACTION_NONE = -1, - META_KEYBINDING_ACTION_WORKSPACE_1, - META_KEYBINDING_ACTION_WORKSPACE_2, - META_KEYBINDING_ACTION_WORKSPACE_3, - META_KEYBINDING_ACTION_WORKSPACE_4, - META_KEYBINDING_ACTION_WORKSPACE_5, - META_KEYBINDING_ACTION_WORKSPACE_6, - META_KEYBINDING_ACTION_WORKSPACE_7, - META_KEYBINDING_ACTION_WORKSPACE_8, - META_KEYBINDING_ACTION_WORKSPACE_9, - META_KEYBINDING_ACTION_WORKSPACE_10, - META_KEYBINDING_ACTION_WORKSPACE_11, - META_KEYBINDING_ACTION_WORKSPACE_12, - META_KEYBINDING_ACTION_WORKSPACE_LEFT, - META_KEYBINDING_ACTION_WORKSPACE_RIGHT, - META_KEYBINDING_ACTION_WORKSPACE_UP, - META_KEYBINDING_ACTION_WORKSPACE_DOWN, - META_KEYBINDING_ACTION_SWITCH_GROUP, - META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD, - META_KEYBINDING_ACTION_SWITCH_WINDOWS, - META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD, - META_KEYBINDING_ACTION_SWITCH_PANELS, - META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD, - META_KEYBINDING_ACTION_CYCLE_GROUP, - META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD, - META_KEYBINDING_ACTION_CYCLE_WINDOWS, - META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD, - META_KEYBINDING_ACTION_CYCLE_PANELS, - META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD, - META_KEYBINDING_ACTION_SHOW_DESKTOP, - META_KEYBINDING_ACTION_PANEL_MAIN_MENU, - META_KEYBINDING_ACTION_PANEL_RUN_DIALOG, - META_KEYBINDING_ACTION_COMMAND_1, - META_KEYBINDING_ACTION_COMMAND_2, - META_KEYBINDING_ACTION_COMMAND_3, - META_KEYBINDING_ACTION_COMMAND_4, - META_KEYBINDING_ACTION_COMMAND_5, - META_KEYBINDING_ACTION_COMMAND_6, - META_KEYBINDING_ACTION_COMMAND_7, - META_KEYBINDING_ACTION_COMMAND_8, - META_KEYBINDING_ACTION_COMMAND_9, - META_KEYBINDING_ACTION_COMMAND_10, - META_KEYBINDING_ACTION_COMMAND_11, - META_KEYBINDING_ACTION_COMMAND_12 -} MetaKeyBindingAction; - -typedef struct -{ - unsigned int keysym; - unsigned int keycode; - MetaVirtualModifier modifiers; -} MetaKeyCombo; - -typedef struct -{ - const char *name; - /** - * A list of MetaKeyCombos. Each of them is bound to - * this keypref. If one has keysym==modifiers==0, it is - * ignored. For historical reasons, the first entry is - * governed by the pref FOO and the remainder are - * governed by the pref FOO_list. - */ - GSList *bindings; - - /** for keybindings that can have shift or not like Alt+Tab */ - gboolean add_shift:1; - - /** for keybindings that apply only to a window */ - gboolean per_window:1; -} MetaKeyPref; - -void meta_prefs_get_key_bindings (const MetaKeyPref **bindings, - int *n_bindings); - -MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name); - -void meta_prefs_get_window_binding (const char *name, - unsigned int *keysym, - MetaVirtualModifier *modifiers); - -typedef enum -{ - META_VISUAL_BELL_INVALID = 0, - META_VISUAL_BELL_FULLSCREEN_FLASH, - META_VISUAL_BELL_FRAME_FLASH - -} MetaVisualBellType; - -gboolean meta_prefs_get_visual_bell (void); -gboolean meta_prefs_bell_is_audible (void); -MetaVisualBellType meta_prefs_get_visual_bell_type (void); - -#endif - - - - diff --git a/src/include/resizepopup.h b/src/include/resizepopup.h deleted file mode 100644 index a861ff38..00000000 --- a/src/include/resizepopup.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity resizing-terminal-window feedback */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_RESIZEPOPUP_H -#define META_RESIZEPOPUP_H - -/* Don't include gtk.h or gdk.h here */ -#include "boxes.h" -#include "common.h" -#include <X11/Xlib.h> -#include <glib.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -MetaResizePopup* meta_ui_resize_popup_new (Display *display, - int screen_number); -void meta_ui_resize_popup_free (MetaResizePopup *popup); -void meta_ui_resize_popup_set (MetaResizePopup *popup, - MetaRectangle rect, - int base_width, - int base_height, - int width_inc, - int height_inc); -void meta_ui_resize_popup_set_showing (MetaResizePopup *popup, - gboolean showing); - -#endif - diff --git a/src/include/screen.h b/src/include/screen.h deleted file mode 100644 index 9f842317..00000000 --- a/src/include/screen.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_SCREEN_H -#define META_SCREEN_H - -#include <X11/Xlib.h> -#include <glib.h> -#include "types.h" - -int meta_screen_get_screen_number (MetaScreen *screen); -MetaDisplay *meta_screen_get_display (MetaScreen *screen); - -Window meta_screen_get_xroot (MetaScreen *screen); -void meta_screen_get_size (MetaScreen *screen, - int *width, - int *height); - -gpointer meta_screen_get_compositor_data (MetaScreen *screen); -void meta_screen_set_compositor_data (MetaScreen *screen, - gpointer info); - -MetaScreen *meta_screen_for_x_screen (Screen *xscreen); - -#ifdef HAVE_COMPOSITE_EXTENSIONS -void meta_screen_set_cm_selection (MetaScreen *screen); -void meta_screen_unset_cm_selection (MetaScreen *screen); -#endif - -#endif diff --git a/src/include/tabpopup.h b/src/include/tabpopup.h deleted file mode 100644 index c210a191..00000000 --- a/src/include/tabpopup.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity tab popup window */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_TABPOPUP_H -#define META_TABPOPUP_H - -/* Don't include gtk.h or gdk.h here */ -#include "common.h" -#include "boxes.h" -#include <X11/Xlib.h> -#include <glib.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -typedef struct _MetaTabEntry MetaTabEntry; -typedef struct _MetaTabPopup MetaTabPopup; -typedef void *MetaTabEntryKey; - -struct _MetaTabEntry -{ - MetaTabEntryKey key; - const char *title; - GdkPixbuf *icon; - MetaRectangle rect; - MetaRectangle inner_rect; - guint blank : 1; - guint hidden : 1; - guint demands_attention : 1; -}; - -MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries, - int screen_number, - int entry_count, - int width, - gboolean outline); -void meta_ui_tab_popup_free (MetaTabPopup *popup); -void meta_ui_tab_popup_set_showing (MetaTabPopup *popup, - gboolean showing); -void meta_ui_tab_popup_forward (MetaTabPopup *popup); -void meta_ui_tab_popup_backward (MetaTabPopup *popup); -MetaTabEntryKey meta_ui_tab_popup_get_selected (MetaTabPopup *popup); -void meta_ui_tab_popup_select (MetaTabPopup *popup, - MetaTabEntryKey key); - - -#endif - diff --git a/src/include/types.h b/src/include/types.h deleted file mode 100644 index 045b102f..00000000 --- a/src/include/types.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_TYPES_H -#define META_TYPES_H - -typedef struct _MetaCompositor MetaCompositor; -typedef struct _MetaDisplay MetaDisplay; -typedef struct _MetaFrame MetaFrame; -typedef struct _MetaScreen MetaScreen; -typedef struct _MetaWindow MetaWindow; - -#endif diff --git a/src/include/ui.h b/src/include/ui.h deleted file mode 100644 index a4d7fea7..00000000 --- a/src/include/ui.h +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity interface for talking to GTK+ UI module */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_UI_H -#define META_UI_H - -/* Don't include gtk.h or gdk.h here */ -#include "common.h" -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <glib.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -/* This is between GTK_PRIORITY_RESIZE (+10) and GTK_PRIORITY_REDRAW (+20) */ -#define META_PRIORITY_RESIZE (G_PRIORITY_HIGH_IDLE + 15) - -typedef struct _MetaUI MetaUI; - -typedef struct _MetaImageWindow MetaImageWindow; - -typedef gboolean (* MetaEventFunc) (XEvent *xevent, gpointer data); - -typedef enum -{ - META_UI_DIRECTION_LTR, - META_UI_DIRECTION_RTL -} MetaUIDirection; - -void meta_ui_init (int *argc, char ***argv); - -Display* meta_ui_get_display (void); - -void meta_ui_add_event_func (Display *xdisplay, - MetaEventFunc func, - gpointer data); -void meta_ui_remove_event_func (Display *xdisplay, - MetaEventFunc func, - gpointer data); - -MetaUI* meta_ui_new (Display *xdisplay, - Screen *screen); -void meta_ui_free (MetaUI *ui); - -void meta_ui_theme_get_frame_borders (MetaUI *ui, - MetaFrameType type, - MetaFrameFlags flags, - int *top_height, - int *bottom_height, - int *left_width, - int *right_width); -void meta_ui_get_frame_geometry (MetaUI *ui, - Window frame_xwindow, - int *top_height, int *bottom_height, - int *left_width, int *right_width); -Window meta_ui_create_frame_window (MetaUI *ui, - Display *xdisplay, - Visual *xvisual, - gint x, - gint y, - gint width, - gint height, - gint screen_no); -void meta_ui_destroy_frame_window (MetaUI *ui, - Window xwindow); -void meta_ui_move_resize_frame (MetaUI *ui, - Window frame, - int x, - int y, - int width, - int height); - -/* GDK insists on tracking map/unmap */ -void meta_ui_map_frame (MetaUI *ui, - Window xwindow); -void meta_ui_unmap_frame (MetaUI *ui, - Window xwindow); - -void meta_ui_unflicker_frame_bg (MetaUI *ui, - Window xwindow, - int target_width, - int target_height); -void meta_ui_reset_frame_bg (MetaUI *ui, - Window xwindow); - -void meta_ui_apply_frame_shape (MetaUI *ui, - Window xwindow, - int new_window_width, - int new_window_height, - gboolean window_has_shape); - -void meta_ui_queue_frame_draw (MetaUI *ui, - Window xwindow); - -void meta_ui_set_frame_title (MetaUI *ui, - Window xwindow, - const char *title); - -void meta_ui_repaint_frame (MetaUI *ui, - Window xwindow); - -MetaWindowMenu* meta_ui_window_menu_new (MetaUI *ui, - Window client_xwindow, - MetaMenuOp ops, - MetaMenuOp insensitive, - unsigned long active_workspace, - int n_workspaces, - MetaWindowMenuFunc func, - gpointer data); -void meta_ui_window_menu_popup (MetaWindowMenu *menu, - int root_x, - int root_y, - int button, - guint32 timestamp); -void meta_ui_window_menu_free (MetaWindowMenu *menu); - - -MetaImageWindow* meta_image_window_new (Display *xdisplay, - int screen_number, - int max_width, - int max_height); -void meta_image_window_free (MetaImageWindow *iw); -void meta_image_window_set_showing (MetaImageWindow *iw, - gboolean showing); -void meta_image_window_set (MetaImageWindow *iw, - GdkPixbuf *pixbuf, - int x, - int y); - -/* FIXME these lack a display arg */ -GdkPixbuf* meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest, - Window xwindow, - int src_x, - int src_y, - int dest_x, - int dest_y, - int width, - int height); - -GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (GdkPixbuf *dest, - Pixmap xpixmap, - int src_x, - int src_y, - int dest_x, - int dest_y, - int width, - int height); - -/* Used when we have a server grab and draw all over everything, - * then we need to handle exposes after doing that, instead of - * during it - */ -void meta_ui_push_delay_exposes (MetaUI *ui); -void meta_ui_pop_delay_exposes (MetaUI *ui); - -GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui); -GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui); - -gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay, - Window xwindow); - -char* meta_text_property_to_utf8 (Display *xdisplay, - const XTextProperty *prop); - -void meta_ui_set_current_theme (const char *name, - gboolean force_reload); -gboolean meta_ui_have_a_theme (void); - -gboolean meta_ui_parse_accelerator (const char *accel, - unsigned int *keysym, - unsigned int *keycode, - MetaVirtualModifier *mask); -gboolean meta_ui_parse_modifier (const char *accel, - MetaVirtualModifier *mask); - -/* Caller responsible for freeing return string of meta_ui_accelerator_name! */ -gchar* meta_ui_accelerator_name (unsigned int keysym, - MetaVirtualModifier mask); -gboolean meta_ui_window_is_widget (MetaUI *ui, - Window xwindow); - -int meta_ui_get_drag_threshold (MetaUI *ui); - -MetaUIDirection meta_ui_get_direction (void); - -GdkPixbuf *meta_ui_get_pixbuf_from_pixmap (Pixmap pmap); - -#include "tabpopup.h" - -#endif diff --git a/src/include/util.h b/src/include/util.h deleted file mode 100644 index 5041f5ec..00000000 --- a/src/include/util.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity utilities */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_UTIL_H -#define META_UTIL_H - -#include <glib.h> - -gboolean meta_is_verbose (void); -void meta_set_verbose (gboolean setting); -gboolean meta_is_debugging (void); -void meta_set_debugging (gboolean setting); -gboolean meta_is_syncing (void); -void meta_set_syncing (gboolean setting); -gboolean meta_get_replace_current_wm (void); -void meta_set_replace_current_wm (gboolean setting); - -void meta_debug_spew_real (const char *format, - ...) G_GNUC_PRINTF (1, 2); -void meta_verbose_real (const char *format, - ...) G_GNUC_PRINTF (1, 2); - -void meta_bug (const char *format, - ...) G_GNUC_PRINTF (1, 2); -void meta_warning (const char *format, - ...) G_GNUC_PRINTF (1, 2); -void meta_fatal (const char *format, - ...) G_GNUC_PRINTF (1, 2); - -typedef enum -{ - META_DEBUG_FOCUS = 1 << 0, - META_DEBUG_WORKAREA = 1 << 1, - META_DEBUG_STACK = 1 << 2, - META_DEBUG_THEMES = 1 << 3, - META_DEBUG_SM = 1 << 4, - META_DEBUG_EVENTS = 1 << 5, - META_DEBUG_WINDOW_STATE = 1 << 6, - META_DEBUG_WINDOW_OPS = 1 << 7, - META_DEBUG_GEOMETRY = 1 << 8, - META_DEBUG_PLACEMENT = 1 << 9, - META_DEBUG_PING = 1 << 10, - META_DEBUG_XINERAMA = 1 << 11, - META_DEBUG_KEYBINDINGS = 1 << 12, - META_DEBUG_SYNC = 1 << 13, - META_DEBUG_ERRORS = 1 << 14, - META_DEBUG_STARTUP = 1 << 15, - META_DEBUG_PREFS = 1 << 16, - META_DEBUG_GROUPS = 1 << 17, - META_DEBUG_RESIZING = 1 << 18, - META_DEBUG_SHAPES = 1 << 19, - META_DEBUG_COMPOSITOR = 1 << 20, - META_DEBUG_EDGE_RESISTANCE = 1 << 21 -} MetaDebugTopic; - -void meta_topic_real (MetaDebugTopic topic, - const char *format, - ...) G_GNUC_PRINTF (2, 3); - -void meta_push_no_msg_prefix (void); -void meta_pop_no_msg_prefix (void); - -gint meta_unsigned_long_equal (gconstpointer v1, - gconstpointer v2); -guint meta_unsigned_long_hash (gconstpointer v); - -void meta_print_backtrace (void); - -const char* meta_gravity_to_string (int gravity); - -#include <libintl.h> -#define _(x) dgettext (GETTEXT_PACKAGE, x) -#define N_(x) x - -char* meta_g_utf8_strndup (const gchar *src, gsize n); - -void meta_free_gslist_and_elements (GSList *list_to_deep_free); - -void meta_show_dialog (const char *type, - const char *title, - const char *message, - gint timeout, - const char **columns, - const char **entries); - -/* To disable verbose mode, we make these functions into no-ops */ -#ifdef WITH_VERBOSE_MODE - -#define meta_debug_spew meta_debug_spew_real -#define meta_verbose meta_verbose_real -#define meta_topic meta_topic_real - -#else - -# ifdef G_HAVE_ISO_VARARGS -# define meta_debug_spew(...) -# define meta_verbose(...) -# define meta_topic(...) -# elif defined(G_HAVE_GNUC_VARARGS) -# define meta_debug_spew(format...) -# define meta_verbose(format...) -# define meta_topic(format...) -# else -# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" -# endif - -#endif /* !WITH_VERBOSE_MODE */ - -#endif /* META_UTIL_H */ - - diff --git a/src/include/window.h b/src/include/window.h deleted file mode 100644 index 8a338660..00000000 --- a/src/include/window.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WINDOW_H -#define META_WINDOW_H - -#include <glib.h> -#include <X11/Xlib.h> - -#include "boxes.h" -#include "types.h" - -MetaFrame *meta_window_get_frame (MetaWindow *window); -gboolean meta_window_has_focus (MetaWindow *window); -gboolean meta_window_is_shaded (MetaWindow *window); -MetaRectangle *meta_window_get_rect (MetaWindow *window); -MetaScreen *meta_window_get_screen (MetaWindow *window); -MetaDisplay *meta_window_get_display (MetaWindow *window); -Window meta_window_get_xwindow (MetaWindow *window); - -#endif diff --git a/src/include/xprops.h b/src/include/xprops.h deleted file mode 100644 index f5ecb6ac..00000000 --- a/src/include/xprops.h +++ /dev/null @@ -1,227 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity X property convenience routines */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_XPROPS_H -#define META_XPROPS_H - -#include <config.h> - -#include "display.h" -#include <X11/Xutil.h> - -#ifdef HAVE_XSYNC -#include <X11/extensions/sync.h> -#endif - -/* Copied from Lesstif by way of GTK. Rudimentary docs can be - * found in some Motif reference guides online. - */ -typedef struct { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long input_mode; - unsigned long status; -} MotifWmHints, MwmHints; - -#define MWM_HINTS_FUNCTIONS (1L << 0) -#define MWM_HINTS_DECORATIONS (1L << 1) -#define MWM_HINTS_INPUT_MODE (1L << 2) -#define MWM_HINTS_STATUS (1L << 3) - -#define MWM_FUNC_ALL (1L << 0) -#define MWM_FUNC_RESIZE (1L << 1) -#define MWM_FUNC_MOVE (1L << 2) -#define MWM_FUNC_MINIMIZE (1L << 3) -#define MWM_FUNC_MAXIMIZE (1L << 4) -#define MWM_FUNC_CLOSE (1L << 5) - -#define MWM_DECOR_ALL (1L << 0) -#define MWM_DECOR_BORDER (1L << 1) -#define MWM_DECOR_RESIZEH (1L << 2) -#define MWM_DECOR_TITLE (1L << 3) -#define MWM_DECOR_MENU (1L << 4) -#define MWM_DECOR_MINIMIZE (1L << 5) -#define MWM_DECOR_MAXIMIZE (1L << 6) - -#define MWM_INPUT_MODELESS 0 -#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 -#define MWM_INPUT_SYSTEM_MODAL 2 -#define MWM_INPUT_FULL_APPLICATION_MODAL 3 -#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL - -#define MWM_TEAROFF_WINDOW (1L<<0) - -/* These all return the memory from Xlib, so require an XFree() - * when they return TRUE. They return TRUE on success. - */ -gboolean meta_prop_get_atom_list (MetaDisplay *display, - Window xwindow, - Atom xatom, - Atom **atoms_p, - int *n_atoms_p); -gboolean meta_prop_get_motif_hints (MetaDisplay *display, - Window xwindow, - Atom xatom, - MotifWmHints **hints_p); -gboolean meta_prop_get_cardinal_list (MetaDisplay *display, - Window xwindow, - Atom xatom, - gulong **cardinals_p, - int *n_cardinals_p); -gboolean meta_prop_get_latin1_string (MetaDisplay *display, - Window xwindow, - Atom xatom, - char **str_p); -gboolean meta_prop_get_utf8_string (MetaDisplay *display, - Window xwindow, - Atom xatom, - char **str_p); -gboolean meta_prop_get_utf8_list (MetaDisplay *display, - Window xwindow, - Atom xatom, - char ***str_p, - int *n_str_p); -void meta_prop_set_utf8_string_hint - (MetaDisplay *display, - Window xwindow, - Atom atom, - const char *val); -gboolean meta_prop_get_window (MetaDisplay *display, - Window xwindow, - Atom xatom, - Window *window_p); -gboolean meta_prop_get_cardinal (MetaDisplay *display, - Window xwindow, - Atom xatom, - gulong *cardinal_p); -gboolean meta_prop_get_cardinal_with_atom_type (MetaDisplay *display, - Window xwindow, - Atom xatom, - Atom prop_type, - gulong *cardinal_p); -gboolean meta_prop_get_text_property (MetaDisplay *display, - Window xwindow, - Atom xatom, - char **utf8_str_p); - -gboolean meta_prop_get_wm_hints (MetaDisplay *display, - Window xwindow, - Atom xatom, - XWMHints **hints_p); - -gboolean meta_prop_get_class_hint (MetaDisplay *display, - Window xwindow, - Atom xatom, - XClassHint *class_hint); - -gboolean meta_prop_get_size_hints (MetaDisplay *display, - Window xwindow, - Atom xatom, - XSizeHints **hints_p, - gulong *flags_p); - -typedef enum -{ - META_PROP_VALUE_INVALID, - META_PROP_VALUE_UTF8, - META_PROP_VALUE_STRING, - META_PROP_VALUE_STRING_AS_UTF8, - META_PROP_VALUE_MOTIF_HINTS, - META_PROP_VALUE_CARDINAL, - META_PROP_VALUE_WINDOW, - META_PROP_VALUE_CARDINAL_LIST, - META_PROP_VALUE_UTF8_LIST, - META_PROP_VALUE_ATOM_LIST, - META_PROP_VALUE_TEXT_PROPERTY, /* comes back as UTF-8 string */ - META_PROP_VALUE_WM_HINTS, - META_PROP_VALUE_CLASS_HINT, - META_PROP_VALUE_SIZE_HINTS, - META_PROP_VALUE_SYNC_COUNTER /* comes back as CARDINAL */ -} MetaPropValueType; - -/* used to request/return/store property values */ -typedef struct -{ - MetaPropValueType type; - Atom atom; - Atom required_type; /* autofilled if None */ - - union - { - char *str; - MotifWmHints *motif_hints; - Window xwindow; - gulong cardinal; - XWMHints *wm_hints; - XClassHint class_hint; -#ifdef HAVE_XSYNC - XSyncCounter xcounter; -#endif - - struct - { - XSizeHints *hints; - unsigned long flags; - } size_hints; - - struct - { - gulong *cardinals; - int n_cardinals; - } cardinal_list; - - struct - { - char **strings; - int n_strings; - } string_list; - - struct - { - Atom *atoms; - int n_atoms; - } atom_list; - - } v; - -} MetaPropValue; - -/* Each value has type and atom initialized. If there's an error, - * or property is unset, type comes back as INVALID; - * else type comes back as it originated, and the data - * is filled in. - */ -void meta_prop_get_values (MetaDisplay *display, - Window xwindow, - MetaPropValue *values, - int n_values); - -void meta_prop_free_values (MetaPropValue *values, - int n_values); - -#endif - - - - diff --git a/src/libmetacity-private.pc.in b/src/libmetacity-private.pc.in deleted file mode 100644 index 3f034b62..00000000 --- a/src/libmetacity-private.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -libgnome_serverdir=@libexecdir@ - -Name: libmetacity-private -Description: Metacity internals shared -Requires: gtk+-2.0 -Version: @VERSION@ -Libs: -L${libdir} -lmetacity-private -Cflags: -I${includedir}/metacity-1 diff --git a/src/metacity-wm.desktop.in b/src/metacity-wm.desktop.in deleted file mode 100644 index 91b81246..00000000 --- a/src/metacity-wm.desktop.in +++ /dev/null @@ -1,21 +0,0 @@ -[Desktop Entry] -Type=Application -Encoding=UTF-8 -_Name=Metacity -Exec=metacity -# name of loadable control center module -X-GNOME-WMSettingsModule=metacity -# name we put on the WM spec check window -X-GNOME-WMName=Metacity -# back compat only -X-GnomeWMSettingsLibrary=metacity -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=metacity -X-GNOME-Bugzilla-Component=general -X-GNOME-Autostart-Phase=WindowManager -X-GNOME-Provides=windowmanager -X-GNOME-Autostart-Notify=true - -[Window Manager] -SessionManaged=true - diff --git a/src/metacity.desktop.in b/src/metacity.desktop.in deleted file mode 100644 index e6b5d475..00000000 --- a/src/metacity.desktop.in +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -Type=Application -Encoding=UTF-8 -_Name=Metacity -Exec=metacity -NoDisplay=true -# name of loadable control center module -X-GNOME-WMSettingsModule=metacity -# name we put on the WM spec check window -X-GNOME-WMName=Metacity -# back compat only -X-GnomeWMSettingsLibrary=metacity -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=metacity -X-GNOME-Bugzilla-Component=general -X-GNOME-Autostart-Phase=WindowManager -X-GNOME-Provides=windowmanager -X-GNOME-Autostart-Notify=true diff --git a/src/metacity.schemas.in.in b/src/metacity.schemas.in.in deleted file mode 100644 index 41b7c267..00000000 --- a/src/metacity.schemas.in.in +++ /dev/null @@ -1,554 +0,0 @@ -<gconfschemafile> - <schemalist> - - <!-- General preferences --> - - <schema> - <key>/schemas/apps/metacity/general/mouse_button_modifier</key> - <applyto>/apps/metacity/general/mouse_button_modifier</applyto> - <owner>metacity</owner> - <type>string</type> - <default><Alt></default> - <locale name="C"> - <short>Modifier to use for modified window click actions</short> - <long> - Clicking a window while holding down this modifier key - will move the window (left click), resize the window - (middle click), or show the window menu (right click). - Modifier is expressed as "<Alt>" or "<Super>" - for example. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/button_layout</key> - <applyto>/apps/metacity/general/button_layout</applyto> - <owner>metacity</owner> - <type>string</type> - <default>menu:minimize,maximize,close</default> - <locale name="C"> - <short>Arrangement of buttons on the titlebar</short> - <long> - Arrangement of buttons on the titlebar. The - value should be a string, such as - "menu:minimize,maximize,spacer,close"; the colon separates the - left corner of the window from the right corner, and - the button names are comma-separated. Duplicate buttons - are not allowed. Unknown button names are silently ignored - so that buttons can be added in future metacity versions - without breaking older versions. - A special spacer tag can be used to insert some space between - two adjacent buttons. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/focus_mode</key> - <applyto>/apps/metacity/general/focus_mode</applyto> - <owner>metacity</owner> - <type>string</type> - <default>click</default> - <locale name="C"> - <short>Window focus mode</short> - <long> - The window focus mode indicates how windows are activated. - It has three possible values; "click" means windows must - be clicked in order to focus them, "sloppy" means windows - are focused when the mouse enters the window, and "mouse" means - windows are focused when the mouse enters the window and - unfocused when the mouse leaves the window. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/focus_new_windows</key> - <applyto>/apps/metacity/general/focus_new_windows</applyto> - <owner>metacity</owner> - <type>string</type> - <default>smart</default> - <locale name="C"> - <short>Control how new windows get focus</short> - <long> - This option provides additional control over how newly created - windows get focus. It has two possible values; "smart" applies - the user's normal focus mode, and "strict" results in windows - started from a terminal not being given focus. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/raise_on_click</key> - <applyto>/apps/metacity/general/raise_on_click</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>true</default> - <locale name="C"> - <short>Whether raising should be a side-effect of other user - interactions</short> - <long> - Setting this option to false can lead to buggy behavior, so - users are strongly discouraged from changing it from the default - of true. - - Many actions (e.g. clicking in the client area, moving or resizing the window) - normally raise the window as a side-effect. Setting this option to false, which - is strongly discouraged, will decouple raising from other user actions, and - ignore raise requests generated by applications. See - http://bugzilla.gnome.org/show_bug.cgi?id=445447#c6. - Even when this option is false, windows can - still be raised by an alt-left-click anywhere on the window, a - normal click on the window decorations, or by special messages - from pagers, such as activation requests from tasklist applets. - This option is currently disabled in click-to-focus mode. - - Note that the list of ways to raise windows when raise_on_click - is false does not include programmatic requests from - applications to raise windows; such requests will be ignored - regardless of the reason for the request. If you are an - application developer and have a user complaining that your - application does not work with this setting disabled, tell them - it is _their_ fault for breaking their window manager and that - they need to change this option back to true or live with the - "bug" they requested. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/action_double_click_titlebar</key> - <applyto>/apps/metacity/general/action_double_click_titlebar</applyto> - <owner>metacity</owner> - <type>string</type> - <default>toggle_maximize</default> - <locale name="C"> - <short>Action on title bar double-click</short> - <long> - This option determines the effects of double-clicking on the - title bar. Current valid options are - 'toggle_shade', which will shade/unshade the window, - 'toggle_maximize' which will maximize/unmaximize the window, - 'toggle_maximize_horizontally' and 'toggle_maximize_vertically' - which will maximize/unmaximize the window in that direction only, - 'minimize' which will minimize the window, - 'shade' which will roll the window up, - 'menu' which will display the window menu, - 'lower' which will put the window behind all the others, - and 'none' which will not do anything. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/action_middle_click_titlebar</key> - <applyto>/apps/metacity/general/action_middle_click_titlebar</applyto> - <owner>metacity</owner> - <type>string</type> - <default>lower</default> - <locale name="C"> - <short>Action on title bar middle-click</short> - <long> - This option determines the effects of middle-clicking on the - title bar. Current valid options are - 'toggle_shade', which will shade/unshade the window, - 'toggle_maximize' which will maximize/unmaximize the window, - 'toggle_maximize_horizontally' and 'toggle_maximize_vertically' - which will maximize/unmaximize the window in that direction only, - 'minimize' which will minimize the window, - 'shade' which will roll the window up, - 'menu' which will display the window menu, - 'lower' which will put the window behind all the others, - and 'none' which will not do anything. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/action_right_click_titlebar</key> - <applyto>/apps/metacity/general/action_right_click_titlebar</applyto> - <owner>metacity</owner> - <type>string</type> - <default>menu</default> - <locale name="C"> - <short>Action on title bar right-click</short> - <long> - This option determines the effects of right-clicking on the - title bar. Current valid options are - 'toggle_shade', which will shade/unshade the window, - 'toggle_maximize' which will maximize/unmaximize the window, - 'toggle_maximize_horizontally' and 'toggle_maximize_vertically' - which will maximize/unmaximize the window in that direction only, - 'minimize' which will minimize the window, - 'shade' which will roll the window up, - 'menu' which will display the window menu, - 'lower' which will put the window behind all the others, - and 'none' which will not do anything. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/auto_raise</key> - <applyto>/apps/metacity/general/auto_raise</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Automatically raises the focused window</short> - <long> - If set to true, and the focus mode is either "sloppy" or "mouse" - then the focused window will be automatically raised after a - delay specified by the auto_raise_delay key. This is not related - to clicking on a window to raise it, nor to entering a window - during drag-and-drop. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/auto_raise_delay</key> - <applyto>/apps/metacity/general/auto_raise_delay</applyto> - <owner>metacity</owner> - <type>int</type> - <default>500</default> - <locale name="C"> - <short>Delay in milliseconds for the auto raise option</short> - <long> - The time delay before raising a window if auto_raise is set to - true. The delay is given in thousandths of a second. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/theme</key> - <applyto>/apps/metacity/general/theme</applyto> - <owner>metacity</owner> - <type>string</type> - <default>Clearlooks</default> - <locale name="C"> - <short>Current theme</short> - <long> - The theme determines the appearance of window borders, - titlebar, and so forth. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/titlebar_uses_system_font</key> - <applyto>/apps/metacity/general/titlebar_uses_system_font</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Use standard system font in window titles</short> - <long> - If true, ignore the titlebar_font - option, and use the standard application font for window - titles. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/titlebar_font</key> - <applyto>/apps/metacity/general/titlebar_font</applyto> - <owner>metacity</owner> - <type>string</type> - <default>Sans Bold 10</default> - <locale name="C"> - <short>Window title font</short> - <long> - A font description string describing a font for window - titlebars. The size from the description will only be used if the - titlebar_font_size option is set to 0. Also, this option is - disabled if the titlebar_uses_desktop_font option is set to true. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/num_workspaces</key> - <applyto>/apps/metacity/general/num_workspaces</applyto> - <owner>metacity</owner> - <type>int</type> - <default>4</default> - <locale name="C"> - <short>Number of workspaces</short> - <long> - Number of workspaces. Must be more than zero, and has a fixed - maximum to prevent making the desktop unusable by accidentally - asking for too many workspaces. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/visual_bell</key> - <applyto>/apps/metacity/general/visual_bell</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Enable Visual Bell</short> - <long> - Turns on a visual indication when an application or the system - issues a 'bell' or 'beep'; useful for the hard-of-hearing and for - use in noisy environments. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/audible_bell</key> - <applyto>/apps/metacity/general/audible_bell</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>true</default> - <locale name="C"> - <short>System Bell is Audible</short> - <long> - Determines whether applications or the system can generate - audible 'beeps'; may be used in conjunction with 'visual bell' to - allow silent 'beeps'. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/visual_bell_type</key> - <applyto>/apps/metacity/general/visual_bell_type</applyto> - <owner>metacity</owner> - <type>string</type> - <default>fullscreen</default> - <locale name="C"> - <short>Visual Bell Type</short> - <long> - Tells Metacity how to implement the visual indication that the - system bell or another application 'bell' indicator has been - rung. Currently there are two valid values, "fullscreen", which - causes a fullscreen white-black flash, and "frame_flash" which - causes the titlebar of the application which sent the bell signal - to flash. If the application which sent the bell is unknown (as - is usually the case for the default "system beep"), the currently - focused window's titlebar is flashed. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/compositing_manager</key> - <applyto>/apps/metacity/general/compositing_manager</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Compositing Manager</short> - <long> - Determines whether Metacity is a compositing manager. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/workspace_names/name</key> - <applyto>/apps/metacity/workspace_names/name_1</applyto> - <applyto>/apps/metacity/workspace_names/name_2</applyto> - <applyto>/apps/metacity/workspace_names/name_3</applyto> - <applyto>/apps/metacity/workspace_names/name_4</applyto> - <applyto>/apps/metacity/workspace_names/name_5</applyto> - <applyto>/apps/metacity/workspace_names/name_6</applyto> - <applyto>/apps/metacity/workspace_names/name_7</applyto> - <applyto>/apps/metacity/workspace_names/name_8</applyto> - <applyto>/apps/metacity/workspace_names/name_9</applyto> - <applyto>/apps/metacity/workspace_names/name_10</applyto> - <applyto>/apps/metacity/workspace_names/name_11</applyto> - <applyto>/apps/metacity/workspace_names/name_12</applyto> - <applyto>/apps/metacity/workspace_names/name_13</applyto> - <applyto>/apps/metacity/workspace_names/name_14</applyto> - <applyto>/apps/metacity/workspace_names/name_15</applyto> - <applyto>/apps/metacity/workspace_names/name_16</applyto> - <owner>metacity</owner> - <type>string</type> - <default></default> - <locale name="C"> - <short>Name of workspace</short> - <long> - The name of a workspace. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/reduced_resources</key> - <applyto>/apps/metacity/general/reduced_resources</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>If true, trade off usability for less resource usage</short> - <long> - If true, metacity will give the user less feedback by using - wireframes, avoiding animations, or other means. This is a - significant reduction in usability for many users, but may allow - legacy applications to continue working, and may also be a - useful tradeoff for terminal servers. However, the wireframe - feature is disabled when accessibility is on. - </long> - </locale> - </schema> - - <!-- Keybindings --> - - <schema> - <key>/schemas/apps/metacity/global_keybindings/run_command</key> - <applyto>/apps/metacity/global_keybindings/run_command_1</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_2</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_3</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_4</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_5</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_6</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_7</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_8</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_9</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_10</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_11</applyto> - <applyto>/apps/metacity/global_keybindings/run_command_12</applyto> - <owner>metacity</owner> - <type>string</type> - <default>disabled</default> - <locale name="C"> - <short>Run a defined command</short> - <long> - The keybinding that runs the correspondingly-numbered - command in /apps/metacity/keybinding_commands - - The format looks like "<Control>a" or - "<Shift><Alt>F1". - - The parser is fairly liberal and allows lower or upper case, - and also abbreviations such as "<Ctl>" and - "<Ctrl>". If you set the option to the special string - "disabled", then there will be no keybinding for this - action. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/keybinding_commands/command</key> - <applyto>/apps/metacity/keybinding_commands/command_1</applyto> - <applyto>/apps/metacity/keybinding_commands/command_2</applyto> - <applyto>/apps/metacity/keybinding_commands/command_3</applyto> - <applyto>/apps/metacity/keybinding_commands/command_4</applyto> - <applyto>/apps/metacity/keybinding_commands/command_5</applyto> - <applyto>/apps/metacity/keybinding_commands/command_6</applyto> - <applyto>/apps/metacity/keybinding_commands/command_7</applyto> - <applyto>/apps/metacity/keybinding_commands/command_8</applyto> - <applyto>/apps/metacity/keybinding_commands/command_9</applyto> - <applyto>/apps/metacity/keybinding_commands/command_10</applyto> - <applyto>/apps/metacity/keybinding_commands/command_11</applyto> - <applyto>/apps/metacity/keybinding_commands/command_12</applyto> - <owner>metacity</owner> - <type>string</type> - <default> </default> - <locale name="C"> - <short>Commands to run in response to keybindings</short> - <long> - The /apps/metacity/global_keybindings/run_command_N - keys define keybindings that correspond to these commands. - Pressing the keybinding for run_command_N will - execute command_N. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/keybinding_commands/command_screenshot</key> - <applyto>/apps/metacity/keybinding_commands/command_screenshot</applyto> - <owner>metacity</owner> - <type>string</type> - <default>gnome-screenshot</default> - <locale name="C"> - <short>The screenshot command</short> - <long> - The /apps/metacity/global_keybindings/run_command_screenshot - key defines a keybinding which causes the command specified - by this setting to be invoked. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/keybinding_commands/command_window_screenshot</key> - <applyto>/apps/metacity/keybinding_commands/command_window_screenshot</applyto> - <owner>metacity</owner> - <type>string</type> - <default>gnome-screenshot --window</default> - <locale name="C"> - <short>The window screenshot command</short> - <long> - The /apps/metacity/global_keybindings/run_command_window_screenshot - key defines a keybinding which causes the command specified - by this setting to be invoked. - </long> - </locale> - </schema> - - <!-- Schemas below are generated by schema-bindings.c when this file - becomes metacity.schemas.in - --> - <!-- GENERATED --> - - <!-- Not used and/or crackrock --> - - <schema> - <key>/schemas/apps/metacity/general/application_based</key> - <applyto>/apps/metacity/general/application_based</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>(Not implemented) Navigation works in terms of applications not windows</short> - <long> - If true, then Metacity works in terms of applications rather than - windows. The concept is a bit abstract, but in general an - application-based setup is more like the Mac and less like - Windows. When you focus a window in application-based mode, all - the windows in the application will be raised. Also, in - application-based mode, focus clicks are not passed through to - windows in other applications. Application-based mode is, - however, largely unimplemented at the moment. - </long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/metacity/general/disable_workarounds</key> - <applyto>/apps/metacity/general/disable_workarounds</applyto> - <owner>metacity</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Disable misfeatures that are required by old or broken - applications</short> - <long> - Some applications disregard specifications in ways that result in - window manager misfeatures. This option puts Metacity in a - rigorously correct mode, which gives a more consistent user - interface, provided one does not need to run any misbehaving - applications. - </long> - </locale> - </schema> - - </schemalist> -</gconfschemafile> - - - - diff --git a/src/run-metacity.sh b/src/run-metacity.sh deleted file mode 100755 index e0d9265a..00000000 --- a/src/run-metacity.sh +++ /dev/null @@ -1,109 +0,0 @@ -#! /bin/bash - -if test -z "$XNEST_DISPLAY"; then - XNEST_DISPLAY=:8 -fi - -if test -z "$CLIENT_DISPLAY"; then - CLIENT_DISPLAY=:8 -fi - -if test -z "$METACITY_DISPLAY"; then - export METACITY_DISPLAY=$CLIENT_DISPLAY -fi - -if test -z "$SCREENS"; then - SCREENS=1 -fi - -MAX_SCREEN=`echo $SCREENS-1 | bc` - -if test "$DEBUG" = none; then - DEBUG= -elif test -z "$DEBUG"; then - DEBUG= -fi - -if test -z "$CLIENTS"; then - CLIENTS=0 -fi - -if test -z "$SM_CLIENTS"; then - SM_CLIENTS=0 -fi - -if test -n "$EVIL_TEST"; then - TEST_CLIENT='./wm-tester/wm-tester --evil' -fi - -if test -n "$ICON_TEST"; then - TEST_CLIENT='./wm-tester/wm-tester --icon-windows' -fi - -if test -n "$DEMO_TEST"; then - TEST_CLIENT='./tools/metacity-window-demo' -fi - -if test -n "$XINERAMA"; then - XINERAMA_FLAGS='+xinerama' -fi - -export EF_ALLOW_MALLOC_0=1 - -if test -z "$ONLY_WM"; then - echo "Launching Xnest" - Xnest -ac $XNEST_DISPLAY -scrns $SCREENS -geometry 640x480 -bw 15 $XINERAMA_FLAGS & - ## usleep 800000 - sleep 1 - - if test -n "$XMON_DIR"; then - echo "Launching xmond" - $XMON_DIR/xmonui | $XMON_DIR/xmond -server localhost:$XNEST_DISPLAY & - sleep 1 - fi - - if test -n "$XSCOPE_DIR"; then - ## xscope doesn't like to die when it should, it backgrounds itself - killall -9 xscope - killall -9 xscope - echo "Launching xscope" - DISPLAY= $XSCOPE_DIR/xscope -o1 -i28 > xscoped-replies.txt & - export METACITY_DISPLAY=localhost:28 - sleep 1 - fi - - echo "Launching clients" - if test -n "$TEST_CLIENT"; then - for I in `seq 0 $MAX_SCREEN`; do - DISPLAY=$CLIENT_DISPLAY.$I $TEST_CLIENT & - done - fi - - if test $CLIENTS != 0; then - for I in `seq 1 $CLIENTS`; do - echo "Launching xterm $I" - DISPLAY=$CLIENT_DISPLAY xterm -geometry 25x15 & - done - fi - - if test $SM_CLIENTS != 0; then - for I in `seq 1 $SM_CLIENTS`; do - echo "Launching gnome-terminal $I" - DISPLAY=$CLIENT_DISPLAY gnome-terminal --geometry 25x15 & - done - fi - - if test -e ~/.Xmodmap; then - DISPLAY=$CLIENT_DISPLAY xmodmap ~/.Xmodmap - fi - - usleep 50000 - - for I in `seq 0 $MAX_SCREEN`; do - DISPLAY=$CLIENT_DISPLAY.$I xsetroot -solid royalblue3 - done -fi - -if test -z "$ONLY_SETUP"; then - METACITY_VERBOSE=1 METACITY_USE_LOGFILE=1 METACITY_DEBUG_BUTTON_GRABS=1 exec $DEBUG ./metacity $OPTIONS -fi diff --git a/src/stock_delete.png b/src/stock_delete.png Binary files differdeleted file mode 100644 index 429401cb..00000000 --- a/src/stock_delete.png +++ /dev/null diff --git a/src/stock_maximize.png b/src/stock_maximize.png Binary files differdeleted file mode 100644 index 6f108405..00000000 --- a/src/stock_maximize.png +++ /dev/null diff --git a/src/stock_minimize.png b/src/stock_minimize.png Binary files differdeleted file mode 100644 index a22e3c45..00000000 --- a/src/stock_minimize.png +++ /dev/null diff --git a/src/themes/.cvsignore b/src/themes/.cvsignore deleted file mode 100644 index 282522db..00000000 --- a/src/themes/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/src/themes/AgingGorilla/README b/src/themes/AgingGorilla/README deleted file mode 100644 index c275e5ee..00000000 --- a/src/themes/AgingGorilla/README +++ /dev/null @@ -1,7 +0,0 @@ -* Gorilla * - -A metacity theme to accompany Scalable and Unscalable Gorilla nautilus -themes. - -(c) 2001 Jakub 'jimmac' Steiner -Ported by Kenneth Christiansen diff --git a/src/themes/AgingGorilla/active-button.png b/src/themes/AgingGorilla/active-button.png Binary files differdeleted file mode 100644 index 64455b33..00000000 --- a/src/themes/AgingGorilla/active-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/active-close-button.png b/src/themes/AgingGorilla/active-close-button.png Binary files differdeleted file mode 100644 index 1d292165..00000000 --- a/src/themes/AgingGorilla/active-close-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/active-close-menu-icon.png b/src/themes/AgingGorilla/active-close-menu-icon.png Binary files differdeleted file mode 100644 index b77f77ae..00000000 --- a/src/themes/AgingGorilla/active-close-menu-icon.png +++ /dev/null diff --git a/src/themes/AgingGorilla/active-maximize-button.png b/src/themes/AgingGorilla/active-maximize-button.png Binary files differdeleted file mode 100644 index a982e5cb..00000000 --- a/src/themes/AgingGorilla/active-maximize-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/active-maximize-menu-icon.png b/src/themes/AgingGorilla/active-maximize-menu-icon.png Binary files differdeleted file mode 100644 index 02ccc37a..00000000 --- a/src/themes/AgingGorilla/active-maximize-menu-icon.png +++ /dev/null diff --git a/src/themes/AgingGorilla/active-menu-button.png b/src/themes/AgingGorilla/active-menu-button.png Binary files differdeleted file mode 100644 index b55d7078..00000000 --- a/src/themes/AgingGorilla/active-menu-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/active-minimize-button.png b/src/themes/AgingGorilla/active-minimize-button.png Binary files differdeleted file mode 100644 index 4205f4e8..00000000 --- a/src/themes/AgingGorilla/active-minimize-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/active-minimize-menu-icon.png b/src/themes/AgingGorilla/active-minimize-menu-icon.png Binary files differdeleted file mode 100644 index 29276929..00000000 --- a/src/themes/AgingGorilla/active-minimize-menu-icon.png +++ /dev/null diff --git a/src/themes/AgingGorilla/gorilla.xcf.bz2 b/src/themes/AgingGorilla/gorilla.xcf.bz2 Binary files differdeleted file mode 100644 index 89b85651..00000000 --- a/src/themes/AgingGorilla/gorilla.xcf.bz2 +++ /dev/null diff --git a/src/themes/AgingGorilla/inactive-close-button.png b/src/themes/AgingGorilla/inactive-close-button.png Binary files differdeleted file mode 100644 index c566b12f..00000000 --- a/src/themes/AgingGorilla/inactive-close-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/inactive-maximize-button.png b/src/themes/AgingGorilla/inactive-maximize-button.png Binary files differdeleted file mode 100644 index 9c838823..00000000 --- a/src/themes/AgingGorilla/inactive-maximize-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/inactive-menu-button.png b/src/themes/AgingGorilla/inactive-menu-button.png Binary files differdeleted file mode 100644 index b000a378..00000000 --- a/src/themes/AgingGorilla/inactive-menu-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/inactive-minimize-button.png b/src/themes/AgingGorilla/inactive-minimize-button.png Binary files differdeleted file mode 100644 index 4459af4e..00000000 --- a/src/themes/AgingGorilla/inactive-minimize-button.png +++ /dev/null diff --git a/src/themes/AgingGorilla/metacity-theme-1.xml b/src/themes/AgingGorilla/metacity-theme-1.xml deleted file mode 100644 index f4f75eb7..00000000 --- a/src/themes/AgingGorilla/metacity-theme-1.xml +++ /dev/null @@ -1,291 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> -<info> - <name>Gorilla</name> - <author>Kenneth Christiansen <kenneth@gnu.org> Anders Carlsson <andersca@gnu.org></author> - <copyright>Â Ximian, Inc, 2001</copyright> - <date>February 8, 2002</date> - <description>A port of the Gorilla theme by Jacub Steiner</description> -</info> - -<!-- define constants --> -<constant name="IconTitleSpacing" value="2"/> <!-- Space between menu button and title --> -<constant name="ButtonWidth" value="18"/> <!-- Button width --> - -<frame_geometry name="normal"> - <distance name="left_width" value="6"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="6"/> - <distance name="left_titlebar_edge" value="8"/> - <distance name="right_titlebar_edge" value="8"/> - <aspect_ratio name="button" value="1.0"/> - <distance name="title_vertical_pad" value="0"/> - <border name="title_border" left="0" right="0" top="7" bottom="4"/> - <border name="button_border" left="0" right="0" top="9" bottom="0"/> -</frame_geometry> - -<frame_geometry name="border" has_title="false"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="4"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<!-- Buttons --> - -<draw_ops name="title_tile"> - <line color="#494d59" x1="0" y1="0" x2="width" y2="0"/> - <line color="#515961" x1="0" y1="1" x2="width" y2="1"/> -</draw_ops> - -<!-- Inactive style --> -<frame_style name="normal" geometry="normal"> - <piece position="entire_background"> - <draw_ops> - <rectangle color="black" x="1" y="1" width="width - 2" height="height - 2" filled="true"/> - <rectangle color="dark gray" x="3" y="3" width="width - 8" height="height - 7" filled="false"/> - <rectangle color="light gray" x="4" y="4" width="width - 9" height="height - 8" filled="false"/> - <rectangle color="light gray" x="5" y="5" width="width - 11" height="height - 10" filled="false"/> - <rectangle color="white" x="6" y="6" width="width - 13" height="height - 12" filled="false"/> - <rectangle color="gtk:bg[INSENSITIVE]" x="6" y="6" width="width - 12" height="height - 12" filled="true"/> - - <line color="gtk:bg[INSENSITIVE]" x1="1" y1="1" x2="2" y2="2"/> - <line color="gtk:bg[INSENSITIVE]" x1="1" y1="height - 2" x2="1" y2="height"/> - <line color="gtk:bg[INSENSITIVE]" x1="width - 2" y1="1" x2="width - 1" y2="2"/> - <line color="gtk:bg[INSENSITIVE]" x1="width - 1" y1="height - 1" x2="width - 2" y2="height - 2"/> - </draw_ops> - </piece> - - <piece position="title"> - <draw_ops> - <title color="gray" x="IconTitleSpacing" y="0"/> - </draw_ops> - </piece> - - <piece position="titlebar"> - <draw_ops> - <rectangle color="black" x="6" y="6" width="width - 12" height="height - 10" filled="true"/> - <tile name="title_tile" tile_width="width" tile_height="2" x="8" y="8" width="width - 16" height="height - 14"/> - </draw_ops> - </piece> - - <button function="close" state="normal"> - <draw_ops> - <image filename="inactive-close-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="close" state="pressed"> - <draw_ops> - <image filename="inactive-close-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="minimize" state="normal"> - <draw_ops> - <image filename="inactive-minimize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="minimize" state="pressed"> - <draw_ops> - <image filename="inactive-minimize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="maximize" state="normal"> - <draw_ops> - <image filename="inactive-maximize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <image filename="inactive-maximize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="normal"> - <draw_ops> - <image filename="inactive-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="pressed"> - <draw_ops> - <image filename="inactive-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - -</frame_style> - - -<!-- Active (focused) shaded style --> -<frame_style name="normal_shaded" geometry="normal" parent="normal"> - -</frame_style> - -<!-- Active (focused) style --> -<frame_style name="focused" geometry="normal"> - <piece position="entire_background"> - <draw_ops> - <rectangle color="black" x="0" y="0" width="width" height="height" filled="true"/> - <rectangle color="dark gray" x="3" y="3" width="width - 8" height="height - 7" filled="false"/> - <rectangle color="light gray" x="4" y="4" width="width - 9" height="height - 8" filled="false"/> - <rectangle color="light gray" x="5" y="5" width="width - 11" height="height - 10" filled="false"/> - <rectangle color="white" x="6" y="6" width="width - 13" height="height - 12" filled="false"/> - <rectangle color="gtk:bg[NORMAL]" x="6" y="6" width="width - 12" height="height - 12" filled="true"/> - - <line color="gtk:bg[NORMAL]" x1="0" y1="0" x2="1" y2="1"/> - <line color="gtk:bg[NORMAL]" x1="0" y1="height - 1" x2="1" y2="height"/> - <line color="gtk:bg[NORMAL]" x1="width - 1" y1="0" x2="width" y2="1"/> - <line color="gtk:bg[NORMAL]" x1="width" y1="height" x2="width - 1" y2="height - 1"/> - </draw_ops> - </piece> - - <piece position="title"> - <draw_ops> - <title color="white" x="IconTitleSpacing" y="0"/> - </draw_ops> - </piece> - - <piece position="titlebar"> - <draw_ops> - <rectangle color="black" x="6" y="6" width="width - 12" height="height - 10" filled="true"/> - <tile name="title_tile" tile_width="width" tile_height="2" x="8" y="8" width="width - 16" height="height - 14"/> - </draw_ops> - </piece> - - <button function="close" state="normal"> - <draw_ops> - <image filename="active-close-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="close" state="pressed"> - <draw_ops> - <image filename="active-close-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="minimize" state="normal"> - <draw_ops> - <image filename="active-minimize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="minimize" state="pressed"> - <draw_ops> - <image filename="active-minimize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="maximize" state="normal"> - <draw_ops> - <image filename="active-maximize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <image filename="active-maximize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="normal"> - <draw_ops> - <image filename="active-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="pressed"> - <draw_ops> - <image filename="active-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - -</frame_style> - -<!-- Active (focused) shaded style --> -<frame_style name="focused_shaded" geometry="normal" parent="focused"> - -</frame_style> - -<frame_style_set name="normal"> -<frame focus="yes" state="shaded" style="focused_shaded"/> -<frame focus="yes" state="normal" resize="both" style="focused"/> -<frame focus="yes" state="maximized" style="focused"/> -<frame focus="yes" state="maximized_and_shaded" style="focused_shaded"/> -<frame focus="no" state="normal" resize="both" style="normal"/> -<frame focus="no" state="shaded" style="normal_shaded"/> -<frame focus="no" state="maximized" style="normal"/> -<frame focus="no" state="maximized_and_shaded" style="normal_shaded"/> -</frame_style_set> - -<draw_ops name="blank"> -<!-- nothing --> -</draw_ops> - -<frame_style name="border" geometry="border" parent="normal"> - <piece position="title" draw_ops="blank"/> -</frame_style> - -<frame_style_set name="border"> -<frame focus="yes" state="normal" resize="both" style="border"/> -<frame focus="no" state="normal" resize="both" style="border"/> -<frame focus="yes" state="maximized" style="border"/> -<frame focus="no" state="maximized" style="border"/> -<frame focus="yes" state="shaded" style="border"/> -<frame focus="no" state="shaded" style="border"/> -<frame focus="yes" state="maximized_and_shaded" style="border"/> -<frame focus="no" state="maximized_and_shaded" style="border"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="normal"/> -<window type="modal_dialog" style_set="normal"/> -<window type="menu" style_set="normal"/> -<window type="utility" style_set="normal"/> -<window type="border" style_set="border"/> - -<menu_icon function="maximize" state="normal"> - <draw_ops> - <image filename="active-maximize-menu-icon.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - - -<menu_icon function="close" state="normal"> - <draw_ops> - <image filename="active-close-menu-icon.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - -<menu_icon function="minimize" state="normal"> - <draw_ops> - <image filename="active-minimize-menu-icon.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - -<menu_icon function="unmaximize" state="normal"> - <draw_ops> - </draw_ops> -</menu_icon> - -</metacity_theme> diff --git a/src/themes/Atlanta/metacity-theme-1.xml b/src/themes/Atlanta/metacity-theme-1.xml deleted file mode 100644 index 8355f4c3..00000000 --- a/src/themes/Atlanta/metacity-theme-1.xml +++ /dev/null @@ -1,350 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> -<info> - <name>Default</name> - <author>Havoc Pennington <hp@redhat.com></author> - <copyright>Â Havoc Pennington, 2002</copyright> - <date>February 3, 2002</date> - <description>Simple low-overhead default theme that comes with Metacity.</description> -</info> - -<frame_geometry name="normal"> - <distance name="left_width" value="6"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="7"/> - <distance name="left_titlebar_edge" value="6"/> - <distance name="right_titlebar_edge" value="6"/> - <aspect_ratio name="button" value="1.0"/> - <distance name="title_vertical_pad" value="3"/> - <border name="title_border" left="3" right="4" top="4" bottom="3"/> - <border name="button_border" left="0" right="0" top="1" bottom="1"/> -</frame_geometry> - -<!-- strip borders off the normal geometry --> -<frame_geometry name="normal_small_borders" parent="normal"> - <distance name="left_width" value="0"/> - <distance name="right_width" value="0"/> - <distance name="bottom_height" value="0"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> -</frame_geometry> - -<frame_geometry name="utility" title_scale="xx-small"> - <distance name="left_width" value="3"/> - <distance name="right_width" value="3"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="3"/> - <distance name="right_titlebar_edge" value="3"/> - <distance name="button_width" value="11"/> - <distance name="button_height" value="11"/> - <distance name="title_vertical_pad" value="1"/> - <border name="title_border" left="3" right="4" top="3" bottom="3"/> - <border name="button_border" left="0" right="0" top="1" bottom="1"/> -</frame_geometry> - -<frame_geometry name="border" has_title="false"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="4"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<!-- define constants --> -<constant name="ArrowSpacer" value="8"/> -<constant name="MinArrowSize" value="7"/> -<constant name="ButtonIPad" value="6"/> -<constant name="ThickLineWidth" value="3"/> -<constant name="IconTitleSpacing" value="2"/> -<constant name="SpacerWidth" value="6"/> -<constant name="SpacerHeight" value="9"/> -<constant name="SpacerOffset" value="4"/> - -<!-- Buttons --> - -<draw_ops name="button_pressed_bg"> - <gtk_box state="active" shadow="in" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="menu_button"> - <gtk_arrow state="normal" shadow="out" arrow="down" - x="ArrowSpacer `min` (width-MinArrowSize)/2" - y="ArrowSpacer `min` (height-MinArrowSize)/2" - width="(width-(ArrowSpacer*2)) `max` MinArrowSize" - height="(height-(ArrowSpacer*2)) `max` MinArrowSize"/> -</draw_ops> - -<draw_ops name="menu_button_pressed"> - <include name="menu_button"/> -</draw_ops> - -<draw_ops name="minimize_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="height - ButtonIPad - ThickLineWidth + 1" - x2="width - ButtonIPad" - y2="height - ButtonIPad - ThickLineWidth + 1" - width="3"/> <!-- FIXME allow a constant here --> -</draw_ops> - -<draw_ops name="minimize_button_pressed"> - <include name="minimize_button"/> -</draw_ops> - -<draw_ops name="maximize_button"> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="ButtonIPad" y="ButtonIPad" width="width-ButtonIPad*2-1" height="height-ButtonIPad*2-1"/> - <line color="gtk:fg[NORMAL]" width="3" - x1="ButtonIPad" y1="ButtonIPad+1" x2="width-ButtonIPad" y2="ButtonIPad+1"/> -</draw_ops> - -<draw_ops name="maximize_button_pressed"> - <include name="maximize_button"/> -</draw_ops> - -<draw_ops name="mini_window_icon"> - <rectangle color="gtk:bg[NORMAL]" filled="true" - x="0" y="0" width="width-1" height="height-1"/> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="0" width="width-1" height="height-1"/> - <line color="gtk:fg[NORMAL]" width="2" - x1="0" y1="1" x2="width" y2="1"/> -</draw_ops> - -<draw_ops name="restore_button"> - <include name="mini_window_icon" - x="ButtonIPad" y="ButtonIPad" - width="width - 5 - ButtonIPad" - height="height - 5 - ButtonIPad"/> - <include name="mini_window_icon" - x="3 + ButtonIPad" y="3 + ButtonIPad" - width="width - 5 - ButtonIPad" - height="height - 5 - ButtonIPad"/> -</draw_ops> - -<draw_ops name="restore_button_pressed"> - <include name="restore_button"/> -</draw_ops> - -<draw_ops name="close_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="ButtonIPad" - x2="width - ButtonIPad - 1" y2="height - ButtonIPad - 1" - width="1"/> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="height - ButtonIPad - 1" - x2="width - ButtonIPad - 1" y2="ButtonIPad" - width="1"/> -</draw_ops> - -<draw_ops name="close_button_pressed"> - <include name="close_button"/> -</draw_ops> - -<draw_ops name="outer_bevel"> - <rectangle color="gtk:fg[NORMAL]" - x="0" y="0" width="width-1" height="height-1"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="1" y2="height-2"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="width-2" y2="1"/> - <line color="gtk:dark[NORMAL]" - x1="width-2" y1="1" x2="width-2" y2="height-2"/> - <line color="gtk:dark[NORMAL]" - x1="1" y1="height-2" x2="width-2" y2="height-2"/> -</draw_ops> - -<draw_ops name="blank"> -<!-- nothing --> -</draw_ops> - -<draw_ops name="focus_outline"> - <rectangle color="gtk:fg[NORMAL]" - x="left_width-1" y="top_height-1" - width="width-left_width-right_width+1" - height="height-top_height-bottom_height+1"/> -</draw_ops> - -<draw_ops name="focus_background"> - <include name="outer_bevel"/> - <include name="focus_outline"/> -</draw_ops> - -<draw_ops name="background_unfocused"> - <include name="outer_bevel"/> - <include name="focus_outline"/> -</draw_ops> - -<draw_ops name="title_gradient"> - <gradient type="diagonal" x="0" y="0" width="width-SpacerWidth" height="height"> - <color value="blend/gtk:bg[NORMAL]/gtk:bg[SELECTED]/0.6"/> - <color value="gtk:bg[SELECTED]"/> - </gradient> -</draw_ops> - -<draw_ops name="title_spacer"> - <gtk_vline state="normal" x="width+1-SpacerWidth/2" - y1="SpacerOffset" - y2="height - SpacerOffset"/> -</draw_ops> - -<draw_ops name="title_text_focused_with_icon"> - <clip x="0" y="0" width="width-SpacerWidth" height="height"/> - <title color="gtk:fg[SELECTED]" - x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing" - y="((height - title_height) / 2) `max` 0"/> - <icon x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2" - y="(height-mini_icon_height) / 2" - width="mini_icon_width" height="mini_icon_height"/> -</draw_ops> - -<draw_ops name="title_text_focused_no_icon"> - <clip x="0" y="0" width="width-SpacerWidth" height="height"/> - <title color="gtk:fg[SELECTED]" - x="(0 `max` (width-title_width)) / 2" - y="((height - title_height) / 2) `max` 0"/> -</draw_ops> - -<draw_ops name="title_text_with_icon"> - <clip x="0" y="0" width="width-SpacerWidth" height="height"/> - <title color="gtk:fg[NORMAL]" - x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing" - y="((height - title_height) / 2) `max` 0"/> - <icon x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2" - y="(height-mini_icon_height) / 2" - width="mini_icon_width" height="mini_icon_height"/> -</draw_ops> - -<draw_ops name="title_text_no_icon"> - <clip x="0" y="0" width="width-SpacerWidth" height="height"/> - <title color="gtk:fg[NORMAL]" - x="(0 `max` (width-title_width)) / 2" - y="((height - title_height) / 2) `max` 0"/> -</draw_ops> - -<draw_ops name="title_normal"> - <include name="title_spacer"/> - <include name="title_text_with_icon"/> -</draw_ops> - -<draw_ops name="title_focused"> - <include name="title_gradient"/> - <include name="title_spacer"/> - <include name="title_text_focused_with_icon"/> -</draw_ops> - -<draw_ops name="title_utility"> - <include name="title_spacer"/> - <include name="title_text_no_icon"/> -</draw_ops> - -<draw_ops name="title_utility_focused"> - <include name="title_gradient"/> - <include name="title_spacer"/> - <include name="title_text_focused_no_icon"/> -</draw_ops> - -<frame_style name="normal_unfocused" geometry="normal"> - <piece position="entire_background" draw_ops="background_unfocused"/> - <piece position="title" draw_ops="title_normal"/> - - <!-- we don't specify for prelight, so normal is used --> - <button function="left_left_background" state="pressed" draw_ops="button_pressed_bg"/> - <button function="left_middle_background" state="pressed" draw_ops="button_pressed_bg"/> - <button function="left_right_background" state="pressed" draw_ops="button_pressed_bg"/> - <button function="right_left_background" state="pressed" draw_ops="button_pressed_bg"/> - <button function="right_middle_background" state="pressed" draw_ops="button_pressed_bg"/> - <button function="right_right_background" state="pressed" draw_ops="button_pressed_bg"/> - - <button function="close" state="normal" draw_ops="close_button"/> - <button function="close" state="pressed" draw_ops="close_button_pressed"/> - <button function="minimize" state="normal" draw_ops="minimize_button"/> - <button function="minimize" state="pressed" draw_ops="minimize_button_pressed"/> - <button function="maximize" state="normal" draw_ops="maximize_button"/> - <button function="maximize" state="pressed" draw_ops="maximize_button_pressed"/> - <button function="menu" state="normal" draw_ops="menu_button"/> - <button function="menu" state="pressed" draw_ops="menu_button_pressed"/> -</frame_style> - -<frame_style name="normal_focused" geometry="normal" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="focus_background"/> - <piece position="title" draw_ops="title_focused"/> -</frame_style> - -<frame_style name="maximized_unfocused" geometry="normal_small_borders" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="blank"/> - <button function="maximize" state="normal" draw_ops="restore_button"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="maximized_focused" geometry="normal_small_borders" parent="normal_focused"> - <piece position="entire_background" draw_ops="focus_outline"/> - <button function="maximize" state="normal" draw_ops="restore_button"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="utility_unfocused" geometry="utility" parent="normal_unfocused"> - <piece position="title" draw_ops="title_utility"/> -</frame_style> - -<frame_style name="utility_focused" geometry="utility" parent="normal_focused"> - <piece position="title" draw_ops="title_utility_focused"/> -</frame_style> - -<frame_style name="border" geometry="border" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="outer_bevel"/> - <piece position="title" draw_ops="blank"/> -</frame_style> - -<frame_style_set name="normal"> -<frame focus="yes" state="normal" resize="both" style="normal_focused"/> -<frame focus="no" state="normal" resize="both" style="normal_unfocused"/> -<frame focus="yes" state="maximized" style="maximized_focused"/> -<frame focus="no" state="maximized" style="maximized_unfocused"/> -<frame focus="yes" state="shaded" style="normal_focused"/> -<frame focus="no" state="shaded" style="normal_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="maximized_focused"/> -<frame focus="no" state="maximized_and_shaded" style="maximized_unfocused"/> -</frame_style_set> - -<frame_style_set name="utility" parent="normal"> -<frame focus="yes" state="normal" resize="both" style="utility_focused"/> -<frame focus="no" state="normal" resize="both" style="utility_unfocused"/> -<!-- this is a bunch of crack since utility windows shouldn't be maximized --> -<frame focus="yes" state="maximized" style="utility_focused"/> -<frame focus="no" state="maximized" style="utility_unfocused"/> -<frame focus="yes" state="shaded" style="utility_focused"/> -<frame focus="no" state="shaded" style="utility_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="utility_focused"/> -<frame focus="no" state="maximized_and_shaded" style="utility_unfocused"/> -</frame_style_set> - -<frame_style_set name="border"> -<frame focus="yes" state="normal" resize="both" style="border"/> -<frame focus="no" state="normal" resize="both" style="border"/> -<frame focus="yes" state="maximized" style="border"/> -<frame focus="no" state="maximized" style="border"/> -<frame focus="yes" state="shaded" style="border"/> -<frame focus="no" state="shaded" style="border"/> -<frame focus="yes" state="maximized_and_shaded" style="border"/> -<frame focus="no" state="maximized_and_shaded" style="border"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="normal"/> -<window type="modal_dialog" style_set="normal"/> -<window type="menu" style_set="normal"/> -<window type="utility" style_set="utility"/> -<window type="border" style_set="border"/> - -<menu_icon function="close" state="normal" draw_ops="close_button"/> -<menu_icon function="maximize" state="normal" draw_ops="maximize_button"/> -<menu_icon function="unmaximize" state="normal" draw_ops="restore_button"/> -<menu_icon function="minimize" state="normal" draw_ops="minimize_button"/> - -</metacity_theme> diff --git a/src/themes/Bright/metacity-theme-1.xml b/src/themes/Bright/metacity-theme-1.xml deleted file mode 100644 index a55f4462..00000000 --- a/src/themes/Bright/metacity-theme-1.xml +++ /dev/null @@ -1,376 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> -<info> - <name>Bright</name> - <author>Gaute Lindkvist <lindkvis@linpro.no></author> - <copyright>Â Havoc Pennington, 2002 for Atlanta. Â Gaute Lindkvist, 2002 for modifications</copyright> - <date>February 3, 2002</date> - <description>Simple theme based on Havoc Pennington's Atlanta</description> -</info> - -<frame_geometry name="normal"> - <distance name="left_width" value="6"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="7"/> - <distance name="left_titlebar_edge" value="6"/> - <distance name="right_titlebar_edge" value="6"/> - <distance name="button_width" value="15"/> - <distance name="button_height" value="15"/> - <distance name="title_vertical_pad" value="4"/> - <border name="title_border" left="3" right="4" top="4" bottom="3"/> - <border name="button_border" left="1" right="2" top="2" bottom="1"/> -</frame_geometry> - -<!-- strip borders off the normal geometry --> -<frame_geometry name="normal_small_borders" parent="normal"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="5"/> - <distance name="left_titlebar_edge" value="4"/> - <distance name="right_titlebar_edge" value="4"/> -</frame_geometry> - -<frame_geometry name="utility" title_scale="xx-small"> - <distance name="left_width" value="3"/> - <distance name="right_width" value="3"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="3"/> - <distance name="right_titlebar_edge" value="3"/> - <distance name="button_width" value="11"/> - <distance name="button_height" value="11"/> - <distance name="title_vertical_pad" value="1"/> - <border name="title_border" left="3" right="4" top="3" bottom="3"/> - <border name="button_border" left="0" right="0" top="1" bottom="1"/> -</frame_geometry> - -<frame_geometry name="border" has_title="false"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="4"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<!-- define constants --> -<constant name="ArrowWidth" value="7"/> -<constant name="ArrowHeight" value="5"/> -<constant name="ButtonIPad" value="3"/> -<constant name="ThickLineWidth" value="3"/> -<constant name="IconTitleSpacing" value="2"/> -<constant name="SpacerWidth" value="7"/> -<constant name="SpacerHeight" value="11"/> - -<!-- Buttons --> - -<draw_ops name="button_normal_bg"> -<rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="0" width="width-2" height="height-2"/> -<line color="#BBBBBB" - x1="1" - y1="height-1" - x2="width" - y2="height-1" - width="1"/> -<line color="#BBBBBB" - x1="width-1" - y1="1" - x2="width-1" - y2="height-1" - width="1"/> -<rectangle color="gtk:base[NORMAL]" filled="true" - x="1" y="1" width="width-3" height="height-3"/> -</draw_ops> - -<draw_ops name="button_pressed_bg"> - <gtk_box state="active" shadow="in" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="menu_button"> - <clip x="0" y="0" width="width" height="height"/> -<icon x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2" - y="(height-mini_icon_height) / 2" - width="mini_icon_width-1" height="mini_icon_height-1"/> -</draw_ops> - -<draw_ops name="menu_button_normal"> - <include name="menu_button"/> -</draw_ops> -<draw_ops name="menu_button_pressed"> - <include name="menu_button"/> -</draw_ops> - -<draw_ops name="minimize_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="height - ButtonIPad - ThickLineWidth + 1" - x2="width - ButtonIPad-1" - y2="height - ButtonIPad - ThickLineWidth + 1" - width="2"/> <!-- FIXME allow a constant here --> -</draw_ops> - -<draw_ops name="minimize_button_normal"> - <include name="button_normal_bg"/> - <include name="minimize_button"/> -</draw_ops> - -<draw_ops name="minimize_button_pressed"> - <include name="button_pressed_bg"/> - <include name="minimize_button"/> -</draw_ops> - -<draw_ops name="maximize_button"> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="ButtonIPad" y="ButtonIPad" width="width-ButtonIPad*2-2" height="height-ButtonIPad*2-2"/> - <line color="gtk:fg[NORMAL]" width="2" - x1="ButtonIPad" y1="ButtonIPad+1" x2="width-ButtonIPad-1" y2="ButtonIPad+1"/> -</draw_ops> - -<draw_ops name="maximize_button_normal"> - <include name="button_normal_bg"/> - <include name="maximize_button"/> -</draw_ops> - -<draw_ops name="maximize_button_pressed"> - <include name="button_pressed_bg"/> - <include name="maximize_button"/> -</draw_ops> - -<draw_ops name="mini_window_icon"> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="0" width="width-3" height="height-3"/> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="0" width="width-3" height="height-3"/> - <line color="gtk:fg[NORMAL]" width="1" - x1="0" y1="1" x2="width-1" y2="1"/> -</draw_ops> - -<draw_ops name="restore_button"> - <include name="mini_window_icon" - x="ButtonIPad" y="ButtonIPad" - width="width - 5 - ButtonIPad" - height="height - 5 - ButtonIPad"/> - <include name="mini_window_icon" - x="3 + ButtonIPad" y="3 + ButtonIPad" - width="width - 5 - ButtonIPad" - height="height - 5 - ButtonIPad"/> -</draw_ops> - -<draw_ops name="restore_button_normal"> - <include name="button_normal_bg"/> - <include name="restore_button"/> -</draw_ops> - -<draw_ops name="restore_button_pressed"> - <include name="button_pressed_bg"/> - <include name="restore_button"/> -</draw_ops> - -<draw_ops name="close_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="ButtonIPad" - x2="width - ButtonIPad - 2" y2="height - ButtonIPad - 2"/> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="height - ButtonIPad - 2" - x2="width - ButtonIPad - 2" y2="ButtonIPad"/> -</draw_ops> - -<draw_ops name="close_button_normal"> - <include name="button_normal_bg"/> - <include name="close_button"/> -</draw_ops> - -<draw_ops name="close_button_pressed"> - <include name="button_pressed_bg"/> - <include name="close_button"/> -</draw_ops> - -<draw_ops name="outer_bevel"> - <rectangle color="gtk:fg[NORMAL]" - x="0" y="0" width="width-1" height="height-1"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="1" y2="height-2"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="width-2" y2="1"/> - <line color="gtk:dark[NORMAL]" - x1="width-2" y1="1" x2="width-2" y2="height-2"/> - <line color="gtk:dark[NORMAL]" - x1="1" y1="height-2" x2="width-2" y2="height-2"/> -</draw_ops> - -<draw_ops name="blank"> -<!-- nothing --> -</draw_ops> - -<draw_ops name="focus_outline"> - <rectangle color="gtk:fg[NORMAL]" - x="left_width-1" y="top_height-1" - width="width-left_width-right_width+1" - height="height-top_height-bottom_height+1"/> -</draw_ops> - -<draw_ops name="focus_background"> - <include name="outer_bevel"/> - <include name="focus_outline"/> -</draw_ops> - -<draw_ops name="background_unfocused"> - <include name="outer_bevel"/> - <include name="focus_outline"/> -</draw_ops> - -<draw_ops name="title_box"> -<rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="1" width="width-SpacerWidth+3" height="height-2"/> -<line color="#BBBBBB" - x1="2" - y1="height-2" - x2="width-SpacerWidth+2" - y2="height-2" - width="1"/> -<line color="#BBBBBB" - x1="width-5" - y1="2" - x2="width-SpacerWidth+2" - y2="height-2" - width="1"/> -<rectangle color="gtk:bg[SELECTED]" filled="true" - x="1" y="2" width="width-5" height="height-3"/> -</draw_ops> - -<draw_ops name="title_spacer"> - <gtk_vline state="normal" x="width+1-SpacerWidth/2" - y1="(height-SpacerHeight)/2" - y2="height - (height-SpacerHeight)/2"/> -</draw_ops> - -<draw_ops name="title_text_focused_no_icon"> - <clip x="3" y="2" width="width-SpacerWidth-2" height="height-4"/> - <title color="gtk:fg[SELECTED]" - x="(3 `max` (width-title_width)) / 2+2" - y="((height - title_height) / 2) `max` 0"/> -</draw_ops> - -<draw_ops name="title_text_no_icon"> - <clip x="3" y="2" width="width-SpacerWidth-2" height="height-4"/> - <title color="gtk:fg[NORMAL]" - x="(3 `max` (width-title_width)) / 2+2" - y="((height - title_height) / 2) `max` 0"/> -</draw_ops> - -<draw_ops name="title_normal"> - <include name="title_text_no_icon"/> -</draw_ops> - -<draw_ops name="title_focused"> - <include name="title_box"/> - <include name="title_text_focused_no_icon"/> -</draw_ops> - -<draw_ops name="title_utility"> - <include name="title_spacer"/> - <include name="title_text_no_icon"/> -</draw_ops> - -<draw_ops name="title_utility_focused"> - <include name="title_box"/> - <include name="title_spacer"/> - <include name="title_text_focused_no_icon"/> -</draw_ops> - -<frame_style name="normal_unfocused" geometry="normal"> - <piece position="entire_background" draw_ops="background_unfocused"/> - <piece position="title" draw_ops="title_normal"/> - - <!-- we don't specify for prelight, so normal is used --> - <button function="close" state="normal" draw_ops="close_button_normal"/> - <button function="close" state="pressed" draw_ops="close_button_pressed"/> - <button function="minimize" state="normal" draw_ops="minimize_button_normal"/> - <button function="minimize" state="pressed" draw_ops="minimize_button_pressed"/> - <button function="maximize" state="normal" draw_ops="maximize_button_normal"/> - <button function="maximize" state="pressed" draw_ops="maximize_button_pressed"/> - <button function="menu" state="normal" draw_ops="menu_button_normal"/> - <button function="menu" state="pressed" draw_ops="menu_button_pressed"/> -</frame_style> - -<frame_style name="normal_focused" geometry="normal" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="focus_background"/> - <piece position="title" draw_ops="title_focused"/> -</frame_style> - -<frame_style name="maximized_unfocused" geometry="normal_small_borders" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="blank"/> - <button function="maximize" state="normal" draw_ops="restore_button_normal"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="maximized_focused" geometry="normal_small_borders" parent="normal_focused"> - <piece position="entire_background" draw_ops="focus_outline"/> - <button function="maximize" state="normal" draw_ops="restore_button_normal"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="utility_unfocused" geometry="utility" parent="normal_unfocused"> - <piece position="title" draw_ops="title_utility"/> -</frame_style> - -<frame_style name="utility_focused" geometry="utility" parent="normal_focused"> - <piece position="title" draw_ops="title_utility_focused"/> -</frame_style> - -<frame_style name="border" geometry="border" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="outer_bevel"/> - <piece position="title" draw_ops="blank"/> -</frame_style> - -<frame_style_set name="normal"> -<frame focus="yes" state="normal" resize="both" style="normal_focused"/> -<frame focus="no" state="normal" resize="both" style="normal_unfocused"/> -<frame focus="yes" state="maximized" style="maximized_focused"/> -<frame focus="no" state="maximized" style="maximized_unfocused"/> -<frame focus="yes" state="shaded" style="normal_focused"/> -<frame focus="no" state="shaded" style="normal_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="maximized_focused"/> -<frame focus="no" state="maximized_and_shaded" style="maximized_unfocused"/> -</frame_style_set> - -<frame_style_set name="utility" parent="normal"> -<frame focus="yes" state="normal" resize="both" style="utility_focused"/> -<frame focus="no" state="normal" resize="both" style="utility_unfocused"/> -<!-- this is a bunch of crack since utility windows shouldn't be maximized --> -<frame focus="yes" state="maximized" style="utility_focused"/> -<frame focus="no" state="maximized" style="utility_unfocused"/> -<frame focus="yes" state="shaded" style="utility_focused"/> -<frame focus="no" state="shaded" style="utility_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="utility_focused"/> -<frame focus="no" state="maximized_and_shaded" style="utility_unfocused"/> -</frame_style_set> - -<frame_style_set name="border"> -<frame focus="yes" state="normal" resize="both" style="border"/> -<frame focus="no" state="normal" resize="both" style="border"/> -<frame focus="yes" state="maximized" style="border"/> -<frame focus="no" state="maximized" style="border"/> -<frame focus="yes" state="shaded" style="border"/> -<frame focus="no" state="shaded" style="border"/> -<frame focus="yes" state="maximized_and_shaded" style="border"/> -<frame focus="no" state="maximized_and_shaded" style="border"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="normal"/> -<window type="modal_dialog" style_set="normal"/> -<window type="menu" style_set="normal"/> -<window type="utility" style_set="utility"/> -<window type="border" style_set="border"/> - -<menu_icon function="close" state="normal" draw_ops="close_button_normal"/> -<menu_icon function="maximize" state="normal" draw_ops="maximize_button_normal"/> -<menu_icon function="unmaximize" state="normal" draw_ops="restore_button_normal"/> -<menu_icon function="minimize" state="normal" draw_ops="minimize_button_normal"/> - -</metacity_theme> diff --git a/src/themes/Bright/metacity-theme-2.xml b/src/themes/Bright/metacity-theme-2.xml deleted file mode 100644 index 1a43fe16..00000000 --- a/src/themes/Bright/metacity-theme-2.xml +++ /dev/null @@ -1,546 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> -<info> - <name>Bright</name> - <author>Gaute Lindkvist <lindkvis@linpro.no></author> - <copyright>Â Havoc Pennington, 2002 for Atlanta. Â Gaute Lindkvist, 2002 for modifications</copyright> - <date>February 3, 2002</date> - <description>Simple theme based on Havoc Pennington's Atlanta</description> -</info> - -<frame_geometry name="normal"> - <distance name="left_width" value="6"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="7"/> - <distance name="left_titlebar_edge" value="6"/> - <distance name="right_titlebar_edge" value="6"/> - <distance name="button_width" value="15"/> - <distance name="button_height" value="15"/> - <distance name="title_vertical_pad" value="4"/> - <border name="title_border" left="3" right="4" top="4" bottom="3"/> - <border name="button_border" left="1" right="2" top="2" bottom="1"/> -</frame_geometry> - -<!-- strip borders off the normal geometry --> -<frame_geometry name="normal_small_borders" parent="normal"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="5"/> - <distance name="left_titlebar_edge" value="4"/> - <distance name="right_titlebar_edge" value="4"/> -</frame_geometry> - -<frame_geometry name="utility" title_scale="xx-small"> - <distance name="left_width" value="3"/> - <distance name="right_width" value="3"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="3"/> - <distance name="right_titlebar_edge" value="3"/> - <distance name="button_width" value="11"/> - <distance name="button_height" value="11"/> - <distance name="title_vertical_pad" value="1"/> - <border name="title_border" left="3" right="4" top="3" bottom="3"/> - <border name="button_border" left="0" right="0" top="1" bottom="1"/> -</frame_geometry> - -<frame_geometry name="border" has_title="false"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="4"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<!-- define constants --> -<constant name="ArrowWidth" value="7"/> -<constant name="ArrowHeight" value="5"/> -<constant name="ButtonIPad" value="3"/> -<constant name="ThickLineWidth" value="3"/> -<constant name="IconTitleSpacing" value="2"/> -<constant name="SpacerWidth" value="7"/> -<constant name="SpacerHeight" value="11"/> - -<!-- Buttons --> - -<draw_ops name="button_normal_bg"> -<rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="0" width="width-2" height="height-2"/> -<line color="#BBBBBB" - x1="1" - y1="height-1" - x2="width" - y2="height-1" - width="1"/> -<line color="#BBBBBB" - x1="width-1" - y1="1" - x2="width-1" - y2="height-1" - width="1"/> -<rectangle color="gtk:base[NORMAL]" filled="true" - x="1" y="1" width="width-3" height="height-3"/> -</draw_ops> - -<draw_ops name="button_pressed_bg"> - <gtk_box state="active" shadow="in" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="menu_button"> - <clip x="0" y="0" width="width" height="height"/> -<icon x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2" - y="(height-mini_icon_height) / 2" - width="mini_icon_width-1" height="mini_icon_height-1"/> -</draw_ops> - -<draw_ops name="menu_button_normal"> - <include name="menu_button"/> -</draw_ops> -<draw_ops name="menu_button_pressed"> - <include name="menu_button"/> -</draw_ops> - -<draw_ops name="minimize_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="height - ButtonIPad - ThickLineWidth + 1" - x2="width - ButtonIPad-1" - y2="height - ButtonIPad - ThickLineWidth + 1" - width="ThickLineWidth"/> -</draw_ops> - -<draw_ops name="minimize_button_normal"> - <include name="button_normal_bg"/> - <include name="minimize_button"/> -</draw_ops> - -<draw_ops name="minimize_button_pressed"> - <include name="button_pressed_bg"/> - <include name="minimize_button"/> -</draw_ops> - -<draw_ops name="maximize_button"> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="ButtonIPad" y="ButtonIPad" width="width-ButtonIPad*2-2" height="height-ButtonIPad*2-2"/> - <line color="gtk:fg[NORMAL]" width="2" - x1="ButtonIPad" y1="ButtonIPad+1" x2="width-ButtonIPad-1" y2="ButtonIPad+1"/> -</draw_ops> - -<draw_ops name="maximize_button_normal"> - <include name="button_normal_bg"/> - <include name="maximize_button"/> -</draw_ops> - -<draw_ops name="maximize_button_pressed"> - <include name="button_pressed_bg"/> - <include name="maximize_button"/> -</draw_ops> - -<draw_ops name="mini_window_icon"> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="0" width="width-3" height="height-3"/> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="0" width="width-3" height="height-3"/> - <line color="gtk:fg[NORMAL]" width="1" - x1="0" y1="1" x2="width-1" y2="1"/> -</draw_ops> - -<draw_ops name="restore_button"> - <include name="mini_window_icon" - x="ButtonIPad" y="ButtonIPad" - width="width - 5 - ButtonIPad" - height="height - 5 - ButtonIPad"/> - <include name="mini_window_icon" - x="3 + ButtonIPad" y="3 + ButtonIPad" - width="width - 5 - ButtonIPad" - height="height - 5 - ButtonIPad"/> -</draw_ops> - -<draw_ops name="restore_button_normal"> - <include name="button_normal_bg"/> - <include name="restore_button"/> -</draw_ops> - -<draw_ops name="restore_button_pressed"> - <include name="button_pressed_bg"/> - <include name="restore_button"/> -</draw_ops> - -<draw_ops name="close_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="ButtonIPad" - x2="width - ButtonIPad - 2" y2="height - ButtonIPad - 2"/> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="height - ButtonIPad - 2" - x2="width - ButtonIPad - 2" y2="ButtonIPad"/> -</draw_ops> - -<draw_ops name="shade_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="ButtonIPad" - x2="width - ButtonIPad-1" - y2="ButtonIPad" - width="ThickLineWidth"/> -</draw_ops> - -<draw_ops name="unshade_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="ButtonIPad" - x2="width - ButtonIPad-1" - y2="ButtonIPad" - width="ThickLineWidth"/> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="ButtonIPad" - y="ButtonIPad*2" - width="width - ButtonIPad*2-1" - height="height - ButtonIPad*3-1"/> -</draw_ops> - -<draw_ops name="above_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="height/2" - x2="ButtonIPad + 2" - y2="height/2" - width="ThickLineWidth"/> - <line color="gtk:fg[NORMAL]" - x1="width - ButtonIPad-1" - y1="height/2" - x2="width - ButtonIPad-3" - y2="height/2" - width="ThickLineWidth"/> - <line color="gtk:fg[NORMAL]" - x1="width/2-1" - y1="height - ButtonIPad - 2" - x2="width/2+1" - y2="height - ButtonIPad - 2" - width="ThickLineWidth"/> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="ButtonIPad" - x2="width - ButtonIPad-1" - y2="ButtonIPad" - width="ThickLineWidth"/> -</draw_ops> - -<draw_ops name="unabove_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="height/2" - x2="ButtonIPad + 2" - y2="height/2" - width="ThickLineWidth"/> - <line color="gtk:fg[NORMAL]" - x1="width - ButtonIPad-1" - y1="height/2" - x2="width - ButtonIPad-3" - y2="height/2" - width="ThickLineWidth"/> - <line color="gtk:fg[NORMAL]" - x1="width/2-1" - y1="height - ButtonIPad - 2" - x2="width/2+1" - y2="height - ButtonIPad - 2" - width="ThickLineWidth"/> - <line color="gtk:fg[NORMAL]" - x1="width/2-1" - y1="ButtonIPad" - x2="width/2+1" - y2="ButtonIPad" - width="ThickLineWidth"/> -</draw_ops> - -<draw_ops name="stick_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="ButtonIPad" - x2="ButtonIPad" y2="height - ButtonIPad - 2"/> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="height/2-1" - x2="width - ButtonIPad - 2" y2="height/2-1"/> -</draw_ops> - -<draw_ops name="unstick_button"> - <line color="gtk:fg[NORMAL]" - x1="width/2" y1="ButtonIPad" - x2="width/2" y2="height - ButtonIPad - 2"/> - <line color="gtk:fg[NORMAL]" - x1="width/2" y1="height/2-1" - x2="width - ButtonIPad - 2" y2="height/2-1"/> - <line color="gtk:fg[NORMAL]" - x1="width-ButtonIPad-2" y1="height/2-3" - x2="width-ButtonIPad-2" y2="height/2+2"/> -</draw_ops> - -<draw_ops name="close_button_normal"> - <include name="button_normal_bg"/> - <include name="close_button"/> -</draw_ops> - -<draw_ops name="close_button_pressed"> - <include name="button_pressed_bg"/> - <include name="close_button"/> -</draw_ops> - -<draw_ops name="shade_button_normal"> - <include name="button_normal_bg"/> - <include name="shade_button"/> -</draw_ops> - -<draw_ops name="shade_button_pressed"> - <include name="button_pressed_bg"/> - <include name="shade_button"/> -</draw_ops> - -<draw_ops name="unshade_button_normal"> - <include name="button_normal_bg"/> - <include name="unshade_button"/> -</draw_ops> - -<draw_ops name="unshade_button_pressed"> - <include name="button_pressed_bg"/> - <include name="unshade_button"/> -</draw_ops> - -<draw_ops name="above_button_normal"> - <include name="button_normal_bg"/> - <include name="above_button"/> -</draw_ops> - -<draw_ops name="above_button_pressed"> - <include name="button_pressed_bg"/> - <include name="above_button"/> -</draw_ops> - -<draw_ops name="unabove_button_normal"> - <include name="button_normal_bg"/> - <include name="unabove_button"/> -</draw_ops> - -<draw_ops name="unabove_button_pressed"> - <include name="button_pressed_bg"/> - <include name="unabove_button"/> -</draw_ops> - -<draw_ops name="stick_button_normal"> - <include name="button_normal_bg"/> - <include name="stick_button"/> -</draw_ops> - -<draw_ops name="stick_button_pressed"> - <include name="button_pressed_bg"/> - <include name="stick_button"/> -</draw_ops> - -<draw_ops name="unstick_button_normal"> - <include name="button_normal_bg"/> - <include name="unstick_button"/> -</draw_ops> - -<draw_ops name="unstick_button_pressed"> - <include name="button_pressed_bg"/> - <include name="unstick_button"/> -</draw_ops> - -<draw_ops name="outer_bevel"> - <rectangle color="gtk:fg[NORMAL]" - x="0" y="0" width="width-1" height="height-1"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="1" y2="height-2"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="width-2" y2="1"/> - <line color="gtk:dark[NORMAL]" - x1="width-2" y1="1" x2="width-2" y2="height-2"/> - <line color="gtk:dark[NORMAL]" - x1="1" y1="height-2" x2="width-2" y2="height-2"/> -</draw_ops> - -<draw_ops name="blank"> -<!-- nothing --> -</draw_ops> - -<draw_ops name="focus_outline"> - <rectangle color="gtk:fg[NORMAL]" - x="left_width-1" y="top_height-1" - width="width-left_width-right_width+1" - height="height-top_height-bottom_height+1"/> -</draw_ops> - -<draw_ops name="focus_background"> - <include name="outer_bevel"/> - <include name="focus_outline"/> -</draw_ops> - -<draw_ops name="background_unfocused"> - <include name="outer_bevel"/> - <include name="focus_outline"/> -</draw_ops> - -<draw_ops name="title_box"> -<rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="1" width="width-SpacerWidth+3" height="height-2"/> -<line color="#BBBBBB" - x1="2" - y1="height-2" - x2="width-SpacerWidth+2" - y2="height-2" - width="1"/> -<line color="#BBBBBB" - x1="width-5" - y1="2" - x2="width-SpacerWidth+2" - y2="height-2" - width="1"/> -<rectangle color="gtk:bg[SELECTED]" filled="true" - x="1" y="2" width="width-5" height="height-3"/> -</draw_ops> - -<draw_ops name="title_spacer"> - <gtk_vline state="normal" x="width+1-SpacerWidth/2" - y1="(height-SpacerHeight)/2" - y2="height - (height-SpacerHeight)/2"/> -</draw_ops> - -<draw_ops name="title_text_focused_no_icon"> - <clip x="3" y="2" width="width-SpacerWidth-2" height="height-4"/> - <title color="gtk:fg[SELECTED]" - x="(3 `max` (width-title_width)) / 2+2" - y="((height - title_height) / 2) `max` 0"/> -</draw_ops> - -<draw_ops name="title_text_no_icon"> - <clip x="3" y="2" width="width-SpacerWidth-2" height="height-4"/> - <title color="gtk:fg[NORMAL]" - x="(3 `max` (width-title_width)) / 2+2" - y="((height - title_height) / 2) `max` 0"/> -</draw_ops> - -<draw_ops name="title_normal"> - <include name="title_text_no_icon"/> -</draw_ops> - -<draw_ops name="title_focused"> - <include name="title_box"/> - <include name="title_text_focused_no_icon"/> -</draw_ops> - -<draw_ops name="title_utility"> - <include name="title_spacer"/> - <include name="title_text_no_icon"/> -</draw_ops> - -<draw_ops name="title_utility_focused"> - <include name="title_box"/> - <include name="title_spacer"/> - <include name="title_text_focused_no_icon"/> -</draw_ops> - -<frame_style name="normal_unfocused" geometry="normal"> - <piece position="entire_background" draw_ops="background_unfocused"/> - <piece position="title" draw_ops="title_normal"/> - - <!-- we don't specify for prelight, so normal is used --> - <button function="close" state="normal" draw_ops="close_button_normal"/> - <button function="close" state="pressed" draw_ops="close_button_pressed"/> - <button function="minimize" state="normal" draw_ops="minimize_button_normal"/> - <button function="minimize" state="pressed" draw_ops="minimize_button_pressed"/> - <button function="maximize" state="normal" draw_ops="maximize_button_normal"/> - <button function="maximize" state="pressed" draw_ops="maximize_button_pressed"/> - <button function="menu" state="normal" draw_ops="menu_button_normal"/> - <button function="menu" state="pressed" draw_ops="menu_button_pressed"/> - <button function="shade" state="normal" draw_ops="shade_button_normal"/> - <button function="shade" state="pressed" draw_ops="shade_button_pressed"/> - <button function="unshade" state="normal" draw_ops="unshade_button_normal"/> - <button function="unshade" state="pressed" draw_ops="unshade_button_pressed"/> - <button function="above" state="normal" draw_ops="above_button_normal"/> - <button function="above" state="pressed" draw_ops="above_button_pressed"/> - <button function="unabove" state="normal" draw_ops="unabove_button_normal"/> - <button function="unabove" state="pressed" draw_ops="unabove_button_pressed"/> - <button function="stick" state="normal" draw_ops="stick_button_normal"/> - <button function="stick" state="pressed" draw_ops="stick_button_pressed"/> - <button function="unstick" state="normal" draw_ops="unstick_button_normal"/> - <button function="unstick" state="pressed" draw_ops="unstick_button_pressed"/> -</frame_style> - -<frame_style name="normal_focused" geometry="normal" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="focus_background"/> - <piece position="title" draw_ops="title_focused"/> -</frame_style> - -<frame_style name="maximized_unfocused" geometry="normal_small_borders" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="blank"/> - <button function="maximize" state="normal" draw_ops="restore_button_normal"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="maximized_focused" geometry="normal_small_borders" parent="normal_focused"> - <piece position="entire_background" draw_ops="focus_outline"/> - <button function="maximize" state="normal" draw_ops="restore_button_normal"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="utility_unfocused" geometry="utility" parent="normal_unfocused"> - <piece position="title" draw_ops="title_utility"/> -</frame_style> - -<frame_style name="utility_focused" geometry="utility" parent="normal_focused"> - <piece position="title" draw_ops="title_utility_focused"/> -</frame_style> - -<frame_style name="border" geometry="border" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="outer_bevel"/> - <piece position="title" draw_ops="blank"/> -</frame_style> - -<frame_style_set name="normal"> -<frame focus="yes" state="normal" resize="both" style="normal_focused"/> -<frame focus="no" state="normal" resize="both" style="normal_unfocused"/> -<frame focus="yes" state="maximized" style="maximized_focused"/> -<frame focus="no" state="maximized" style="maximized_unfocused"/> -<frame focus="yes" state="shaded" style="normal_focused"/> -<frame focus="no" state="shaded" style="normal_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="maximized_focused"/> -<frame focus="no" state="maximized_and_shaded" style="maximized_unfocused"/> -</frame_style_set> - -<frame_style_set name="utility" parent="normal"> -<frame focus="yes" state="normal" resize="both" style="utility_focused"/> -<frame focus="no" state="normal" resize="both" style="utility_unfocused"/> -<!-- this is a bunch of crack since utility windows shouldn't be maximized --> -<frame focus="yes" state="maximized" style="utility_focused"/> -<frame focus="no" state="maximized" style="utility_unfocused"/> -<frame focus="yes" state="shaded" style="utility_focused"/> -<frame focus="no" state="shaded" style="utility_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="utility_focused"/> -<frame focus="no" state="maximized_and_shaded" style="utility_unfocused"/> -</frame_style_set> - -<frame_style_set name="border"> -<frame focus="yes" state="normal" resize="both" style="border"/> -<frame focus="no" state="normal" resize="both" style="border"/> -<frame focus="yes" state="maximized" style="border"/> -<frame focus="no" state="maximized" style="border"/> -<frame focus="yes" state="shaded" style="border"/> -<frame focus="no" state="shaded" style="border"/> -<frame focus="yes" state="maximized_and_shaded" style="border"/> -<frame focus="no" state="maximized_and_shaded" style="border"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="normal"/> -<window type="modal_dialog" style_set="normal"/> -<window type="menu" style_set="normal"/> -<window type="utility" style_set="utility"/> -<window type="border" style_set="border"/> - -<menu_icon function="close" state="normal" draw_ops="close_button_normal"/> -<menu_icon function="maximize" state="normal" draw_ops="maximize_button_normal"/> -<menu_icon function="unmaximize" state="normal" draw_ops="restore_button_normal"/> -<menu_icon function="minimize" state="normal" draw_ops="minimize_button_normal"/> - -</metacity_theme> diff --git a/src/themes/Crux/active-above-button.png b/src/themes/Crux/active-above-button.png Binary files differdeleted file mode 100644 index 0eec82b8..00000000 --- a/src/themes/Crux/active-above-button.png +++ /dev/null diff --git a/src/themes/Crux/active-border-top-left-border.png b/src/themes/Crux/active-border-top-left-border.png Binary files differdeleted file mode 100644 index 2d61acf5..00000000 --- a/src/themes/Crux/active-border-top-left-border.png +++ /dev/null diff --git a/src/themes/Crux/active-border-top-right-border.png b/src/themes/Crux/active-border-top-right-border.png Binary files differdeleted file mode 100644 index 9797c0fc..00000000 --- a/src/themes/Crux/active-border-top-right-border.png +++ /dev/null diff --git a/src/themes/Crux/active-bottom-left-border.png b/src/themes/Crux/active-bottom-left-border.png Binary files differdeleted file mode 100644 index f22ea1a3..00000000 --- a/src/themes/Crux/active-bottom-left-border.png +++ /dev/null diff --git a/src/themes/Crux/active-bottom-left-corner.png b/src/themes/Crux/active-bottom-left-corner.png Binary files differdeleted file mode 100644 index de8fe868..00000000 --- a/src/themes/Crux/active-bottom-left-corner.png +++ /dev/null diff --git a/src/themes/Crux/active-bottom-mid-left-border.png b/src/themes/Crux/active-bottom-mid-left-border.png Binary files differdeleted file mode 100644 index 7eec69f5..00000000 --- a/src/themes/Crux/active-bottom-mid-left-border.png +++ /dev/null diff --git a/src/themes/Crux/active-bottom-mid-right-border.png b/src/themes/Crux/active-bottom-mid-right-border.png Binary files differdeleted file mode 100644 index 63da8e9d..00000000 --- a/src/themes/Crux/active-bottom-mid-right-border.png +++ /dev/null diff --git a/src/themes/Crux/active-bottom-right-border.png b/src/themes/Crux/active-bottom-right-border.png Binary files differdeleted file mode 100644 index 61a4f560..00000000 --- a/src/themes/Crux/active-bottom-right-border.png +++ /dev/null diff --git a/src/themes/Crux/active-bottom-right-corner.png b/src/themes/Crux/active-bottom-right-corner.png Binary files differdeleted file mode 100644 index 57594466..00000000 --- a/src/themes/Crux/active-bottom-right-corner.png +++ /dev/null diff --git a/src/themes/Crux/active-button-prelight.png b/src/themes/Crux/active-button-prelight.png Binary files differdeleted file mode 100644 index 6da2ae25..00000000 --- a/src/themes/Crux/active-button-prelight.png +++ /dev/null diff --git a/src/themes/Crux/active-button-pressed.png b/src/themes/Crux/active-button-pressed.png Binary files differdeleted file mode 100644 index 4fb94aa4..00000000 --- a/src/themes/Crux/active-button-pressed.png +++ /dev/null diff --git a/src/themes/Crux/active-button.png b/src/themes/Crux/active-button.png Binary files differdeleted file mode 100644 index cd93b8c5..00000000 --- a/src/themes/Crux/active-button.png +++ /dev/null diff --git a/src/themes/Crux/active-close-button.png b/src/themes/Crux/active-close-button.png Binary files differdeleted file mode 100644 index bfbfd142..00000000 --- a/src/themes/Crux/active-close-button.png +++ /dev/null diff --git a/src/themes/Crux/active-left-border.png b/src/themes/Crux/active-left-border.png Binary files differdeleted file mode 100644 index 89b47f42..00000000 --- a/src/themes/Crux/active-left-border.png +++ /dev/null diff --git a/src/themes/Crux/active-left-top-border-shaded.png b/src/themes/Crux/active-left-top-border-shaded.png Binary files differdeleted file mode 100644 index a9e775ac..00000000 --- a/src/themes/Crux/active-left-top-border-shaded.png +++ /dev/null diff --git a/src/themes/Crux/active-left-top-border.png b/src/themes/Crux/active-left-top-border.png Binary files differdeleted file mode 100644 index 24a13ea9..00000000 --- a/src/themes/Crux/active-left-top-border.png +++ /dev/null diff --git a/src/themes/Crux/active-maximize-button.png b/src/themes/Crux/active-maximize-button.png Binary files differdeleted file mode 100644 index 870e2cb6..00000000 --- a/src/themes/Crux/active-maximize-button.png +++ /dev/null diff --git a/src/themes/Crux/active-menu-button-prelight.png b/src/themes/Crux/active-menu-button-prelight.png Binary files differdeleted file mode 100644 index db0a88c8..00000000 --- a/src/themes/Crux/active-menu-button-prelight.png +++ /dev/null diff --git a/src/themes/Crux/active-menu-button-pressed.png b/src/themes/Crux/active-menu-button-pressed.png Binary files differdeleted file mode 100644 index 8ac8201d..00000000 --- a/src/themes/Crux/active-menu-button-pressed.png +++ /dev/null diff --git a/src/themes/Crux/active-menu-button.png b/src/themes/Crux/active-menu-button.png Binary files differdeleted file mode 100644 index de8e1a7b..00000000 --- a/src/themes/Crux/active-menu-button.png +++ /dev/null diff --git a/src/themes/Crux/active-minimize-button.png b/src/themes/Crux/active-minimize-button.png Binary files differdeleted file mode 100644 index ea740ffb..00000000 --- a/src/themes/Crux/active-minimize-button.png +++ /dev/null diff --git a/src/themes/Crux/active-restore-button.png b/src/themes/Crux/active-restore-button.png Binary files differdeleted file mode 100644 index ec7259e3..00000000 --- a/src/themes/Crux/active-restore-button.png +++ /dev/null diff --git a/src/themes/Crux/active-right-border.png b/src/themes/Crux/active-right-border.png Binary files differdeleted file mode 100644 index 2dea03e3..00000000 --- a/src/themes/Crux/active-right-border.png +++ /dev/null diff --git a/src/themes/Crux/active-right-top-border-shaded.png b/src/themes/Crux/active-right-top-border-shaded.png Binary files differdeleted file mode 100644 index cf7ac2ec..00000000 --- a/src/themes/Crux/active-right-top-border-shaded.png +++ /dev/null diff --git a/src/themes/Crux/active-right-top-border.png b/src/themes/Crux/active-right-top-border.png Binary files differdeleted file mode 100644 index eab9cae0..00000000 --- a/src/themes/Crux/active-right-top-border.png +++ /dev/null diff --git a/src/themes/Crux/active-shade-button.png b/src/themes/Crux/active-shade-button.png Binary files differdeleted file mode 100644 index 2c86470e..00000000 --- a/src/themes/Crux/active-shade-button.png +++ /dev/null diff --git a/src/themes/Crux/active-stick-button.png b/src/themes/Crux/active-stick-button.png Binary files differdeleted file mode 100644 index 2bb224c5..00000000 --- a/src/themes/Crux/active-stick-button.png +++ /dev/null diff --git a/src/themes/Crux/active-top-center-left.png b/src/themes/Crux/active-top-center-left.png Binary files differdeleted file mode 100644 index 9d43fc2f..00000000 --- a/src/themes/Crux/active-top-center-left.png +++ /dev/null diff --git a/src/themes/Crux/active-top-center-mid-left.png b/src/themes/Crux/active-top-center-mid-left.png Binary files differdeleted file mode 100644 index 927d50e9..00000000 --- a/src/themes/Crux/active-top-center-mid-left.png +++ /dev/null diff --git a/src/themes/Crux/active-top-center-mid-right.png b/src/themes/Crux/active-top-center-mid-right.png Binary files differdeleted file mode 100644 index 8cea6f6f..00000000 --- a/src/themes/Crux/active-top-center-mid-right.png +++ /dev/null diff --git a/src/themes/Crux/active-top-center-right.png b/src/themes/Crux/active-top-center-right.png Binary files differdeleted file mode 100644 index e471c363..00000000 --- a/src/themes/Crux/active-top-center-right.png +++ /dev/null diff --git a/src/themes/Crux/active-top-left-border.png b/src/themes/Crux/active-top-left-border.png Binary files differdeleted file mode 100644 index fa4a6f54..00000000 --- a/src/themes/Crux/active-top-left-border.png +++ /dev/null diff --git a/src/themes/Crux/active-top-left-corner.png b/src/themes/Crux/active-top-left-corner.png Binary files differdeleted file mode 100644 index 477e46a9..00000000 --- a/src/themes/Crux/active-top-left-corner.png +++ /dev/null diff --git a/src/themes/Crux/active-top-mid-left-border.png b/src/themes/Crux/active-top-mid-left-border.png Binary files differdeleted file mode 100644 index 35a42feb..00000000 --- a/src/themes/Crux/active-top-mid-left-border.png +++ /dev/null diff --git a/src/themes/Crux/active-top-mid-right-border.png b/src/themes/Crux/active-top-mid-right-border.png Binary files differdeleted file mode 100644 index 1fa16504..00000000 --- a/src/themes/Crux/active-top-mid-right-border.png +++ /dev/null diff --git a/src/themes/Crux/active-top-right-border.png b/src/themes/Crux/active-top-right-border.png Binary files differdeleted file mode 100644 index b3f07f2f..00000000 --- a/src/themes/Crux/active-top-right-border.png +++ /dev/null diff --git a/src/themes/Crux/active-top-right-corner.png b/src/themes/Crux/active-top-right-corner.png Binary files differdeleted file mode 100644 index 199a3780..00000000 --- a/src/themes/Crux/active-top-right-corner.png +++ /dev/null diff --git a/src/themes/Crux/active-unabove-button.png b/src/themes/Crux/active-unabove-button.png Binary files differdeleted file mode 100644 index af1104ce..00000000 --- a/src/themes/Crux/active-unabove-button.png +++ /dev/null diff --git a/src/themes/Crux/active-unshade-button.png b/src/themes/Crux/active-unshade-button.png Binary files differdeleted file mode 100644 index ddaf11f5..00000000 --- a/src/themes/Crux/active-unshade-button.png +++ /dev/null diff --git a/src/themes/Crux/active-unstick-button.png b/src/themes/Crux/active-unstick-button.png Binary files differdeleted file mode 100644 index 2936b166..00000000 --- a/src/themes/Crux/active-unstick-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-above-button.png b/src/themes/Crux/inactive-above-button.png Binary files differdeleted file mode 100644 index dd6de031..00000000 --- a/src/themes/Crux/inactive-above-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-border-top-left-border.png b/src/themes/Crux/inactive-border-top-left-border.png Binary files differdeleted file mode 100644 index 0f6a1b88..00000000 --- a/src/themes/Crux/inactive-border-top-left-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-border-top-right-border.png b/src/themes/Crux/inactive-border-top-right-border.png Binary files differdeleted file mode 100644 index 0e37f50b..00000000 --- a/src/themes/Crux/inactive-border-top-right-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-bottom-left-border.png b/src/themes/Crux/inactive-bottom-left-border.png Binary files differdeleted file mode 100644 index ea174d65..00000000 --- a/src/themes/Crux/inactive-bottom-left-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-bottom-left-corner.png b/src/themes/Crux/inactive-bottom-left-corner.png Binary files differdeleted file mode 100644 index f6f43632..00000000 --- a/src/themes/Crux/inactive-bottom-left-corner.png +++ /dev/null diff --git a/src/themes/Crux/inactive-bottom-mid-border.png b/src/themes/Crux/inactive-bottom-mid-border.png Binary files differdeleted file mode 100644 index b24ea233..00000000 --- a/src/themes/Crux/inactive-bottom-mid-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-bottom-right-border.png b/src/themes/Crux/inactive-bottom-right-border.png Binary files differdeleted file mode 100644 index 3302e015..00000000 --- a/src/themes/Crux/inactive-bottom-right-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-bottom-right-corner.png b/src/themes/Crux/inactive-bottom-right-corner.png Binary files differdeleted file mode 100644 index 0fddaac5..00000000 --- a/src/themes/Crux/inactive-bottom-right-corner.png +++ /dev/null diff --git a/src/themes/Crux/inactive-button-prelight.png b/src/themes/Crux/inactive-button-prelight.png Binary files differdeleted file mode 100644 index 070a164e..00000000 --- a/src/themes/Crux/inactive-button-prelight.png +++ /dev/null diff --git a/src/themes/Crux/inactive-button-pressed.png b/src/themes/Crux/inactive-button-pressed.png Binary files differdeleted file mode 100644 index 88f3f8a0..00000000 --- a/src/themes/Crux/inactive-button-pressed.png +++ /dev/null diff --git a/src/themes/Crux/inactive-button.png b/src/themes/Crux/inactive-button.png Binary files differdeleted file mode 100644 index e74564d2..00000000 --- a/src/themes/Crux/inactive-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-close-button.png b/src/themes/Crux/inactive-close-button.png Binary files differdeleted file mode 100644 index 2f9d0a57..00000000 --- a/src/themes/Crux/inactive-close-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-left-border.png b/src/themes/Crux/inactive-left-border.png Binary files differdeleted file mode 100644 index 3f7ad16e..00000000 --- a/src/themes/Crux/inactive-left-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-left-top-border-shaded.png b/src/themes/Crux/inactive-left-top-border-shaded.png Binary files differdeleted file mode 100644 index 177fa41f..00000000 --- a/src/themes/Crux/inactive-left-top-border-shaded.png +++ /dev/null diff --git a/src/themes/Crux/inactive-left-top-border.png b/src/themes/Crux/inactive-left-top-border.png Binary files differdeleted file mode 100644 index 74fa074e..00000000 --- a/src/themes/Crux/inactive-left-top-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-maximize-button.png b/src/themes/Crux/inactive-maximize-button.png Binary files differdeleted file mode 100644 index 73244678..00000000 --- a/src/themes/Crux/inactive-maximize-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-menu-button-prelight.png b/src/themes/Crux/inactive-menu-button-prelight.png Binary files differdeleted file mode 100644 index 8c45a1bb..00000000 --- a/src/themes/Crux/inactive-menu-button-prelight.png +++ /dev/null diff --git a/src/themes/Crux/inactive-menu-button-pressed.png b/src/themes/Crux/inactive-menu-button-pressed.png Binary files differdeleted file mode 100644 index 757ff7c2..00000000 --- a/src/themes/Crux/inactive-menu-button-pressed.png +++ /dev/null diff --git a/src/themes/Crux/inactive-menu-button.png b/src/themes/Crux/inactive-menu-button.png Binary files differdeleted file mode 100644 index 89b2a442..00000000 --- a/src/themes/Crux/inactive-menu-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-minimize-button.png b/src/themes/Crux/inactive-minimize-button.png Binary files differdeleted file mode 100644 index 6cdac563..00000000 --- a/src/themes/Crux/inactive-minimize-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-restore-button.png b/src/themes/Crux/inactive-restore-button.png Binary files differdeleted file mode 100644 index bafa2967..00000000 --- a/src/themes/Crux/inactive-restore-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-right-border.png b/src/themes/Crux/inactive-right-border.png Binary files differdeleted file mode 100644 index 0404cc48..00000000 --- a/src/themes/Crux/inactive-right-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-right-top-border-shaded.png b/src/themes/Crux/inactive-right-top-border-shaded.png Binary files differdeleted file mode 100644 index 92955273..00000000 --- a/src/themes/Crux/inactive-right-top-border-shaded.png +++ /dev/null diff --git a/src/themes/Crux/inactive-right-top-border.png b/src/themes/Crux/inactive-right-top-border.png Binary files differdeleted file mode 100644 index c1882e96..00000000 --- a/src/themes/Crux/inactive-right-top-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-shade-button.png b/src/themes/Crux/inactive-shade-button.png Binary files differdeleted file mode 100644 index 93ff14b2..00000000 --- a/src/themes/Crux/inactive-shade-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-stick-button.png b/src/themes/Crux/inactive-stick-button.png Binary files differdeleted file mode 100644 index 14ffd9ed..00000000 --- a/src/themes/Crux/inactive-stick-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-top-center-left.png b/src/themes/Crux/inactive-top-center-left.png Binary files differdeleted file mode 100644 index eaba4798..00000000 --- a/src/themes/Crux/inactive-top-center-left.png +++ /dev/null diff --git a/src/themes/Crux/inactive-top-center-mid.png b/src/themes/Crux/inactive-top-center-mid.png Binary files differdeleted file mode 100644 index 7346fbc4..00000000 --- a/src/themes/Crux/inactive-top-center-mid.png +++ /dev/null diff --git a/src/themes/Crux/inactive-top-center-right.png b/src/themes/Crux/inactive-top-center-right.png Binary files differdeleted file mode 100644 index 3a2e3a0a..00000000 --- a/src/themes/Crux/inactive-top-center-right.png +++ /dev/null diff --git a/src/themes/Crux/inactive-top-left-border.png b/src/themes/Crux/inactive-top-left-border.png Binary files differdeleted file mode 100644 index 8ebbdca9..00000000 --- a/src/themes/Crux/inactive-top-left-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-top-left-corner.png b/src/themes/Crux/inactive-top-left-corner.png Binary files differdeleted file mode 100644 index 1db17706..00000000 --- a/src/themes/Crux/inactive-top-left-corner.png +++ /dev/null diff --git a/src/themes/Crux/inactive-top-mid-border.png b/src/themes/Crux/inactive-top-mid-border.png Binary files differdeleted file mode 100644 index 0ec3b26a..00000000 --- a/src/themes/Crux/inactive-top-mid-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-top-right-border.png b/src/themes/Crux/inactive-top-right-border.png Binary files differdeleted file mode 100644 index e86fddc7..00000000 --- a/src/themes/Crux/inactive-top-right-border.png +++ /dev/null diff --git a/src/themes/Crux/inactive-top-right-corner.png b/src/themes/Crux/inactive-top-right-corner.png Binary files differdeleted file mode 100644 index 7b13da35..00000000 --- a/src/themes/Crux/inactive-top-right-corner.png +++ /dev/null diff --git a/src/themes/Crux/inactive-unabove-button.png b/src/themes/Crux/inactive-unabove-button.png Binary files differdeleted file mode 100644 index bc1052d9..00000000 --- a/src/themes/Crux/inactive-unabove-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-unshade-button.png b/src/themes/Crux/inactive-unshade-button.png Binary files differdeleted file mode 100644 index 982abeac..00000000 --- a/src/themes/Crux/inactive-unshade-button.png +++ /dev/null diff --git a/src/themes/Crux/inactive-unstick-button.png b/src/themes/Crux/inactive-unstick-button.png Binary files differdeleted file mode 100644 index e4822729..00000000 --- a/src/themes/Crux/inactive-unstick-button.png +++ /dev/null diff --git a/src/themes/Crux/metacity-theme-1.xml b/src/themes/Crux/metacity-theme-1.xml deleted file mode 100644 index a6994561..00000000 --- a/src/themes/Crux/metacity-theme-1.xml +++ /dev/null @@ -1,579 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> -<info> - <name>Crux</name> - <author>Anders Carlsson <andersca@gnu.org></author> - <copyright>Â Eazel Inc, 2000</copyright> - <date>February 6, 2002</date> - <description>A port of the Crux theme by Arlo Rose and John Harper</description> -</info> - -<!-- define constants --> -<constant name="IconTitleSpacing" value="2"/> <!-- Space between menu button and title --> -<constant name="CenterTitlePieceWidth" value="48"/> <!-- Width of center title piece --> -<constant name="ButtonWidth" value="16"/> <!-- Button width --> - -<frame_geometry name="normal"> - <distance name="left_width" value="5"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="6"/> - <distance name="left_titlebar_edge" value="5"/> - <distance name="right_titlebar_edge" value="6"/> - <aspect_ratio name="button" value="1.0"/> - <distance name="title_vertical_pad" value="0"/> - <border name="title_border" left="0" right="0" top="3" bottom="3"/> - <border name="button_border" left="0" right="0" top="3" bottom="3"/> -</frame_geometry> - -<frame_geometry name="border" has_title="false"> - <distance name="left_width" value="5"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="6"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="5"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<!-- Buttons --> - -<draw_ops name="active_button"> - <image filename="active-button.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="active_button_pressed"> - <image filename="active-button-pressed.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="active_button_prelight"> - <image filename="active-button-prelight.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="inactive_button"> - <image filename="inactive-button.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="inactive_button_pressed"> - <image filename="inactive-button-pressed.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="inactive_button_prelight"> - <image filename="inactive-button-prelight.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<!-- Inactive style --> -<frame_style name="normal" geometry="normal"> - <piece position="left_edge"> - <draw_ops> - <image filename="inactive-left-border.png" x="0" y="0" width="object_width" height="height"/> - </draw_ops> - </piece> - - <piece position="right_edge"> - <draw_ops> - <image filename="inactive-right-border.png" x="0" y="0" width="object_width" height="height"/> - </draw_ops> - </piece> - - <piece position="title"> - <draw_ops> - <title color="gtk:fg[SELECTED]" x="IconTitleSpacing" y="0"/> - </draw_ops> - </piece> - - <piece position="titlebar"> - <draw_ops> - - <image filename="inactive-left-top-border.png" - x="0" y="0" width="object_width" height="height"/> - <image filename="inactive-right-top-border.png" - x="width - object_width" y="0" width="object_width" height="height"/> - - <image filename="inactive-top-center-left.png" - x="4" y="0" - width="(left_width + ButtonWidth + IconTitleSpacing + title_width) `min` - (width - right_width - 3 * ButtonWidth - CenterTitlePieceWidth * height / 22 - 3)" - height="height"/> - - <image filename="inactive-top-center-mid.png" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min` (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1" - y="0" width="object_width * height / 22" height="height"/> - - <image filename="inactive-top-center-right.png" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width + CenterTitlePieceWidth * height / 22) `min` (width - 3 * ButtonWidth - right_width)) + 1" - y="0" - width="(width - title_width - left_width - ButtonWidth - IconTitleSpacing - CenterTitlePieceWidth * height / 22 - right_width) `max` (3 * ButtonWidth)" - height="height"/> - - </draw_ops> - </piece> - - <!-- We have to draw the bottom edge in the background piece - because that's the only way we can get the correct window height --> - <piece position="overlay"> - <draw_ops> - <image filename="inactive-bottom-left-corner.png" - x="0" y="height - object_height" width="object_width" height="object_height"/> - <image filename="inactive-bottom-left-border.png" x="5" y="height - object_height" - width="((title_width + height / 2 - 4) `min` (width - object_width - 26))" - height="object_height"/> - <image filename="inactive-bottom-mid-border.png" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="height - object_height" width="object_width" height="object_height"/> - - <image filename="inactive-bottom-right-border.png" - x="((title_width + height / 2 + 32)) + 1" - y="height - object_height" - width="(width - title_width - height / 2 - 32 - 7) `max` 0" - height="object_height"/> - - <image filename="inactive-bottom-right-corner.png" - x="width - object_width" y="height - object_height" width="object_height" height="object_height"/> - - </draw_ops> - </piece> - - <button function="close" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="close" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="close" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-maximize-button.png" x="2" y="2" width="width - 4" height="height - 4"/> - </draw_ops> - </button> - - <button function="maximize" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="menu" state="normal"> - <draw_ops> - <image filename="inactive-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="pressed"> - <draw_ops> - <image filename="inactive-menu-button-pressed.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - <button function="menu" state="prelight"> - <draw_ops> - <image filename="inactive-menu-button-prelight.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> -</frame_style> - -<frame_style name="normal_maximized" parent="normal"> - <button function="maximize" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-restore-button.png" x="2" y="2" width="width - 4" height="height - 4"/> - </draw_ops> - </button> - - <button function="maximize" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - -</frame_style> - -<!-- Active (focused) shaded style --> - <frame_style name="normal_shaded" geometry="normal" parent="normal"> - <piece position="left_titlebar_edge"> - <draw_ops> - <image filename="inactive-left-top-border-shaded.png" x="0" y="3" width="object_width" height="object_height"/> - </draw_ops> - </piece> - <piece position="right_titlebar_edge"> - <draw_ops> - <image filename="inactive-right-top-border-shaded.png" x="width - object_width" y="3" width="object_width" height="object_height"/> - </draw_ops> - </piece> - </frame_style> - - -<!-- Active (focused) style --> -<frame_style name="focused" geometry="normal"> - <piece position="left_edge"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-left-border.png" x="0" y="0" width="object_width" height="height"/> - </draw_ops> - </piece> - - <piece position="right_edge"> - <draw_ops> - <image filename="active-right-border.png" x="0" y="0" width="object_width" height="height"/> - </draw_ops> - </piece> - - <piece position="title"> - <draw_ops> - <title color="gtk:fg[SELECTED]" x="IconTitleSpacing" y="((height - title_height) / 2) `max` 0"/> - </draw_ops> - </piece> - - <piece position="titlebar"> - <draw_ops> - - <image filename="active-left-top-border.png" - colorize="gtk:bg[SELECTED]" - x="0" y="0" width="object_width" height="height"/> - - <image filename="active-right-top-border.png" - x="width - object_width" y="0" width="object_width" height="height"/> - - <image filename="active-top-center-left.png" - colorize="gtk:bg[SELECTED]" - x="4" y="0" - width="(left_width + ButtonWidth + IconTitleSpacing + title_width) `min` - (width - right_width - 3 * ButtonWidth - CenterTitlePieceWidth * height / 22 - 3)" - height="height"/> - - <image filename="active-top-center-mid-left.png" - colorize="gtk:bg[SELECTED]" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min` (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1" - y="0" width="object_width * height / 22" height="height"/> - - <image filename="active-top-center-mid-right.png" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min` (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1" - y="0" width="object_width * height / 22" height="height"/> - - <image filename="active-top-center-right.png" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width + CenterTitlePieceWidth * height / 22) `min` (width - 3 * ButtonWidth - right_width)) + 1" - y="0" - width="(width - title_width - left_width - ButtonWidth - IconTitleSpacing - CenterTitlePieceWidth * height / 22 - right_width) `max` (3 * ButtonWidth)" - height="height"/> - - </draw_ops> - </piece> - - <!-- We have to draw the bottom edge in the background piece - because that's the only way we can get the correct window height --> - <piece position="overlay"> - <draw_ops> - <image filename="active-bottom-left-corner.png" - colorize="gtk:bg[SELECTED]" - x="0" y="height - object_height" width="object_width" height="object_height"/> - <image filename="active-bottom-left-border.png" x="5" y="height - object_height" - colorize="gtk:bg[SELECTED]" - width="((title_width + height / 2 - 4) `min` (width - object_width - 26))" - height="object_height"/> - <image filename="active-bottom-mid-left-border.png" - colorize="gtk:bg[SELECTED]" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="height - object_height" width="object_width" height="object_height"/> - <image filename="active-bottom-mid-right-border.png" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="height - object_height" width="object_width" height="object_height"/> - - <image filename="active-bottom-right-border.png" - x="((title_width + height / 2 + 32)) + 1" - y="height - object_height" - width="(width - title_width - height / 2 - 32 - 7) `max` 0" - height="object_height"/> - - <image filename="active-bottom-right-corner.png" - x="width - object_width" y="height - object_height" width="object_height" height="object_height"/> - - </draw_ops> - </piece> - - <button function="close" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="close" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="close" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="menu" state="normal"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="pressed"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-menu-button-pressed.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - <button function="menu" state="prelight"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-menu-button-prelight.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> -</frame_style> - -<frame_style name="focused_maximized" geometry="normal" parent="focused"> - <button function="maximize" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - -</frame_style> - -<!-- Active (focused) shaded style --> -<frame_style name="focused_shaded" geometry="normal" parent="focused"> - <piece position="left_titlebar_edge"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-left-top-border-shaded.png" x="0" y="3" width="object_width" height="object_height"/> - </draw_ops> - </piece> - <piece position="right_titlebar_edge"> - <draw_ops> - <image filename="active-right-top-border-shaded.png" x="width - object_width" y="3" width="object_width" height="object_height"/> - </draw_ops> - </piece> -</frame_style> - -<!-- Inactive border style --> -<frame_style name="border_unfocused" geometry="border" parent="normal"> - <piece position="title"><draw_ops/></piece> - <piece position="titlebar"> - <draw_ops> - <image filename="inactive-top-left-corner.png" - x="0" y="0" width="object_width" height="object_height"/> - <image filename="inactive-border-top-left-border.png" x="5" y="0" - width="((title_width + height / 2 - 4) `min` (width - object_width - 26))" - height="object_height"/> - <image filename="inactive-top-mid-border.png" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="0" width="object_width" height="object_height"/> - <image filename="inactive-border-top-right-border.png" - x="((title_width + height / 2 + 32)) + 1" - y="0" - width="(width - title_width - height / 2 - 32 - 7) `max` 0" - height="object_height"/> - <image filename="inactive-top-right-corner.png" - x="width - object_width" y="0" width="object_height" height="object_height"/> - </draw_ops> - </piece> -</frame_style> - -<!-- Active (focused) border style --> -<frame_style name="border_focused" geometry="border" parent="focused"> - <piece position="title"><draw_ops/></piece> - <piece position="titlebar"> - <draw_ops> - <image filename="active-top-left-corner.png" - colorize="gtk:bg[SELECTED]" - x="0" y="0" width="object_width" height="object_height"/> - <image filename="active-border-top-left-border.png" - colorize="gtk:bg[SELECTED]" x="5" y="0" - width="((title_width + height / 2 - 4) `min` (width - object_width - 26))" - height="object_height"/> - <image filename="active-top-mid-left-border.png" - colorize="gtk:bg[SELECTED]" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="0" width="object_width" height="object_height"/> - <image filename="active-top-mid-right-border.png" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="0" width="object_width" height="object_height"/> - <image filename="active-border-top-right-border.png" - x="((title_width + height / 2 + 32)) + 1" y="0" - width="(width - title_width - height / 2 - 32 - 7) `max` 0" - height="object_height"/> - <image filename="active-top-right-corner.png" - x="width - object_width" y="0" width="object_height" height="object_height"/> - </draw_ops> - </piece> -</frame_style> - -<frame_style_set name="normal"> -<frame focus="yes" state="shaded" style="focused_shaded"/> -<frame focus="yes" state="normal" resize="both" style="focused"/> -<frame focus="yes" state="maximized" style="focused_maximized"/> -<frame focus="yes" state="maximized_and_shaded" style="focused_maximized"/> -<frame focus="no" state="normal" resize="both" style="normal"/> -<frame focus="no" state="shaded" style="normal_shaded"/> -<frame focus="no" state="maximized" style="normal_maximized"/> -<frame focus="no" state="maximized_and_shaded" style="normal_maximized"/> -</frame_style_set> - -<frame_style_set name="border"> -<frame focus="yes" state="normal" resize="both" style="border_focused"/> -<frame focus="yes" state="maximized" style="border_focused"/> -<frame focus="yes" state="shaded" style="border_focused"/> -<frame focus="yes" state="maximized_and_shaded" style="border_focused"/> -<frame focus="no" state="normal" resize="both" style="border_unfocused"/> -<frame focus="no" state="maximized" style="border_unfocused"/> -<frame focus="no" state="shaded" style="border_unfocused"/> -<frame focus="no" state="maximized_and_shaded" style="border_unfocused"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="normal"/> -<window type="modal_dialog" style_set="normal"/> -<window type="menu" style_set="normal"/> -<window type="utility" style_set="normal"/> -<window type="border" style_set="border"/> - -<menu_icon function="close" state="normal"> - <draw_ops> - <image filename="active-close-button.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - -<menu_icon function="maximize" state="normal"> - <draw_ops> - <image filename="active-maximize-button.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - - -<menu_icon function="minimize" state="normal"> - <draw_ops> - <image filename="active-minimize-button.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - -<menu_icon function="unmaximize" state="normal"> - <draw_ops> - </draw_ops> -</menu_icon> - -</metacity_theme> diff --git a/src/themes/Crux/metacity-theme-2.xml b/src/themes/Crux/metacity-theme-2.xml deleted file mode 100644 index 11820d3f..00000000 --- a/src/themes/Crux/metacity-theme-2.xml +++ /dev/null @@ -1,832 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> -<info> - <name>Crux</name> - <author>Anders Carlsson <andersca@gnu.org></author> - <copyright>Â Eazel Inc, 2000</copyright> - <date>February 6, 2002</date> - <description>A port of the Crux theme by Arlo Rose and John Harper</description> -</info> - -<!-- define constants --> -<constant name="IconTitleSpacing" value="2"/> <!-- Space between menu button and title --> -<constant name="CenterTitlePieceWidth" value="48"/> <!-- Width of center title piece --> -<constant name="ButtonWidth" value="16"/> <!-- Button width --> - -<frame_geometry name="normal"> - <distance name="left_width" value="5"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="6"/> - <distance name="left_titlebar_edge" value="5"/> - <distance name="right_titlebar_edge" value="6"/> - <aspect_ratio name="button" value="1.0"/> - <distance name="title_vertical_pad" value="0"/> - <border name="title_border" left="0" right="0" top="3" bottom="3"/> - <border name="button_border" left="0" right="0" top="3" bottom="3"/> -</frame_geometry> - -<frame_geometry name="border" has_title="false"> - <distance name="left_width" value="5"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="6"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="5"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<!-- Buttons --> - -<draw_ops name="active_button"> - <image filename="active-button.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="active_button_pressed"> - <image filename="active-button-pressed.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="active_button_prelight"> - <image filename="active-button-prelight.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="inactive_button"> - <image filename="inactive-button.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="inactive_button_pressed"> - <image filename="inactive-button-pressed.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<draw_ops name="inactive_button_prelight"> - <image filename="inactive-button-prelight.png" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<!-- Inactive style --> -<frame_style name="normal" geometry="normal"> - <piece position="left_edge"> - <draw_ops> - <image filename="inactive-left-border.png" x="0" y="0" width="object_width" height="height"/> - </draw_ops> - </piece> - - <piece position="right_edge"> - <draw_ops> - <image filename="inactive-right-border.png" x="0" y="0" width="object_width" height="height"/> - </draw_ops> - </piece> - - <piece position="title"> - <draw_ops> - <title color="gtk:fg[SELECTED]" x="IconTitleSpacing" y="0"/> - </draw_ops> - </piece> - - <piece position="titlebar"> - <draw_ops> - - <image filename="inactive-left-top-border.png" - x="0" y="0" width="object_width" height="height"/> - <image filename="inactive-right-top-border.png" - x="width - object_width" y="0" width="object_width" height="height"/> - - <image filename="inactive-top-center-left.png" - x="4" y="0" - width="(left_width + ButtonWidth + IconTitleSpacing + title_width) `min` - (width - right_width - 3 * ButtonWidth - CenterTitlePieceWidth * height / 22 - 3)" - height="height"/> - - <image filename="inactive-top-center-mid.png" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min` (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1" - y="0" width="object_width * height / 22" height="height"/> - - <image filename="inactive-top-center-right.png" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width + CenterTitlePieceWidth * height / 22) `min` (width - 3 * ButtonWidth - right_width)) + 1" - y="0" - width="(width - title_width - left_width - ButtonWidth - IconTitleSpacing - CenterTitlePieceWidth * height / 22 - right_width) `max` (3 * ButtonWidth)" - height="height"/> - - </draw_ops> - </piece> - - <!-- We have to draw the bottom edge in the background piece - because that's the only way we can get the correct window height --> - <piece position="overlay"> - <draw_ops> - <image filename="inactive-bottom-left-corner.png" - x="0" y="height - object_height" width="object_width" height="object_height"/> - <image filename="inactive-bottom-left-border.png" x="5" y="height - object_height" - width="((title_width + height / 2 - 4) `min` (width - object_width - 26))" - height="object_height"/> - <image filename="inactive-bottom-mid-border.png" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="height - object_height" width="object_width" height="object_height"/> - - <image filename="inactive-bottom-right-border.png" - x="((title_width + height / 2 + 32)) + 1" - y="height - object_height" - width="(width - title_width - height / 2 - 32 - 7) `max` 0" - height="object_height"/> - - <image filename="inactive-bottom-right-corner.png" - x="width - object_width" y="height - object_height" width="object_height" height="object_height"/> - - </draw_ops> - </piece> - - <button function="close" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="close" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="close" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-maximize-button.png" x="2" y="2" width="width - 4" height="height - 4"/> - </draw_ops> - </button> - - <button function="maximize" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unshade" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-unshade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unshade" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-unshade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unshade" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-unshade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="shade" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-shade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="shade" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-shade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="shade" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-shade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unabove" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-unabove-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unabove" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-unabove-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unabove" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-unabove-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="above" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-above-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="above" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-above-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="above" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-above-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="stick" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-stick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="stick" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-stick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="stick" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-stick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unstick" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-unstick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unstick" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-unstick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unstick" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-unstick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="menu" state="normal"> - <draw_ops> - <image filename="inactive-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="pressed"> - <draw_ops> - <image filename="inactive-menu-button-pressed.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="prelight"> - <draw_ops> - <image filename="inactive-menu-button-prelight.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> -</frame_style> - -<frame_style name="normal_maximized" parent="normal"> - <button function="maximize" state="normal"> - <draw_ops> - <include name="inactive_button"/> - <image filename="inactive-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <include name="inactive_button_pressed"/> - <image filename="inactive-restore-button.png" x="2" y="2" width="width - 4" height="height - 4"/> - </draw_ops> - </button> - - <button function="maximize" state="prelight"> - <draw_ops> - <include name="inactive_button_prelight"/> - <image filename="inactive-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - -</frame_style> - -<!-- Active (focused) shaded style --> - <frame_style name="normal_shaded" geometry="normal" parent="normal"> - <piece position="left_titlebar_edge"> - <draw_ops> - <image filename="inactive-left-top-border-shaded.png" x="0" y="3" width="object_width" height="object_height"/> - </draw_ops> - </piece> - <piece position="right_titlebar_edge"> - <draw_ops> - <image filename="inactive-right-top-border-shaded.png" x="width - object_width" y="3" width="object_width" height="object_height"/> - </draw_ops> - </piece> - </frame_style> - - -<!-- Active (focused) style --> -<frame_style name="focused" geometry="normal"> - <piece position="left_edge"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-left-border.png" x="0" y="0" width="object_width" height="height"/> - </draw_ops> - </piece> - - <piece position="right_edge"> - <draw_ops> - <image filename="active-right-border.png" x="0" y="0" width="object_width" height="height"/> - </draw_ops> - </piece> - - <piece position="title"> - <draw_ops> - <title color="gtk:fg[SELECTED]" x="IconTitleSpacing" y="((height - title_height) / 2) `max` 0"/> - </draw_ops> - </piece> - - <piece position="titlebar"> - <draw_ops> - - <image filename="active-left-top-border.png" - colorize="gtk:bg[SELECTED]" - x="0" y="0" width="object_width" height="height"/> - - <image filename="active-right-top-border.png" - x="width - object_width" y="0" width="object_width" height="height"/> - - <image filename="active-top-center-left.png" - colorize="gtk:bg[SELECTED]" - x="4" y="0" - width="(left_width + ButtonWidth + IconTitleSpacing + title_width) `min` - (width - right_width - 3 * ButtonWidth - CenterTitlePieceWidth * height / 22 - 3)" - height="height"/> - - <image filename="active-top-center-mid-left.png" - colorize="gtk:bg[SELECTED]" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min` (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1" - y="0" width="object_width * height / 22" height="height"/> - - <image filename="active-top-center-mid-right.png" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width) `min` (width - object_width * height / 22 - right_width - 3 * ButtonWidth)) + 1" - y="0" width="object_width * height / 22" height="height"/> - - <image filename="active-top-center-right.png" - x="((left_width + ButtonWidth + IconTitleSpacing + title_width + CenterTitlePieceWidth * height / 22) `min` (width - 3 * ButtonWidth - right_width)) + 1" - y="0" - width="(width - title_width - left_width - ButtonWidth - IconTitleSpacing - CenterTitlePieceWidth * height / 22 - right_width) `max` (3 * ButtonWidth)" - height="height"/> - - </draw_ops> - </piece> - - <!-- We have to draw the bottom edge in the background piece - because that's the only way we can get the correct window height --> - <piece position="overlay"> - <draw_ops> - <image filename="active-bottom-left-corner.png" - colorize="gtk:bg[SELECTED]" - x="0" y="height - object_height" width="object_width" height="object_height"/> - <image filename="active-bottom-left-border.png" x="5" y="height - object_height" - colorize="gtk:bg[SELECTED]" - width="((title_width + height / 2 - 4) `min` (width - object_width - 26))" - height="object_height"/> - <image filename="active-bottom-mid-left-border.png" - colorize="gtk:bg[SELECTED]" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="height - object_height" width="object_width" height="object_height"/> - <image filename="active-bottom-mid-right-border.png" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="height - object_height" width="object_width" height="object_height"/> - - <image filename="active-bottom-right-border.png" - x="((title_width + height / 2 + 32)) + 1" - y="height - object_height" - width="(width - title_width - height / 2 - 32 - 7) `max` 0" - height="object_height"/> - - <image filename="active-bottom-right-corner.png" - x="width - object_width" y="height - object_height" width="object_height" height="object_height"/> - - </draw_ops> - </piece> - - <button function="close" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="close" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="close" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-close-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="minimize" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-minimize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-maximize-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="shade" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-shade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="shade" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-shade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="shade" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-shade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unshade" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-unshade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unshade" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-unshade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unshade" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-unshade-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="above" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-above-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="above" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-above-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="above" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-above-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unabove" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-unabove-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unabove" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-unabove-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unabove" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-unabove-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="stick" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-stick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="stick" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-stick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="stick" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-stick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unstick" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-unstick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unstick" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-unstick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="unstick" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-unstick-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="menu" state="normal"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="pressed"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-menu-button-pressed.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - <button function="menu" state="prelight"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-menu-button-prelight.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> -</frame_style> - -<frame_style name="focused_maximized" geometry="normal" parent="focused"> - <button function="maximize" state="normal"> - <draw_ops> - <include name="active_button"/> - <image filename="active-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <include name="active_button_pressed"/> - <image filename="active-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - - <button function="maximize" state="prelight"> - <draw_ops> - <include name="active_button_prelight"/> - <image filename="active-restore-button.png" x="2" y="2" width="width-4" height="height-4"/> - </draw_ops> - </button> - -</frame_style> - -<!-- Active (focused) shaded style --> -<frame_style name="focused_shaded" geometry="normal" parent="focused"> - <piece position="left_titlebar_edge"> - <draw_ops> - <image colorize="gtk:bg[SELECTED]" filename="active-left-top-border-shaded.png" x="0" y="3" width="object_width" height="object_height"/> - </draw_ops> - </piece> - <piece position="right_titlebar_edge"> - <draw_ops> - <image filename="active-right-top-border-shaded.png" x="width - object_width" y="3" width="object_width" height="object_height"/> - </draw_ops> - </piece> -</frame_style> - -<!-- Inactive border style --> -<frame_style name="border_unfocused" geometry="border" parent="normal"> - <piece position="title"><draw_ops/></piece> - <piece position="titlebar"> - <draw_ops> - <image filename="inactive-top-left-corner.png" - x="0" y="0" width="object_width" height="object_height"/> - <image filename="inactive-border-top-left-border.png" x="5" y="0" - width="((title_width + height / 2 - 4) `min` (width - object_width - 26))" - height="object_height"/> - <image filename="inactive-top-mid-border.png" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="0" width="object_width" height="object_height"/> - <image filename="inactive-border-top-right-border.png" - x="((title_width + height / 2 + 32)) + 1" - y="0" - width="(width - title_width - height / 2 - 32 - 7) `max` 0" - height="object_height"/> - <image filename="inactive-top-right-corner.png" - x="width - object_width" y="0" width="object_height" height="object_height"/> - </draw_ops> - </piece> -</frame_style> - -<!-- Active (focused) border style --> -<frame_style name="border_focused" geometry="border" parent="focused"> - <piece position="title"><draw_ops/></piece> - <piece position="titlebar"> - <draw_ops> - <image filename="active-top-left-corner.png" - colorize="gtk:bg[SELECTED]" - x="0" y="0" width="object_width" height="object_height"/> - <image filename="active-border-top-left-border.png" - colorize="gtk:bg[SELECTED]" x="5" y="0" - width="((title_width + height / 2 - 4) `min` (width - object_width - 26))" - height="object_height"/> - <image filename="active-top-mid-left-border.png" - colorize="gtk:bg[SELECTED]" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="0" width="object_width" height="object_height"/> - <image filename="active-top-mid-right-border.png" - x="((title_width + height / 2) `min` (width - object_width - 6)) + 1" - y="0" width="object_width" height="object_height"/> - <image filename="active-border-top-right-border.png" - x="((title_width + height / 2 + 32)) + 1" y="0" - width="(width - title_width - height / 2 - 32 - 7) `max` 0" - height="object_height"/> - <image filename="active-top-right-corner.png" - x="width - object_width" y="0" width="object_height" height="object_height"/> - </draw_ops> - </piece> -</frame_style> - -<frame_style_set name="normal"> -<frame focus="yes" state="shaded" resize="both" style="focused_shaded"/> -<frame focus="yes" state="normal" resize="both" style="focused"/> -<frame focus="yes" state="maximized" style="focused_maximized"/> -<frame focus="yes" state="maximized_and_shaded" style="focused_maximized"/> -<frame focus="no" state="normal" resize="both" style="normal"/> -<frame focus="no" state="shaded" resize="both" style="normal_shaded"/> -<frame focus="no" state="maximized" style="normal_maximized"/> -<frame focus="no" state="maximized_and_shaded" style="normal_maximized"/> -</frame_style_set> - -<frame_style_set name="border"> -<frame focus="yes" state="normal" resize="both" style="border_focused"/> -<frame focus="yes" state="maximized" style="border_focused"/> -<frame focus="yes" state="shaded" resize="both" style="border_focused"/> -<frame focus="yes" state="maximized_and_shaded" style="border_focused"/> -<frame focus="no" state="normal" resize="both" style="border_unfocused"/> -<frame focus="no" state="maximized" style="border_unfocused"/> -<frame focus="no" state="shaded" resize="both" style="border_unfocused"/> -<frame focus="no" state="maximized_and_shaded" style="border_unfocused"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="normal"/> -<window type="modal_dialog" style_set="normal"/> -<window type="menu" style_set="normal"/> -<window type="utility" style_set="normal"/> -<window type="border" style_set="border"/> - -<menu_icon function="close" state="normal"> - <draw_ops> - <image filename="active-close-button.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - -<menu_icon function="maximize" state="normal"> - <draw_ops> - <image filename="active-maximize-button.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - - -<menu_icon function="minimize" state="normal"> - <draw_ops> - <image filename="active-minimize-button.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - -<menu_icon function="unmaximize" state="normal"> - <draw_ops> - </draw_ops> -</menu_icon> - -</metacity_theme> diff --git a/src/themes/Esco/metacity-theme-1.xml b/src/themes/Esco/metacity-theme-1.xml deleted file mode 100644 index 9a9061ba..00000000 --- a/src/themes/Esco/metacity-theme-1.xml +++ /dev/null @@ -1,990 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> - -<info> - <name>Esco</name> - <author>James M. Cape <jcape@ignore-your.tv></author> - <copyright>Â Havoc Pennington, 2002 for Atlanta. Â Gaute Lindkvist, 2002 for Bright. Â James M. Cape 2002 for modifications</copyright> - <date>February 3, 2002</date> - <description>Simple theme designed to look really good & match GTK+ well.</description> -</info> - -<frame_geometry name="normal"> - <distance name="left_width" value="5"/> - <distance name="right_width" value="5"/> - <distance name="bottom_height" value="5"/> - <distance name="left_titlebar_edge" value="5"/> - <distance name="right_titlebar_edge" value="5"/> - <aspect_ratio name="button" value="1.0"/> - <distance name="title_vertical_pad" value="1"/> - <border name="title_border" left="5" right="5" top="3" bottom="2"/> - <border name="button_border" left="0" right="0" top="3" bottom="2"/> -</frame_geometry> - -<!-- strip borders off the normal geometry --> -<frame_geometry name="normal_small_borders" parent="normal"> - <distance name="left_width" value="0"/> - <distance name="right_width" value="0"/> - <distance name="bottom_height" value="0"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="title_vertical_pad" value="2"/> - <border name="title_border" left="5" right="5" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<frame_geometry name="utility" title_scale="small"> - <distance name="left_width" value="1"/> - <distance name="right_width" value="1"/> - <distance name="bottom_height" value="5"/> - <distance name="left_titlebar_edge" value="2"/> - <distance name="right_titlebar_edge" value="2"/> - <aspect_ratio name="button" value="1.0"/> - <distance name="title_vertical_pad" value="3"/> - <border name="title_border" left="2" right="2" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="2" bottom="0"/> -</frame_geometry> - -<frame_geometry name="border" has_title="false"> - <distance name="left_width" value="5"/> - <distance name="right_width" value="5"/> - <distance name="bottom_height" value="5"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="5"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<!-- define constants --> -<constant name="ButtonIPad" value="3"/> -<constant name="IconTitleSpacing" value="8"/> - -<!-- Button Outlines --> -<draw_ops name="button_prelight_bg"> - <gtk_box state="prelight" shadow="out" x="0" y="0" width="width" - height="height"/> -</draw_ops> - -<draw_ops name="button_pressed_bg"> - <gtk_box state="active" shadow="in" x="0" y="0" width="width" - height="height"/> -</draw_ops> - -<draw_ops name="right_button_normal_bg"> - <rectangle color="#ffffff" filled="true" x="0" y="0" width="width" height="height"/> -</draw_ops> - -<!-- Button Icons --> - -<!-- Minimize Button --> -<draw_ops name="minimize_button"> - <rectangle color="gtk:dark[NORMAL]" filled="true" - x="ButtonIPad" - y="height - ButtonIPad - ((height - (ButtonIPad + 1) * 2) * 0.4) - 1" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4"/> -</draw_ops> -<draw_ops name="minimize_button_focused"> - <rectangle color="gtk:fg[SELECTED]" filled="true" - x="ButtonIPad" - y="height - ButtonIPad - ((height - (ButtonIPad + 1) * 2) * 0.4) - 1" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4"/> -</draw_ops> -<draw_ops name="minimize_button_prelight"> - <include name="button_prelight_bg"/> - <rectangle color="gtk:dark[PRELIGHT]" filled="true" - x="ButtonIPad + 1" - y="height - ButtonIPad - ((height - (ButtonIPad + 1) * 2) * 0.4)" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4 + 1"/> - <rectangle color="gtk:fg[PRELIGHT]" filled="false" - x="ButtonIPad" - y="height - ButtonIPad - ((height - (ButtonIPad + 1) * 2) * 0.4) - 1" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4"/> -</draw_ops> -<draw_ops name="minimize_button_pressed"> - <include name="button_pressed_bg"/> - <rectangle color="gtk:dark[ACTIVE]" filled="true" - x="ButtonIPad + 1" - y="height - ButtonIPad - ((height - (ButtonIPad + 1) * 2) * 0.4)" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4 + 1"/> - <rectangle color="gtk:fg[ACTIVE]" filled="false" - x="ButtonIPad" - y="height - ButtonIPad - ((height - (ButtonIPad + 1) * 2) * 0.4) - 1" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4"/> -</draw_ops> - -<!-- Maximize Button --> -<draw_ops name="maximize_button"> - <rectangle color="gtk:dark[NORMAL]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="width - (ButtonIPad + 1) * 2" - height="height - (ButtonIPad + 1) * 2"/> - <rectangle color="gtk:dark[NORMAL]" filled="true" - x="ButtonIPad" - y="ButtonIPad" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4"/> -</draw_ops> -<draw_ops name="maximize_button_focused"> - <rectangle color="gtk:fg[SELECTED]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="width - (ButtonIPad + 1) * 2" - height="height - (ButtonIPad + 1) * 2"/> - <rectangle color="gtk:fg[SELECTED]" filled="true" - x="ButtonIPad" - y="ButtonIPad" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4"/> -</draw_ops> -<draw_ops name="maximize_button_prelight"> - <include name="button_prelight_bg"/> - <rectangle color="gtk:dark[PRELIGHT]" filled="false" - x="ButtonIPad + 1" - y="ButtonIPad + 1" - width="width - (ButtonIPad + 1) * 2" - height="height - (ButtonIPad + 1) * 2"/> - <rectangle color="gtk:dark[PRELIGHT]" filled="true" - x="ButtonIPad + 1" - y="ButtonIPad + 1" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4 + 1"/> - <rectangle color="gtk:fg[PRELIGHT]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="width - (ButtonIPad + 1) * 2" - height="height - (ButtonIPad + 1) * 2"/> - <rectangle color="gtk:fg[PRELIGHT]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4"/> -</draw_ops> -<draw_ops name="maximize_button_pressed"> - <include name="button_pressed_bg"/> - <rectangle color="gtk:dark[ACTIVE]" filled="false" - x="ButtonIPad + 1" - y="ButtonIPad + 1" - width="width - (ButtonIPad + 1) * 2" - height="height - (ButtonIPad + 1) * 2"/> - <rectangle color="gtk:dark[ACTIVE]" filled="true" - x="ButtonIPad + 1" - y="ButtonIPad + 1" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4 + 1"/> - <rectangle color="gtk:fg[ACTIVE]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="width - (ButtonIPad + 1) * 2" - height="height - (ButtonIPad + 1) * 2"/> - <rectangle color="gtk:fg[ACTIVE]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="width - (ButtonIPad + 1) * 2" - height="(height - (ButtonIPad + 1) * 2) * 0.4"/> -</draw_ops> - -<!-- UnMaximize Button --> -<draw_ops name="restore_button"> - <rectangle color="gtk:dark[NORMAL]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:dark[NORMAL]" filled="true" - x="ButtonIPad" - y="ButtonIPad" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> - <rectangle color="gtk:dark[NORMAL]" filled="false" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:dark[NORMAL]" filled="true" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> -</draw_ops> -<draw_ops name="restore_button_focused"> - <rectangle color="gtk:fg[SELECTED]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:fg[SELECTED]" filled="true" - x="ButtonIPad" - y="ButtonIPad" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> - <rectangle color="gtk:fg[SELECTED]" filled="false" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:fg[SELECTED]" filled="true" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> -</draw_ops> -<draw_ops name="restore_button_prelight"> - <include name="button_prelight_bg"/> - <rectangle color="gtk:dark[PRELIGHT]" filled="false" - x="ButtonIPad + 1" - y="ButtonIPad + 1" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:dark[PRELIGHT]" filled="true" - x="ButtonIPad + 1" - y="ButtonIPad + 1" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> - <rectangle color="gtk:dark[PRELIGHT]" filled="false" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33 + 1" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33 + 1" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:dark[PRELIGHT]" filled="true" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33 + 1" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33 + 1" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> - <rectangle color="gtk:fg[PRELIGHT]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:fg[PRELIGHT]" filled="true" - x="ButtonIPad" - y="ButtonIPad" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> - <rectangle color="gtk:fg[PRELIGHT]" filled="false" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:fg[PRELIGHT]" filled="true" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> -</draw_ops> -<draw_ops name="restore_button_pressed"> - <include name="button_pressed_bg"/> - <rectangle color="gtk:dark[ACTIVE]" filled="false" - x="ButtonIPad + 1" - y="ButtonIPad + 1" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:dark[ACTIVE]" filled="true" - x="ButtonIPad + 1" - y="ButtonIPad + 1" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> - <rectangle color="gtk:dark[ACTIVE]" filled="false" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33 + 1" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33 + 1" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:dark[ACTIVE]" filled="true" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33 + 1" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33 + 1" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> - <rectangle color="gtk:fg[ACTIVE]" filled="false" - x="ButtonIPad" - y="ButtonIPad" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:fg[ACTIVE]" filled="true" - x="ButtonIPad" - y="ButtonIPad" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> - <rectangle color="gtk:fg[ACTIVE]" filled="false" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="(height - (ButtonIPad + 1) * 2) * 0.67"/> - <rectangle color="gtk:fg[ACTIVE]" filled="true" - x="ButtonIPad + (width - (ButtonIPad + 1) * 2) * 0.33" - y="ButtonIPad + (height - (ButtonIPad + 1) * 2) * 0.33" - width="(width - (ButtonIPad + 1) * 2) * 0.67" - height="((height - (ButtonIPad + 1) * 2) * 0.4) * 0.67"/> -</draw_ops> - -<!-- Menu Button --> -<draw_ops name="menu_button"> - <line color="gtk:dark[NORMAL]" width="3" - x1="ButtonIPad + 1" - y1="ButtonIPad" - x2="ButtonIPad + 1" - y2="height - ButtonIPad - 3"/> - <line color="gtk:dark[NORMAL]" width="3" - x1="ButtonIPad" - y1="height - ButtonIPad - 5" - x2="width - ButtonIPad - 2" - y2="height - ButtonIPad - 5"/> - <line color="gtk:dark[NORMAL]" width="1" - x1="ButtonIPad" - y1="height - ButtonIPad - 5" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 5"/> - <line color="gtk:dark[NORMAL]" width="1" - x1="width - ButtonIPad - 4" - y1="height - ButtonIPad - 3 - 4" - x2="width - ButtonIPad - 4" - y2="height - ButtonIPad - 2"/> - <line color="gtk:dark[NORMAL]" width="1" - x1="width - ButtonIPad - 5" - y1="height - ButtonIPad - 3 - 5" - x2="width - ButtonIPad - 5" - y2="height - ButtonIPad - 1"/> -</draw_ops> -<draw_ops name="menu_button_focused"> - <line color="gtk:fg[SELECTED]" width="3" - x1="ButtonIPad + 1" - y1="ButtonIPad" - x2="ButtonIPad + 1" - y2="height - ButtonIPad - 3"/> - <line color="gtk:fg[SELECTED]" width="3" - x1="ButtonIPad" - y1="height - ButtonIPad - 5" - x2="width - ButtonIPad - 2" - y2="height - ButtonIPad - 5"/> - <line color="gtk:fg[SELECTED]" width="1" - x1="ButtonIPad" - y1="height - ButtonIPad - 5" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 5"/> - <line color="gtk:fg[SELECTED]" width="1" - x1="width - ButtonIPad - 4" - y1="height - ButtonIPad - 3 - 4" - x2="width - ButtonIPad - 4" - y2="height - ButtonIPad - 2"/> - <line color="gtk:fg[SELECTED]" width="1" - x1="width - ButtonIPad - 5" - y1="height - ButtonIPad - 3 - 5" - x2="width - ButtonIPad - 5" - y2="height - ButtonIPad - 1"/> -</draw_ops> -<draw_ops name="menu_button_prelight"> - <include name="button_prelight_bg"/> - <line color="gtk:dark[PRELIGHT]" width="3" - x1="ButtonIPad + 1 + 1" - y1="ButtonIPad + 1" - x2="ButtonIPad + 1 + 1" - y2="height - ButtonIPad - 3 + 1"/> - <line color="gtk:dark[PRELIGHT]" width="3" - x1="ButtonIPad + 1" - y1="height - ButtonIPad - 5 + 1" - x2="width - ButtonIPad - 2 + 1" - y2="height - ButtonIPad - 5 + 1"/> - <line color="gtk:dark[PRELIGHT]" width="1" - x1="ButtonIPad + 1" - y1="height - ButtonIPad - 5 + 1" - x2="width - ButtonIPad - 1 + 1" - y2="height - ButtonIPad - 5 + 1"/> - <line color="gtk:dark[PRELIGHT]" width="1" - x1="width - ButtonIPad - 4 + 1" - y1="height - ButtonIPad - 3 - 4 + 1" - x2="width - ButtonIPad - 4 + 1" - y2="height - ButtonIPad - 2 + 1"/> - <line color="gtk:dark[PRELIGHT]" width="1" - x1="width - ButtonIPad - 5 + 1" - y1="height - ButtonIPad - 3 - 5 + 1" - x2="width - ButtonIPad - 5 + 1" - y2="height - ButtonIPad - 1 + 1"/> - <line color="gtk:fg[PRELIGHT]" width="3" - x1="ButtonIPad + 1" - y1="ButtonIPad" - x2="ButtonIPad + 1" - y2="height - ButtonIPad - 3"/> - <line color="gtk:fg[PRELIGHT]" width="3" - x1="ButtonIPad" - y1="height - ButtonIPad - 5" - x2="width - ButtonIPad - 2" - y2="height - ButtonIPad - 5"/> - <line color="gtk:fg[PRELIGHT]" width="1" - x1="ButtonIPad" - y1="height - ButtonIPad - 5" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 5"/> - <line color="gtk:fg[PRELIGHT]" width="1" - x1="width - ButtonIPad - 4" - y1="height - ButtonIPad - 3 - 4" - x2="width - ButtonIPad - 4" - y2="height - ButtonIPad - 2"/> - <line color="gtk:fg[PRELIGHT]" width="1" - x1="width - ButtonIPad - 5" - y1="height - ButtonIPad - 3 - 5" - x2="width - ButtonIPad - 5" - y2="height - ButtonIPad - 1"/> -</draw_ops> -<draw_ops name="menu_button_pressed"> - <include name="button_pressed_bg"/> - <line color="gtk:dark[ACTIVE]" width="3" - x1="ButtonIPad + 1 + 1" - y1="ButtonIPad + 1" - x2="ButtonIPad + 1 + 1" - y2="height - ButtonIPad - 3 + 1"/> - <line color="gtk:dark[ACTIVE]" width="3" - x1="ButtonIPad + 1" - y1="height - ButtonIPad - 5 + 1" - x2="width - ButtonIPad - 2 + 1" - y2="height - ButtonIPad - 5 + 1"/> - <line color="gtk:dark[ACTIVE]" width="1" - x1="ButtonIPad + 1" - y1="height - ButtonIPad - 5 + 1" - x2="width - ButtonIPad - 1 + 1" - y2="height - ButtonIPad - 5 + 1"/> - <line color="gtk:dark[ACTIVE]" width="1" - x1="width - ButtonIPad - 4 + 1" - y1="height - ButtonIPad - 3 - 4 + 1" - x2="width - ButtonIPad - 4 + 1" - y2="height - ButtonIPad - 2 + 1"/> - <line color="gtk:dark[ACTIVE]" width="1" - x1="width - ButtonIPad - 5 + 1" - y1="height - ButtonIPad - 3 - 5 + 1" - x2="width - ButtonIPad - 5 + 1" - y2="height - ButtonIPad - 1 + 1"/> - <line color="gtk:fg[ACTIVE]" width="3" - x1="ButtonIPad + 1" - y1="ButtonIPad" - x2="ButtonIPad + 1" - y2="height - ButtonIPad - 3"/> - <line color="gtk:fg[ACTIVE]" width="3" - x1="ButtonIPad" - y1="height - ButtonIPad - 5" - x2="width - ButtonIPad - 2" - y2="height - ButtonIPad - 5"/> - <line color="gtk:fg[ACTIVE]" width="1" - x1="ButtonIPad" - y1="height - ButtonIPad - 5" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 5"/> - <line color="gtk:fg[ACTIVE]" width="1" - x1="width - ButtonIPad - 4" - y1="height - ButtonIPad - 3 - 4" - x2="width - ButtonIPad - 4" - y2="height - ButtonIPad - 2"/> - <line color="gtk:fg[ACTIVE]" width="1" - x1="width - ButtonIPad - 5" - y1="height - ButtonIPad - 3 - 5" - x2="width - ButtonIPad - 5" - y2="height - ButtonIPad - 1"/> -</draw_ops> - -<!-- Close Button --> -<draw_ops name="close_button"> - <line color="gtk:dark[NORMAL]" width="1" - x1="ButtonIPad" - y1="ButtonIPad" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 1"/> - <line color="gtk:dark[NORMAL]" width="1" - x1="ButtonIPad + 1" - y1="ButtonIPad" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 1 - 1"/> - <line color="gtk:dark[NORMAL]" width="1" - x1="ButtonIPad" - y1="ButtonIPad + 1" - x2="width - ButtonIPad - 1 - 1" - y2="height - ButtonIPad - 1"/> - - <line color="gtk:dark[NORMAL]" width="1" - x1="ButtonIPad" - y1="height - 1 - ButtonIPad - 1" - x2="width - 1 - ButtonIPad" - y2="ButtonIPad - 1"/> - <line color="gtk:dark[NORMAL]" width="1" - x1="ButtonIPad + 1" - y1="height - 1 - ButtonIPad - 1" - x2="width - 1 - ButtonIPad" - y2="ButtonIPad"/> - <line color="gtk:dark[NORMAL]" width="1" - x1="ButtonIPad" - y1="height - 1 - ButtonIPad - 1 - 1" - x2="width - 1 - ButtonIPad - 1" - y2="ButtonIPad - 1"/> -</draw_ops> -<draw_ops name="close_button_focused"> - <line color="gtk:fg[SELECTED]" width="1" - x1="ButtonIPad" - y1="ButtonIPad" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 1"/> - <line color="gtk:fg[SELECTED]" width="1" - x1="ButtonIPad + 1" - y1="ButtonIPad" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 1 - 1"/> - <line color="gtk:fg[SELECTED]" width="1" - x1="ButtonIPad" - y1="ButtonIPad + 1" - x2="width - ButtonIPad - 1 - 1" - y2="height - ButtonIPad - 1"/> - - <line color="gtk:fg[SELECTED]" width="1" - x1="ButtonIPad" - y1="height - 1 - ButtonIPad - 1" - x2="width - 1 - ButtonIPad" - y2="ButtonIPad - 1"/> - <line color="gtk:fg[SELECTED]" width="1" - x1="ButtonIPad + 1" - y1="height - 1 - ButtonIPad - 1" - x2="width - 1 - ButtonIPad" - y2="ButtonIPad"/> - <line color="gtk:fg[SELECTED]" width="1" - x1="ButtonIPad" - y1="height - 1 - ButtonIPad - 1 - 1" - x2="width - 1 - ButtonIPad - 1" - y2="ButtonIPad - 1"/> -</draw_ops> -<draw_ops name="close_button_prelight"> - <include name="button_prelight_bg"/> - <line color="gtk:dark[PRELIGHT]" width="1" - x1="ButtonIPad + 1" - y1="ButtonIPad + 1" - x2="width - ButtonIPad - 1 + 1" - y2="height - ButtonIPad - 1 + 1"/> - <line color="gtk:dark[PRELIGHT]" width="1" - x1="ButtonIPad + 1 + 1" - y1="ButtonIPad + 1" - x2="width - ButtonIPad - 1 + 1" - y2="height - ButtonIPad - 1 - 1 + 1"/> - <line color="gtk:dark[PRELIGHT]" width="1" - x1="ButtonIPad + 1" - y1="ButtonIPad + 1 + 1" - x2="width - ButtonIPad - 1 - 1 + 1" - y2="height - ButtonIPad - 1 + 1"/> - - <line color="gtk:dark[PRELIGHT]" width="1" - x1="ButtonIPad + 1" - y1="height - 1 - ButtonIPad - 1 + 1" - x2="width - 1 - ButtonIPad + 1" - y2="ButtonIPad - 1 + 1"/> - <line color="gtk:dark[PRELIGHT]" width="1" - x1="ButtonIPad + 1 + 1" - y1="height - 1 - ButtonIPad - 1 + 1" - x2="width - 1 - ButtonIPad + 1" - y2="ButtonIPad + 1"/> - <line color="gtk:dark[PRELIGHT]" width="1" - x1="ButtonIPad + 1" - y1="height - 1 - ButtonIPad - 1 - 1 + 1" - x2="width - 1 - ButtonIPad - 1 + 1" - y2="ButtonIPad - 1 + 1"/> - - <line color="gtk:fg[PRELIGHT]" width="1" - x1="ButtonIPad" - y1="ButtonIPad" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 1"/> - <line color="gtk:fg[PRELIGHT]" width="1" - x1="ButtonIPad + 1" - y1="ButtonIPad" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 1 - 1"/> - <line color="gtk:fg[PRELIGHT]" width="1" - x1="ButtonIPad" - y1="ButtonIPad + 1" - x2="width - ButtonIPad - 1 - 1" - y2="height - ButtonIPad - 1"/> - - <line color="gtk:fg[PRELIGHT]" width="1" - x1="ButtonIPad" - y1="height - 1 - ButtonIPad - 1" - x2="width - 1 - ButtonIPad" - y2="ButtonIPad - 1"/> - <line color="gtk:fg[PRELIGHT]" width="1" - x1="ButtonIPad + 1" - y1="height - 1 - ButtonIPad - 1" - x2="width - 1 - ButtonIPad" - y2="ButtonIPad"/> - <line color="gtk:fg[PRELIGHT]" width="1" - x1="ButtonIPad" - y1="height - 1 - ButtonIPad - 1 - 1" - x2="width - 1 - ButtonIPad - 1" - y2="ButtonIPad - 1"/> -</draw_ops> -<draw_ops name="close_button_pressed"> - <include name="button_pressed_bg"/> - <line color="gtk:dark[ACTIVE]" width="1" - x1="ButtonIPad + 1" - y1="ButtonIPad + 1" - x2="width - ButtonIPad - 1 + 1" - y2="height - ButtonIPad - 1 + 1"/> - <line color="gtk:dark[ACTIVE]" width="1" - x1="ButtonIPad + 1 + 1" - y1="ButtonIPad + 1" - x2="width - ButtonIPad - 1 + 1" - y2="height - ButtonIPad - 1 - 1 + 1"/> - <line color="gtk:dark[ACTIVE]" width="1" - x1="ButtonIPad + 1" - y1="ButtonIPad + 1 + 1" - x2="width - ButtonIPad - 1 - 1 + 1" - y2="height - ButtonIPad - 1 + 1"/> - - <line color="gtk:dark[ACTIVE]" width="1" - x1="ButtonIPad + 1" - y1="height - 1 - ButtonIPad - 1 + 1" - x2="width - 1 - ButtonIPad + 1" - y2="ButtonIPad - 1 + 1"/> - <line color="gtk:dark[ACTIVE]" width="1" - x1="ButtonIPad + 1 + 1" - y1="height - 1 - ButtonIPad - 1 + 1" - x2="width - 1 - ButtonIPad + 1" - y2="ButtonIPad + 1"/> - <line color="gtk:dark[ACTIVE]" width="1" - x1="ButtonIPad + 1" - y1="height - 1 - ButtonIPad - 1 - 1 + 1" - x2="width - 1 - ButtonIPad - 1 + 1" - y2="ButtonIPad - 1 + 1"/> - - <line color="gtk:fg[ACTIVE]" width="1" - x1="ButtonIPad" - y1="ButtonIPad" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 1"/> - <line color="gtk:fg[ACTIVE]" width="1" - x1="ButtonIPad + 1" - y1="ButtonIPad" - x2="width - ButtonIPad - 1" - y2="height - ButtonIPad - 1 - 1"/> - <line color="gtk:fg[ACTIVE]" width="1" - x1="ButtonIPad" - y1="ButtonIPad + 1" - x2="width - ButtonIPad - 1 - 1" - y2="height - ButtonIPad - 1"/> - - <line color="gtk:fg[ACTIVE]" width="1" - x1="ButtonIPad" - y1="height - 1 - ButtonIPad - 1" - x2="width - 1 - ButtonIPad" - y2="ButtonIPad - 1"/> - <line color="gtk:fg[ACTIVE]" width="1" - x1="ButtonIPad + 1" - y1="height - 1 - ButtonIPad - 1" - x2="width - 1 - ButtonIPad" - y2="ButtonIPad"/> - <line color="gtk:fg[ACTIVE]" width="1" - x1="ButtonIPad" - y1="height - 1 - ButtonIPad - 1 - 1" - x2="width - 1 - ButtonIPad - 1" - y2="ButtonIPad - 1"/> -</draw_ops> -<!-- End Buttons Icons --> - -<!-- Outer Bevel --> -<draw_ops name="outer_bevel"> - <rectangle color="gtk:dark[NORMAL]" - x="0" y="0" width="width - 1" height="height - 1"/> - <rectangle color="gtk:bg[NORMAL]" filled="true" - x="1" y="1" width="width - 2" height="height - 2"/> -</draw_ops> - -<draw_ops name="gradient_background"> - <gradient type="vertical" x="0" y="0" width="width" height="top_height"> - <color value="gtk:light[SELECTED]"/> - <color value="gtk:dark[SELECTED]"/> - </gradient> -</draw_ops> - -<draw_ops name="outer_bevel_focused"> - <gtk_box state="selected" shadow="out" x="2" y="2" width="width - 2" - height="height - 2"/> - <rectangle color="gtk:bg[NORMAL]" filled="true" - x="left_width" y="top_height" - width="width - left_width - right_width - 1" - height="height - top_height - bottom_height - 1"/> - <rectangle color="gtk:fg[NORMAL]" - x="0" y="0" width="width - 1" height="height - 1"/> - <include name="gradient_background" - x="3" y="3" width="width - 7" height="height - 7"/> -</draw_ops> - -<draw_ops name="blank"> -<!-- nothing --> -</draw_ops> - -<draw_ops name="outline_focused"> - <rectangle color="gtk:fg[NORMAL]" - x="left_width - 1" y="top_height - 1" - width="width - left_width - right_width + 1" - height="height - top_height - bottom_height + 1"/> -</draw_ops> - -<draw_ops name="background"> - <include name="outer_bevel"/> -</draw_ops> - -<draw_ops name="background_focused"> - <include name="outer_bevel_focused"/> - <include name="outline_focused"/> -</draw_ops> - -<draw_ops name="title_background"> - <line color="#000000" width="50" - x1="width - title_width - IconTitleSpacing + 25 - 1 + 3" - y1="0 - 25" - x2="width - title_width - IconTitleSpacing - height - 25 - 1 + 3" - y2="height + 25"/> - <line color="#ffffff" width="50" - x1="width - title_width - IconTitleSpacing + 25 + 3" - y1="0 - 25" - x2="width - title_width - IconTitleSpacing - height - 25 + 3" - y2="height + 25"/> - <line color="#000000" width="1" - x1="width - 1" - y1="0" - x2="width - 1" - y2="height"/> - <rectangle color="#ffffff" filled="true" - x="width - title_width - mini_icon_width - IconTitleSpacing * 3" - y="0" - width="title_width + mini_icon_width + IconTitleSpacing * 3 - 1" - height="height"/> -</draw_ops> - -<draw_ops name="title_text_focused_with_icon"> - <title color="#000000" - x="width - title_width - IconTitleSpacing" - y="(height / 2) - (title_height / 2) - 1"/> - <icon - x="width - title_width - mini_icon_width - (IconTitleSpacing * 2)" - y="(height / 2) - (mini_icon_height / 2)" - width="mini_icon_width" - height="mini_icon_height"/> -</draw_ops> - -<draw_ops name="title_text_focused_no_icon"> - <title color="gtk:fg[INSENSITIVE]" - x="width - title_width - IconTitleSpacing" - y="(height / 2) - (title_height / 2)"/> - <icon - x="width - title_width - height - (IconTitleSpacing * 2)" - y="1" - width="height - 2" - height="height - 2"/> -</draw_ops> - -<draw_ops name="title_text_with_icon"> - <title color="gtk:dark[NORMAL]" - x="width - title_width - IconTitleSpacing" - y="(height / 2) - (title_height / 2) - 2"/> - <icon alpha="0.33" - x="width - title_width - mini_icon_width - (IconTitleSpacing * 2)" - y="(height / 2) - (mini_icon_height / 2) - 2" - width="mini_icon_width" - height="mini_icon_height"/> -</draw_ops> - -<draw_ops name="title_text_no_icon"> - <title color="gtk:dark[NORMAL]" - x="width - title_width - IconTitleSpacing" - y="(height / 2) - (title_height / 2)"/> - <icon alpha="0.33" - x="width - title_width - height - (IconTitleSpacing * 2)" - y="1" - width="height - 2" - height="height - 2"/> -</draw_ops> - -<draw_ops name="title_normal"> - <include name="title_text_with_icon" x="0" y="3" width="width" height="height - 3"/> -</draw_ops> - -<draw_ops name="title_focused"> - <include name="title_background"/> - <line color="#000000" width="1" - x1="width - title_width - mini_icon_width - IconTitleSpacing * 3" - y1="0" - x2="width" - y2="0"/> - <line color="#000000" width="1" - x1="width - title_width - mini_icon_width - IconTitleSpacing * 3 - 18" - y1="height - 1" - x2="width" - y2="height - 1"/> - <include name="title_text_focused_with_icon" x="0" y="2" width="width" height="height - 3"/> -</draw_ops> - -<draw_ops name="title_maximized"> - <include name="title_text_with_icon"/> -</draw_ops> - -<draw_ops name="title_maximized_focused"> - <include name="title_background"/> - <include name="title_text_focused_with_icon"/> -</draw_ops> - -<draw_ops name="title_utility"> - <include name="title_text_no_icon"/> -</draw_ops> - -<draw_ops name="title_utility_focused"> - <include name="title_background" - x="mini_icon_width + IconTitleSpacing" - y="0" - width="width - mini_icon_width - IconTitleSpacing" - height="height"/> - <line color="#000000" width="1" - x1="width - title_width - mini_icon_width - IconTitleSpacing * 3" - y1="0" - x2="width" - y2="0"/> - <include name="title_text_focused_no_icon"/> -</draw_ops> - -<frame_style name="normal_unfocused" geometry="normal"> - <piece position="entire_background" draw_ops="background"/> - - <piece position="title" draw_ops="title_normal"/> - - <button function="menu" state="normal" - draw_ops="menu_button"/> - <button function="menu" state="pressed" - draw_ops="menu_button_pressed"/> - - <button function="minimize" state="normal" - draw_ops="minimize_button"/> - <button function="minimize" state="pressed" - draw_ops="minimize_button_pressed"/> - - <button function="maximize" state="normal" - draw_ops="maximize_button"/> - <button function="maximize" state="pressed" - draw_ops="maximize_button_pressed"/> - - <button function="close" state="normal" draw_ops="close_button"/> - <button function="close" state="pressed" draw_ops="close_button_pressed"/> -</frame_style> - -<frame_style name="normal_focused" geometry="normal" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="background_focused"/> - <piece position="title" draw_ops="title_focused"/> - - <button function="close" state="normal" - draw_ops="close_button_focused"/> - <button function="close" state="prelight" - draw_ops="close_button_prelight"/> - - <button function="menu" state="normal" - draw_ops="menu_button_focused"/> - <button function="menu" state="prelight" - draw_ops="menu_button_prelight"/> - - <button function="maximize" state="normal" - draw_ops="maximize_button_focused"/> - <button function="maximize" state="prelight" - draw_ops="maximize_button_prelight"/> - - <button function="minimize" state="normal" - draw_ops="minimize_button_focused"/> - <button function="minimize" state="prelight" - draw_ops="minimize_button_prelight"/> -</frame_style> - -<frame_style name="maximized_unfocused" geometry="normal_small_borders" - parent="normal_unfocused"> - <piece position="entire_background" draw_ops="blank"/> - - <piece position="title" draw_ops="title_maximized"/> - - <button function="maximize" state="normal" - draw_ops="restore_button"/> - <button function="maximize" state="pressed" - draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="maximized_focused" geometry="normal_small_borders" - parent="normal_focused"> - <piece position="entire_background" draw_ops="gradient_background"/> - <piece position="title" draw_ops="title_maximized_focused"/> - - <button function="maximize" state="normal" - draw_ops="restore_button_focused"/> - <button function="maximize" state="pressed" - draw_ops="restore_button_pressed"/> - <button function="maximize" state="prelight" - draw_ops="restore_button_prelight"/> -</frame_style> - -<frame_style name="utility_unfocused" geometry="utility" - parent="normal_unfocused"> - <piece position="title" draw_ops="title_utility"/> -</frame_style> - -<frame_style name="utility_focused" geometry="utility" parent="normal_focused"> - <piece position="title" draw_ops="title_utility_focused"/> -</frame_style> - -<frame_style name="border" geometry="border" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="outer_bevel"/> - <piece position="title" draw_ops="blank"/> -</frame_style> - -<frame_style_set name="normal"> - <frame focus="yes" state="normal" resize="both" style="normal_focused"/> - <frame focus="no" state="normal" resize="both" style="normal_unfocused"/> - <frame focus="yes" state="maximized" style="maximized_focused"/> - <frame focus="no" state="maximized" style="maximized_unfocused"/> - <frame focus="yes" state="shaded" style="normal_focused"/> - <frame focus="no" state="shaded" style="normal_unfocused"/> - <frame focus="yes" state="maximized_and_shaded" style="maximized_focused"/> - <frame focus="no" state="maximized_and_shaded" style="maximized_unfocused"/> -</frame_style_set> - -<frame_style_set name="utility" parent="normal"> - <frame focus="yes" state="normal" resize="both" style="utility_focused"/> - <frame focus="no" state="normal" resize="both" style="utility_unfocused"/> -<!-- this is a bunch of crack since utility windows shouldn't be maximized --> - <frame focus="yes" state="maximized" style="utility_focused"/> - <frame focus="no" state="maximized" style="utility_unfocused"/> - <frame focus="yes" state="shaded" style="utility_focused"/> - <frame focus="no" state="shaded" style="utility_unfocused"/> - <frame focus="yes" state="maximized_and_shaded" style="utility_focused"/> - <frame focus="no" state="maximized_and_shaded" style="utility_unfocused"/> -</frame_style_set> - -<frame_style_set name="border"> - <frame focus="yes" state="normal" resize="both" style="border"/> - <frame focus="no" state="normal" resize="both" style="border"/> - <frame focus="yes" state="maximized" style="border"/> - <frame focus="no" state="maximized" style="border"/> - <frame focus="yes" state="shaded" style="border"/> - <frame focus="no" state="shaded" style="border"/> - <frame focus="yes" state="maximized_and_shaded" style="border"/> - <frame focus="no" state="maximized_and_shaded" style="border"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="utility"/> -<window type="modal_dialog" style_set="utility"/> -<window type="menu" style_set="utility"/> -<window type="utility" style_set="utility"/> -<window type="border" style_set="border"/> - -<menu_icon function="close" state="normal" - draw_ops="close_button_focused"/> -<menu_icon function="maximize" state="normal" - draw_ops="maximize_button_focused"/> -<menu_icon function="unmaximize" state="normal" - draw_ops="restore_button_focused"/> -<menu_icon function="minimize" state="normal" - draw_ops="minimize_button_focused"/> - -</metacity_theme> diff --git a/src/themes/Gorilla/README b/src/themes/Gorilla/README deleted file mode 100644 index c275e5ee..00000000 --- a/src/themes/Gorilla/README +++ /dev/null @@ -1,7 +0,0 @@ -* Gorilla * - -A metacity theme to accompany Scalable and Unscalable Gorilla nautilus -themes. - -(c) 2001 Jakub 'jimmac' Steiner -Ported by Kenneth Christiansen diff --git a/src/themes/Gorilla/active-button.png b/src/themes/Gorilla/active-button.png Binary files differdeleted file mode 100644 index 64455b33..00000000 --- a/src/themes/Gorilla/active-button.png +++ /dev/null diff --git a/src/themes/Gorilla/active-close-button.png b/src/themes/Gorilla/active-close-button.png Binary files differdeleted file mode 100644 index 1d292165..00000000 --- a/src/themes/Gorilla/active-close-button.png +++ /dev/null diff --git a/src/themes/Gorilla/active-close-menu-icon.png b/src/themes/Gorilla/active-close-menu-icon.png Binary files differdeleted file mode 100644 index b77f77ae..00000000 --- a/src/themes/Gorilla/active-close-menu-icon.png +++ /dev/null diff --git a/src/themes/Gorilla/active-maximize-button.png b/src/themes/Gorilla/active-maximize-button.png Binary files differdeleted file mode 100644 index a982e5cb..00000000 --- a/src/themes/Gorilla/active-maximize-button.png +++ /dev/null diff --git a/src/themes/Gorilla/active-maximize-menu-icon.png b/src/themes/Gorilla/active-maximize-menu-icon.png Binary files differdeleted file mode 100644 index 02ccc37a..00000000 --- a/src/themes/Gorilla/active-maximize-menu-icon.png +++ /dev/null diff --git a/src/themes/Gorilla/active-menu-button.png b/src/themes/Gorilla/active-menu-button.png Binary files differdeleted file mode 100644 index b55d7078..00000000 --- a/src/themes/Gorilla/active-menu-button.png +++ /dev/null diff --git a/src/themes/Gorilla/active-minimize-button.png b/src/themes/Gorilla/active-minimize-button.png Binary files differdeleted file mode 100644 index 4205f4e8..00000000 --- a/src/themes/Gorilla/active-minimize-button.png +++ /dev/null diff --git a/src/themes/Gorilla/active-minimize-menu-icon.png b/src/themes/Gorilla/active-minimize-menu-icon.png Binary files differdeleted file mode 100644 index 29276929..00000000 --- a/src/themes/Gorilla/active-minimize-menu-icon.png +++ /dev/null diff --git a/src/themes/Gorilla/gorilla.xcf.bz2 b/src/themes/Gorilla/gorilla.xcf.bz2 Binary files differdeleted file mode 100644 index 89b85651..00000000 --- a/src/themes/Gorilla/gorilla.xcf.bz2 +++ /dev/null diff --git a/src/themes/Gorilla/inactive-close-button.png b/src/themes/Gorilla/inactive-close-button.png Binary files differdeleted file mode 100644 index c566b12f..00000000 --- a/src/themes/Gorilla/inactive-close-button.png +++ /dev/null diff --git a/src/themes/Gorilla/inactive-maximize-button.png b/src/themes/Gorilla/inactive-maximize-button.png Binary files differdeleted file mode 100644 index 9c838823..00000000 --- a/src/themes/Gorilla/inactive-maximize-button.png +++ /dev/null diff --git a/src/themes/Gorilla/inactive-menu-button.png b/src/themes/Gorilla/inactive-menu-button.png Binary files differdeleted file mode 100644 index b000a378..00000000 --- a/src/themes/Gorilla/inactive-menu-button.png +++ /dev/null diff --git a/src/themes/Gorilla/inactive-minimize-button.png b/src/themes/Gorilla/inactive-minimize-button.png Binary files differdeleted file mode 100644 index 4459af4e..00000000 --- a/src/themes/Gorilla/inactive-minimize-button.png +++ /dev/null diff --git a/src/themes/Gorilla/metacity-theme-1.xml b/src/themes/Gorilla/metacity-theme-1.xml deleted file mode 100644 index 7dde366a..00000000 --- a/src/themes/Gorilla/metacity-theme-1.xml +++ /dev/null @@ -1,260 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> -<info> - <name>Gorilla</name> - <author>Kenneth Christiansen <kenneth@gnu.org> Anders Carlsson <andersca@gnu.org></author> - <copyright>Â Ximian, Inc, 2001</copyright> - <date>February 8, 2002</date> - <description>A port of the Gorilla theme by Jacub Steiner</description> -</info> - -<!-- define constants --> -<constant name="IconTitleSpacing" value="2"/> <!-- Space between menu button and title --> -<constant name="ButtonWidth" value="18"/> <!-- Button width --> - -<frame_geometry name="normal"> - <distance name="left_width" value="6"/> - <distance name="right_width" value="6"/> - <distance name="bottom_height" value="6"/> - <distance name="left_titlebar_edge" value="8"/> - <distance name="right_titlebar_edge" value="8"/> - <aspect_ratio name="button" value="1.0"/> - <distance name="title_vertical_pad" value="0"/> - <border name="title_border" left="0" right="0" top="7" bottom="4"/> - <border name="button_border" left="0" right="0" top="9" bottom="0"/> -</frame_geometry> - - -<!-- Buttons --> - -<draw_ops name="title_tile"> - <line color="#494d59" x1="0" y1="0" x2="width" y2="0"/> - <line color="#515961" x1="0" y1="1" x2="width" y2="1"/> -</draw_ops> - -<!-- Inactive style --> -<frame_style name="normal" geometry="normal"> - <piece position="entire_background"> - <draw_ops> - <rectangle color="black" x="1" y="1" width="width - 2" height="height - 2" filled="true"/> - <rectangle color="dark gray" x="3" y="3" width="width - 8" height="height - 7" filled="false"/> - <rectangle color="light gray" x="4" y="4" width="width - 9" height="height - 8" filled="false"/> - <rectangle color="light gray" x="5" y="5" width="width - 11" height="height - 10" filled="false"/> - <rectangle color="white" x="6" y="6" width="width - 13" height="height - 12" filled="false"/> - <rectangle color="gtk:bg[INSENSITIVE]" x="6" y="6" width="width - 12" height="height - 12" filled="true"/> - - <line color="gtk:bg[INSENSITIVE]" x1="1" y1="1" x2="2" y2="2"/> - <line color="gtk:bg[INSENSITIVE]" x1="1" y1="height - 2" x2="1" y2="height"/> - <line color="gtk:bg[INSENSITIVE]" x1="width - 2" y1="1" x2="width - 1" y2="2"/> - <line color="gtk:bg[INSENSITIVE]" x1="width - 1" y1="height - 1" x2="width - 2" y2="height - 2"/> - </draw_ops> - </piece> - - <piece position="title"> - <draw_ops> - <title color="gray" x="IconTitleSpacing" y="0"/> - </draw_ops> - </piece> - - <piece position="titlebar"> - <draw_ops> - <rectangle color="black" x="6" y="6" width="width - 12" height="height - 10" filled="true"/> - <tile name="title_tile" tile_width="width" tile_height="2" x="8" y="8" width="width - 16" height="height - 14"/> - </draw_ops> - </piece> - - <button function="close" state="normal"> - <draw_ops> - <image filename="inactive-close-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="close" state="pressed"> - <draw_ops> - <image filename="inactive-close-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="minimize" state="normal"> - <draw_ops> - <image filename="inactive-minimize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="minimize" state="pressed"> - <draw_ops> - <image filename="inactive-minimize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="maximize" state="normal"> - <draw_ops> - <image filename="inactive-maximize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <image filename="inactive-maximize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="normal"> - <draw_ops> - <image filename="inactive-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="pressed"> - <draw_ops> - <image filename="inactive-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - -</frame_style> - - -<!-- Active (focused) shaded style --> -<frame_style name="normal_shaded" geometry="normal" parent="normal"> - -</frame_style> - -<!-- Active (focused) style --> -<frame_style name="focused" geometry="normal"> - <piece position="entire_background"> - <draw_ops> - <rectangle color="black" x="0" y="0" width="width" height="height" filled="true"/> - <rectangle color="dark gray" x="3" y="3" width="width - 8" height="height - 7" filled="false"/> - <rectangle color="light gray" x="4" y="4" width="width - 9" height="height - 8" filled="false"/> - <rectangle color="light gray" x="5" y="5" width="width - 11" height="height - 10" filled="false"/> - <rectangle color="white" x="6" y="6" width="width - 13" height="height - 12" filled="false"/> - <rectangle color="gtk:bg[NORMAL]" x="6" y="6" width="width - 12" height="height - 12" filled="true"/> - - <line color="gtk:bg[NORMAL]" x1="0" y1="0" x2="1" y2="1"/> - <line color="gtk:bg[NORMAL]" x1="0" y1="height - 1" x2="1" y2="height"/> - <line color="gtk:bg[NORMAL]" x1="width - 1" y1="0" x2="width" y2="1"/> - <line color="gtk:bg[NORMAL]" x1="width" y1="height" x2="width - 1" y2="height - 1"/> - </draw_ops> - </piece> - - <piece position="title"> - <draw_ops> - <title color="white" x="IconTitleSpacing" y="0"/> - </draw_ops> - </piece> - - <piece position="titlebar"> - <draw_ops> - <rectangle color="black" x="6" y="6" width="width - 12" height="height - 10" filled="true"/> - <tile name="title_tile" tile_width="width" tile_height="2" x="8" y="8" width="width - 16" height="height - 14"/> - </draw_ops> - </piece> - - <button function="close" state="normal"> - <draw_ops> - <image filename="active-close-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="close" state="pressed"> - <draw_ops> - <image filename="active-close-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="minimize" state="normal"> - <draw_ops> - <image filename="active-minimize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="minimize" state="pressed"> - <draw_ops> - <image filename="active-minimize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="maximize" state="normal"> - <draw_ops> - <image filename="active-maximize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="maximize" state="pressed"> - <draw_ops> - <image filename="active-maximize-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="normal"> - <draw_ops> - <image filename="active-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - - <button function="menu" state="pressed"> - <draw_ops> - <image filename="active-menu-button.png" x="0" y="0" width="width" height="height"/> - </draw_ops> - </button> - -</frame_style> - -<!-- Active (focused) shaded style --> -<frame_style name="focused_shaded" geometry="normal" parent="focused"> - -</frame_style> - -<frame_style_set name="normal"> -<frame focus="yes" state="shaded" style="focused_shaded"/> -<frame focus="yes" state="normal" resize="both" style="focused"/> -<frame focus="yes" state="maximized" style="focused"/> -<frame focus="yes" state="maximized_and_shaded" style="focused_shaded"/> -<frame focus="no" state="normal" resize="both" style="normal"/> -<frame focus="no" state="shaded" style="normal_shaded"/> -<frame focus="no" state="maximized" style="normal"/> -<frame focus="no" state="maximized_and_shaded" style="normal_shaded"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="normal"/> -<window type="modal_dialog" style_set="normal"/> -<window type="menu" style_set="normal"/> -<window type="utility" style_set="normal"/> -<window type="border" style_set="normal"/> - -<menu_icon function="maximize" state="normal"> - <draw_ops> - <image filename="active-maximize-menu-icon.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - - -<menu_icon function="close" state="normal"> - <draw_ops> - <image filename="active-close-menu-icon.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - -<menu_icon function="minimize" state="normal"> - <draw_ops> - <image filename="active-minimize-menu-icon.png" - x="(width - object_width) / 2" - y="(height - object_height) / 2" - width="object_width" height="object_height"/> - </draw_ops> -</menu_icon> - -<menu_icon function="unmaximize" state="normal"> - <draw_ops> - </draw_ops> -</menu_icon> - -</metacity_theme> diff --git a/src/themes/Makefile.am b/src/themes/Makefile.am deleted file mode 100644 index 82c504e8..00000000 --- a/src/themes/Makefile.am +++ /dev/null @@ -1,50 +0,0 @@ -THEMES= \ - Atlanta \ - Bright \ - Crux \ - Esco \ - AgingGorilla \ - Metabox \ - Simple - -THEME_DIR=$(datadir)/themes -THEME_SUBDIR=metacity-1 - -install-data-local: - $(mkinstalldirs) $(DESTDIR)$(THEME_DIR); \ - for THEME in $(THEMES); do \ - echo '-- Installing theme '$$THEME; \ - $(mkinstalldirs) $(DESTDIR)$(THEME_DIR)/$$THEME; \ - $(mkinstalldirs) $(DESTDIR)$(THEME_DIR)/$$THEME/$(THEME_SUBDIR); \ - (installfiles=`find $(srcdir)/$$THEME -name "*.png" -o -name "*.xml"`; \ - for i in $$installfiles; do \ - echo '-- Installing '$$i ; \ - $(INSTALL_DATA) $$i $(DESTDIR)$(THEME_DIR)/$$THEME/$(THEME_SUBDIR) ; \ - done) \ - done - -uninstall-local: - for THEME in $(THEMES); do \ - echo '-- Uninstalling theme '$$THEME; \ - (uninstallfiles=`find $(srcdir)/$$THEME -name "*.png" -o -name "*.xml"`; \ - for i in $$uninstallfiles; do \ - i=`basename $$i`; \ - echo '-- Removing '$$i ; \ - rm -f $(DESTDIR)$(THEME_DIR)/$$THEME/$(THEME_SUBDIR)/$$i ; \ - done); \ - rmdir $(DESTDIR)$(THEME_DIR)/$$THEME/$(THEME_SUBDIR) || :; \ - rmdir $(DESTDIR)$(THEME_DIR)/$$THEME || :; \ - done - -rmdir $(DESTDIR)$(THEME_DIR) - -dist-hook: - mkdir $(distdir)/themes; \ - for THEME in $(THEMES); do \ - echo '-- Disting theme '$$THEME; \ - mkdir $(distdir)/$$THEME; \ - (installfiles=`find $(srcdir)/$$THEME -name "*.png" -o -name "*.xml"`; \ - for i in $$installfiles; do \ - echo '-- Disting '$$i ; \ - cp $$i $(distdir)/$$THEME; \ - done) \ - done diff --git a/src/themes/Metabox/metacity-theme-1.xml b/src/themes/Metabox/metacity-theme-1.xml deleted file mode 100644 index ac90a3f9..00000000 --- a/src/themes/Metabox/metacity-theme-1.xml +++ /dev/null @@ -1,479 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> - <info> - <name>Metabox</name> - <author>Garrett LeSage <garrett@redhat.com> based on Havoc Pennington <hp@redhat.com>'s Atlanta theme</author> - <copyright>Â Garrett LeSage, Havoc Pennington, 2002</copyright> - <date>Jun 12, 2002</date> - <description>Looks a little like BlackBox.</description> - </info> - - <frame_geometry name="normal"> - <distance name="left_width" value="1"/> - <distance name="right_width" value="1"/> - <distance name="bottom_height" value="6"/> - <distance name="left_titlebar_edge" value="1"/> - <distance name="right_titlebar_edge" value="1"/> - <distance name="title_vertical_pad" value="3"/> - <border name="title_border" left="0" right="0" top="1" bottom="1"/> - <border name="button_border" left="0" right="0" top="1" bottom="1"/> - <aspect_ratio name="button" value="1.0"/> - </frame_geometry> - - <!-- strip borders off the normal geometry --> - <frame_geometry name="normal_small_borders" parent="normal"> - <distance name="left_width" value="0"/> - <distance name="right_width" value="0"/> - <distance name="bottom_height" value="0"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - </frame_geometry> - - <frame_geometry name="utility" title_scale="small"> - <distance name="left_width" value="1"/> - <distance name="right_width" value="1"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="1"/> - <distance name="right_titlebar_edge" value="1"/> - <distance name="title_vertical_pad" value="1"/> - <border name="title_border" left="0" right="0" top="1" bottom="1"/> - <border name="button_border" left="0" right="0" top="1" bottom="1"/> - <aspect_ratio name="button" value="1.0"/> - </frame_geometry> - - <frame_geometry name="border" has_title="false"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="4"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> - </frame_geometry> - - <!-- define constants --> - <constant name="ArrowWidth" value="7"/> - <constant name="ArrowHeight" value="5"/> - <constant name="ButtonIPad" value="4"/> - <constant name="ThickLineWidth" value="3"/> - <constant name="IconTitleSpacing" value="2"/> - <constant name="SpacerWidth" value="8"/> - <constant name="SpacerHeight" value="11"/> - - <!-- Backgrounds --> - - <draw_ops name="bg_active"> - <gradient type="vertical" x="0" y="0" width="width" height="height"> - <color value="shade/gtk:bg[SELECTED]/1.25"/> - <color value="shade/gtk:bg[SELECTED]/0.85"/> - </gradient> - </draw_ops> - - <draw_ops name="bg_inactive"> - <gradient type="vertical" x="0" y="0" width="width" height="height"> - <color value="shade/gtk:bg[INSENSITIVE]/1.1"/> - <color value="shade/gtk:bg[INSENSITIVE]/0.9"/> - </gradient> - </draw_ops> - - <draw_ops name="bg_button_active"> - <include name="bg_active"/> - </draw_ops> - - <draw_ops name="bg_button_inactive"> - <include name="bg_inactive"/> - </draw_ops> - - <draw_ops name="bg_title_active"> - <include name="bg_active"/> - </draw_ops> - - <draw_ops name="bg_title_inactive"> - <include name="bg_inactive"/> - </draw_ops> - - <!-- Buttons --> - - <draw_ops name="button_pressed_bg"> - <gradient type="vertical" x="0" y="0" width="width" height="height" alpha="0.25"> - <color value="shade/gtk:bg[SELECTED]/0.75"/> - <color value="shade/gtk:bg[SELECTED]/0.5"/> - </gradient> - </draw_ops> - - <draw_ops name="button_prelight_bg"> - <gradient type="vertical" x="0" y="0" width="width" height="height" alpha="0.25"> - <color value="shade/gtk:bg[SELECTED]/2.0"/> - <color value="shade/gtk:bg[SELECTED]/1.5"/> - </gradient> - </draw_ops> - - <draw_ops name="menu_button"> - <include name="bg_button_active"/> - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" width="2" x1="ButtonIPad+1" y1="width/2+2" x2="(width-ButtonIPad)/2+1" y2="width/2+2"/> - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" width="2" x1="ButtonIPad+1" y1="width/2-2" x2="(width-ButtonIPad)/2+1" y2="width/2-2"/> - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" width="2" x1="width-ButtonIPad-1" y1="width/2+2" x2="width-(width-ButtonIPad)/2-1" y2="width/2+2"/> - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" width="2" x1="width-ButtonIPad-1" y1="width/2-2" x2="width-(width-ButtonIPad)/2-1" y2="width/2-2"/> - </draw_ops> - - <draw_ops name="menu_button_pressed"> - <include name="menu_button"/> - <include name="button_pressed_bg"/> - </draw_ops> - - <draw_ops name="menu_button_prelight"> - <include name="menu_button"/> - <include name="button_prelight_bg"/> - </draw_ops> - - <draw_ops name="menu_button_unfocused"> - <include name="bg_button_inactive"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" width="2" x1="ButtonIPad+1" y1="width/2+2" x2="(width-ButtonIPad)/2+1" y2="width/2+2"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" width="2" x1="ButtonIPad+1" y1="width/2-2" x2="(width-ButtonIPad)/2+1" y2="width/2-2"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" width="2" x1="width-ButtonIPad-1" y1="width/2+2" x2="width-(width-ButtonIPad)/2-1" y2="width/2+2"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" width="2" x1="width-ButtonIPad-1" y1="width/2-2" x2="width-(width-ButtonIPad)/2-1" y2="width/2-2"/> - </draw_ops> - - <draw_ops name="minimize_button"> - <include name="bg_button_active"/> - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" - x1="ButtonIPad" - y1="height - ButtonIPad - ThickLineWidth + 1" - x2="width - ButtonIPad" - y2="height - ButtonIPad - ThickLineWidth + 1" - width="3"/> <!-- FIXME allow a constant here --> - </draw_ops> - - <draw_ops name="minimize_button_pressed"> - <include name="minimize_button"/> - <include name="button_pressed_bg"/> - </draw_ops> - - <draw_ops name="minimize_button_prelight"> - <include name="minimize_button"/> - <include name="button_prelight_bg"/> - </draw_ops> - - <draw_ops name="minimize_button_unfocused"> - <include name="bg_button_inactive"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" - x1="ButtonIPad" - y1="height - ButtonIPad - ThickLineWidth + 1" - x2="width - ButtonIPad" - y2="height - ButtonIPad - ThickLineWidth + 1" - width="3"/> <!-- FIXME allow a constant here --> - </draw_ops> - - <draw_ops name="maximize_button"> - <include name="bg_button_active"/> - <rectangle color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" filled="false" - x="ButtonIPad" y="ButtonIPad" width="width-ButtonIPad*2-1" height="height-ButtonIPad*2-1"/> - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" width="3" - x1="ButtonIPad" y1="ButtonIPad+1" x2="width-ButtonIPad" y2="ButtonIPad+1"/> - </draw_ops> - - <draw_ops name="maximize_button_pressed"> - <include name="maximize_button"/> - <include name="button_pressed_bg"/> - </draw_ops> - - <draw_ops name="maximize_button_prelight"> - <include name="maximize_button"/> - <include name="button_prelight_bg"/> - </draw_ops> - - <draw_ops name="maximize_button_unfocused"> - <include name="bg_button_inactive"/> - <rectangle color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" filled="false" - x="ButtonIPad" y="ButtonIPad" width="width-ButtonIPad*2-1" height="height-ButtonIPad*2-1"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" width="3" - x1="ButtonIPad" y1="ButtonIPad+1" x2="width-ButtonIPad" y2="ButtonIPad+1"/> - </draw_ops> - - <draw_ops name="mini_window_icon"> - <rectangle color="gtk:bg[SELECTED]" filled="true" - x="0" y="0" width="width-1" height="height-1"/> - <rectangle color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" filled="false" - x="0" y="0" width="width-1" height="height-1"/> - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" width="2" - x1="0" y1="1" x2="width" y2="1"/> - </draw_ops> - - <draw_ops name="mini_window_icon_unfocused"> - <rectangle color="gtk:bg[NORMAL]" filled="true" - x="0" y="0" width="width-1" height="height-1"/> - <rectangle color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" filled="false" - x="0" y="0" width="width-1" height="height-1"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" width="2" - x1="0" y1="1" x2="width" y2="1"/> - </draw_ops> - - <draw_ops name="restore_button"> - <include name="bg_button_active"/> - <include name="mini_window_icon" - x="3 + ButtonIPad" y="ButtonIPad" - width="width - 7 - ButtonIPad" - height="height - 7 - ButtonIPad"/> - <include name="mini_window_icon" - x="ButtonIPad" y="3 + ButtonIPad" - width="width - 7 - ButtonIPad" - height="height - 7 - ButtonIPad"/> - </draw_ops> - - <draw_ops name="restore_button_pressed"> - <include name="restore_button"/> - <include name="button_pressed_bg"/> - </draw_ops> - - <draw_ops name="restore_button_prelight"> - <include name="restore_button"/> - <include name="button_prelight_bg"/> - </draw_ops> - - <draw_ops name="restore_button_unfocused"> - <include name="bg_button_inactive"/> - <include name="mini_window_icon_unfocused" - x="3 + ButtonIPad" y="ButtonIPad" - width="width - 7 - ButtonIPad" - height="height - 7 - ButtonIPad"/> - <include name="mini_window_icon_unfocused" - x="ButtonIPad" y="3 + ButtonIPad" - width="width - 7 - ButtonIPad" - height="height - 7 - ButtonIPad"/> - </draw_ops> - - <draw_ops name="close_button"> - <include name="bg_button_active"/> - <!-- draw longer lines and clip for 'x' with symmetrical endpoints <joefefifo@yahoo.com> --> - <clip x="ButtonIPad" y="ButtonIPad" - width="width - ButtonIPad - 4" - height="height - ButtonIPad - 4"/> - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" - width="2" - x1="ButtonIPad" y1="ButtonIPad" - x2="width - ButtonIPad" y2="height - ButtonIPad"/> - - <line color="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.75" - width="2" - x1="ButtonIPad" y1="height - ButtonIPad - 1" - x2="width - ButtonIPad" y2="ButtonIPad - 1"/> - </draw_ops> - - <draw_ops name="close_button_pressed"> - <include name="close_button"/> - <include name="button_pressed_bg"/> - </draw_ops> - - <draw_ops name="close_button_prelight"> - <include name="close_button"/> - <include name="button_prelight_bg"/> - </draw_ops> - - <draw_ops name="close_button_unfocused"> - <include name="bg_button_inactive"/> - <!-- draw longer lines and clip for 'x' with symmetrical endpoints <joefefifo@yahoo.com> --> - <clip x="ButtonIPad" y="ButtonIPad" - width="width - ButtonIPad - 4" - height="height - ButtonIPad - 4"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" - width="2" - x1="ButtonIPad" y1="ButtonIPad" - x2="width - ButtonIPad" y2="height - ButtonIPad"/> - <line color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" - width="2" - x1="ButtonIPad" y1="height - ButtonIPad - 1" - x2="width - ButtonIPad" y2="ButtonIPad - 1"/> - </draw_ops> - - <draw_ops name="outer_bevel"> - <rectangle color="#000000" - x="0" y="0" width="width-1" height="height-1"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="1" y2="height-2"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="width-2" y2="1"/> - <line color="gtk:dark[NORMAL]" - x1="width-2" y1="1" x2="width-2" y2="height-2"/> - <line color="gtk:dark[NORMAL]" - x1="1" y1="height-2" x2="width-2" y2="height-2"/> - </draw_ops> - - <draw_ops name="blank"> - <!-- nothing --> - </draw_ops> - - <draw_ops name="focus_outline"> - <rectangle color="#000000" - x="left_width-1" y="top_height-1" - width="width-left_width-right_width+1" - height="height-top_height-bottom_height+1"/> - </draw_ops> - - <draw_ops name="focus_background"> - <include name="outer_bevel"/> - <include name="focus_outline"/> - </draw_ops> - - <draw_ops name="title_text_focused_with_icon"> - <clip x="0" y="0" width="width" height="height"/> - <title color="gtk:fg[SELECTED]" - x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing" - y="((height - title_height) / 2) `max` 0"/> - <icon x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2" - y="(height-mini_icon_height) / 2" - width="mini_icon_width" height="mini_icon_height"/> - </draw_ops> - - <draw_ops name="title_text_focused_no_icon"> - <clip x="0" y="0" width="width" height="height"/> - <title color="gtk:fg[SELECTED]" - x="(0 `max` (width-title_width)) / 2" - y="((height - title_height) / 2) `max` 0"/> - </draw_ops> - - <draw_ops name="title_text_with_icon"> - <clip x="0" y="0" width="width" height="height"/> - <title color="gtk:fg[INSENSITIVE]" - x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing" - y="((height - title_height) / 2) `max` 0"/> - <icon x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2" - y="(height-mini_icon_height) / 2" - width="mini_icon_width" height="mini_icon_height"/> - </draw_ops> - - <draw_ops name="title_text_no_icon"> - <clip x="0" y="0" width="width" height="height"/> - <title color="blend/gtk:fg[INSENSITIVE]/gtk:bg[INSENSITIVE]/0.35" - x="(0 `max` (width-title_width)) / 2" - y="((height - title_height) / 2) `max` 0"/> - </draw_ops> - - <draw_ops name="title_normal"> - <include name="bg_title_inactive"/> - <include name="title_text_no_icon"/> - </draw_ops> - - <draw_ops name="title_focused"> - <include name="bg_title_active"/> - <include name="title_text_focused_no_icon"/> - </draw_ops> - - <draw_ops name="title_utility"> - <include name="title_text_no_icon"/> - </draw_ops> - - <draw_ops name="title_utility_focused"> - <include name="bg_title_active"/> - <include name="title_text_focused_no_icon"/> - </draw_ops> - - <frame_style name="normal_unfocused" geometry="normal"> - <piece position="entire_background" draw_ops="focus_background"/> - <piece position="title" draw_ops="title_normal"/> - - <!-- we don't specify for prelight, so normal is used --> - <button function="close" state="normal" draw_ops="close_button_unfocused"/> - <button function="close" state="pressed" draw_ops="close_button_pressed"/> - <button function="minimize" state="normal" draw_ops="minimize_button_unfocused"/> - <button function="minimize" state="pressed" draw_ops="minimize_button_pressed"/> - <button function="maximize" state="normal" draw_ops="maximize_button_unfocused"/> - <button function="maximize" state="pressed" draw_ops="maximize_button_pressed"/> - <button function="menu" state="normal" draw_ops="menu_button_unfocused"/> - <button function="menu" state="pressed" draw_ops="menu_button_pressed"/> - </frame_style> - - <frame_style name="normal_focused" geometry="normal"> - <piece position="entire_background" draw_ops="focus_background"/> - <piece position="title" draw_ops="title_focused"/> - - <!-- we don't specify for prelight, so normal is used --> - <button function="close" state="normal" draw_ops="close_button"/> - <button function="close" state="pressed" draw_ops="close_button_pressed"/> - <button function="close" state="prelight" draw_ops="close_button_prelight"/> - <button function="minimize" state="normal" draw_ops="minimize_button"/> - <button function="minimize" state="pressed" draw_ops="minimize_button_pressed"/> - <button function="minimize" state="prelight" draw_ops="minimize_button_prelight"/> - <button function="maximize" state="normal" draw_ops="maximize_button"/> - <button function="maximize" state="pressed" draw_ops="maximize_button_pressed"/> - <button function="maximize" state="prelight" draw_ops="maximize_button_prelight"/> - <button function="menu" state="normal" draw_ops="menu_button"/> - <button function="menu" state="pressed" draw_ops="menu_button_pressed"/> - <button function="menu" state="prelight" draw_ops="menu_button_prelight"/> - </frame_style> - - <frame_style name="maximized_unfocused" geometry="normal_small_borders" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="blank"/> - <button function="maximize" state="normal" draw_ops="restore_button_unfocused"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> - </frame_style> - - <frame_style name="maximized_focused" geometry="normal_small_borders" parent="normal_focused"> - <piece position="entire_background" draw_ops="focus_outline"/> - <button function="maximize" state="normal" draw_ops="restore_button"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> - <button function="maximize" state="prelight" draw_ops="restore_button_prelight"/> - </frame_style> - - <frame_style name="utility_unfocused" geometry="utility" parent="normal_unfocused"> - <piece position="title" draw_ops="title_utility"/> - </frame_style> - - <frame_style name="utility_focused" geometry="utility" parent="normal_focused"> - <piece position="title" draw_ops="title_utility_focused"/> - </frame_style> - - <frame_style name="border" geometry="border" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="outer_bevel"/> - <piece position="title" draw_ops="blank"/> - </frame_style> - - <frame_style_set name="normal"> - <frame focus="yes" state="normal" resize="both" style="normal_focused"/> - <frame focus="no" state="normal" resize="both" style="normal_unfocused"/> - <frame focus="yes" state="maximized" style="maximized_focused"/> - <frame focus="no" state="maximized" style="maximized_unfocused"/> - <frame focus="yes" state="shaded" style="normal_focused"/> - <frame focus="no" state="shaded" style="normal_unfocused"/> - <frame focus="yes" state="maximized_and_shaded" style="maximized_focused"/> - <frame focus="no" state="maximized_and_shaded" style="maximized_unfocused"/> - </frame_style_set> - - <frame_style_set name="utility" parent="normal"> - <frame focus="yes" state="normal" resize="both" style="utility_focused"/> - <frame focus="no" state="normal" resize="both" style="utility_unfocused"/> - <!-- this is a bunch of crack since utility windows shouldn't be maximized --> - <frame focus="yes" state="maximized" style="utility_focused"/> - <frame focus="no" state="maximized" style="utility_unfocused"/> - <frame focus="yes" state="shaded" style="utility_focused"/> - <frame focus="no" state="shaded" style="utility_unfocused"/> - <frame focus="yes" state="maximized_and_shaded" style="utility_focused"/> - <frame focus="no" state="maximized_and_shaded" style="utility_unfocused"/> - </frame_style_set> - - <frame_style_set name="border"> - <frame focus="yes" state="normal" resize="both" style="border"/> - <frame focus="no" state="normal" resize="both" style="border"/> - <frame focus="yes" state="maximized" style="border"/> - <frame focus="no" state="maximized" style="border"/> - <frame focus="yes" state="shaded" style="border"/> - <frame focus="no" state="shaded" style="border"/> - <frame focus="yes" state="maximized_and_shaded" style="border"/> - <frame focus="no" state="maximized_and_shaded" style="border"/> - </frame_style_set> - - <window type="normal" style_set="normal"/> - <window type="dialog" style_set="normal"/> - <window type="modal_dialog" style_set="normal"/> - <window type="menu" style_set="normal"/> - <window type="utility" style_set="utility"/> - <window type="border" style_set="border"/> - - <menu_icon function="close" state="normal" draw_ops="close_button"/> - <menu_icon function="maximize" state="normal" draw_ops="maximize_button"/> - <menu_icon function="unmaximize" state="normal" draw_ops="restore_button"/> - <menu_icon function="minimize" state="normal" draw_ops="minimize_button"/> - -</metacity_theme> diff --git a/src/themes/Simple/close.png b/src/themes/Simple/close.png Binary files differdeleted file mode 100644 index 3c29292d..00000000 --- a/src/themes/Simple/close.png +++ /dev/null diff --git a/src/themes/Simple/maximize.png b/src/themes/Simple/maximize.png Binary files differdeleted file mode 100644 index e487352b..00000000 --- a/src/themes/Simple/maximize.png +++ /dev/null diff --git a/src/themes/Simple/maximized.png b/src/themes/Simple/maximized.png Binary files differdeleted file mode 100644 index 5e3ad4c5..00000000 --- a/src/themes/Simple/maximized.png +++ /dev/null diff --git a/src/themes/Simple/metacity-theme-1.xml b/src/themes/Simple/metacity-theme-1.xml deleted file mode 100644 index ec97ce86..00000000 --- a/src/themes/Simple/metacity-theme-1.xml +++ /dev/null @@ -1,346 +0,0 @@ -<?xml version="1.0"?> -<metacity_theme> -<info> - <name>Simple</name> - <author>Tuomas Kuosmanen <tigert@ximian.com></author> - <copyright>Â Tuomas Kuosmanen, 2002, based on Atlanta theme by Havoc.</copyright> - <date>April, 2002</date> - <description>Default GNOME window theme</description> -</info> - -<frame_geometry name="normal"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="2"/> - <distance name="right_titlebar_edge" value="2"/> - <distance name="button_width" value="16"/> - <distance name="button_height" value="16"/> - <distance name="title_vertical_pad" value="0"/> - <border name="title_border" left="1" right="1" top="2" bottom="2"/> - <border name="button_border" left="1" right="1" top="0" bottom="0"/> -</frame_geometry> - -<!-- strip borders off the normal geometry --> -<frame_geometry name="normal_small_borders" parent="normal"> - <distance name="left_width" value="0"/> - <distance name="right_width" value="0"/> - <distance name="bottom_height" value="0"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> -</frame_geometry> - -<frame_geometry name="utility" title_scale="xx-small"> - <distance name="left_width" value="3"/> - <distance name="right_width" value="3"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="3"/> - <distance name="right_titlebar_edge" value="3"/> - <distance name="button_width" value="16"/> - <distance name="button_height" value="16"/> - <distance name="title_vertical_pad" value="1"/> - <border name="title_border" left="3" right="4" top="3" bottom="3"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<frame_geometry name="border" has_title="false"> - <distance name="left_width" value="4"/> - <distance name="right_width" value="4"/> - <distance name="bottom_height" value="4"/> - <distance name="left_titlebar_edge" value="0"/> - <distance name="right_titlebar_edge" value="0"/> - <distance name="button_width" value="0"/> - <distance name="button_height" value="0"/> - <distance name="title_vertical_pad" value="4"/> - <border name="title_border" left="0" right="0" top="0" bottom="0"/> - <border name="button_border" left="0" right="0" top="0" bottom="0"/> -</frame_geometry> - -<!-- define constants --> -<constant name="ArrowWidth" value="8"/> -<constant name="ArrowHeight" value="4"/> -<constant name="ButtonIPad" value="4"/> -<constant name="ThickLineWidth" value="3"/> -<constant name="IconTitleSpacing" value="6"/> -<constant name="SpacerWidth" value="2"/> -<constant name="SpacerHeight" value="10"/> - -<!-- Buttons --> - -<draw_ops name="button_pressed_bg"> - <rectangle color="gtk:light[NORMAL]" filled="true" - x="1" y="1" width="width" height="height"/> - <rectangle color="gtk:dark[NORMAL]" filled="true" - x="0" y="0" width="width - 1" height="height - 1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.9" filled="true" - x="1" y="1" width="width - 2" height="height - 2"/> - <!-- gtk_box state="active" shadow="out" x="0" y="0" width="width" height="height"/ --> -</draw_ops> - -<draw_ops name="menu_button"> - <icon x="1" - y="1" - width="width-2" height="height-2"/> -</draw_ops> - -<draw_ops name="menu_button_pressed"> - <include name="menu_button"/> -</draw_ops> - -<draw_ops name="minimize_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" - y1="height - ButtonIPad - ThickLineWidth + 3" - x2="width" - y2="height - ButtonIPad - ThickLineWidth + 3" - width="2"/> -</draw_ops> - -<draw_ops name="minimize_button_pressed"> - <include name="button_pressed_bg"/> - <include name="minimize_button"/> -</draw_ops> - -<draw_ops name="maximize_button"> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="ButtonIPad" y="ButtonIPad" width="width-ButtonIPad*2 + 2" - height="height-ButtonIPad*2 + 1"/> - <line color="gtk:fg[NORMAL]" width="2" - x1="ButtonIPad" y1="ButtonIPad+1" x2="width-ButtonIPad + 2" - y2="ButtonIPad+2"/> -</draw_ops> - -<draw_ops name="maximize_button_pressed"> - <include name="button_pressed_bg"/> - <include name="maximize_button"/> -</draw_ops> - -<draw_ops name="mini_window_icon"> - <rectangle color="gtk:bg[NORMAL]" filled="true" - x="0" y="0" width="width-1" height="height-1"/> - <rectangle color="gtk:fg[NORMAL]" filled="false" - x="0" y="0" width="width-1" height="height-1"/> - <line color="gtk:fg[NORMAL]" width="2" x1="0" y1="1" x2="width" y2="1"/> -</draw_ops> - -<draw_ops name="restore_button"> - <include name="mini_window_icon" - x="3 + ButtonIPad" y="3 + ButtonIPad" - width="width - 5 - ButtonIPad" - height="height - 5 - ButtonIPad"/> - <include name="mini_window_icon" - x="ButtonIPad" y="ButtonIPad" - width="width - 5 - ButtonIPad" - height="height - 5 - ButtonIPad"/> -</draw_ops> - -<draw_ops name="restore_button_pressed"> - <include name="button_pressed_bg"/> - <include name="restore_button"/> -</draw_ops> - -<draw_ops name="close_button"> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad" y1="ButtonIPad" - x2="width - ButtonIPad + 1" y2="height - ButtonIPad + 1" width="3"/> - <line color="gtk:fg[NORMAL]" - x1="ButtonIPad - 1" y1="height - ButtonIPad" - x2="width - ButtonIPad + 1" y2="ButtonIPad" width="3"/> -</draw_ops> - -<draw_ops name="close_button_pressed"> - <include name="button_pressed_bg"/> - <include name="close_button"/> -</draw_ops> - -<draw_ops name="outer_bevel"> - <rectangle color="gtk:fg[NORMAL]" - x="0" y="0" width="width" height="height" filled="true"/> - <rectangle color="gtk:bg[NORMAL]" - x="1" y="1" width="width-2" height="height-2" filled="true"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="1" y2="height-3"/> - <line color="gtk:light[NORMAL]" - x1="1" y1="1" x2="width-3" y2="1"/> - <line color="gtk:dark[NORMAL]" - x1="width-2" y1="2" x2="width-2" y2="height-2"/> - <line color="gtk:dark[NORMAL]" - x1="2" y1="height-2" x2="width-3" y2="height-2"/> -</draw_ops> - -<draw_ops name="blank"> -<!-- nothing --> -</draw_ops> - -<draw_ops name="focus_outline"> - <rectangle color="gtk:dark[NORMAL]" - x="left_width-1" y="top_height-1" - width="width-left_width-right_width+1" - height="height-top_height-bottom_height+1"/> -</draw_ops> - -<draw_ops name="focus_background"> - <include name="outer_bevel"/> -</draw_ops> - -<draw_ops name="title_tile"> - <line color="gtk:bg[SELECTED]" x1="0" y1="0" x2="width" y2="0"/> - <line color="blend/gtk:bg[SELECTED]/#000000/0.1" x1="0" y1="1" x2="width" y2="1"/> -</draw_ops> - -<draw_ops name="title_tile_unfocused"> - <line color="blend/gtk:bg[NORMAL]/#000000/0.1" x1="0" y1="0" x2="width" y2="0"/> - <line color="blend/gtk:bg[NORMAL]/#ffffff/0.2" x1="0" y1="1" x2="width" y2="1"/> -</draw_ops> - -<draw_ops name="title_bg"> - <tile name="title_tile" tile_width="width" tile_height="2" x="0" y="0" width="width" height="height"/> - <rectangle color="blend/gtk:bg[SELECTED]/#000000/0.6" filled="false" x="0" y="0" width="width-1" height="height-1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.5" filled="true" x="0" y="0" width="1" height="1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.5" filled="true" x="width-1" y="0" width="1" height="1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.5" filled="true" x="0" y="height-1" width="1" height="1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.5" filled="true" x="width-1" y="height-1" width="1" height="1"/> -</draw_ops> - -<draw_ops name="title_bg_unfocused"> - <tile name="title_tile_unfocused" tile_width="width" tile_height="2" x="0" y="0" width="width-1" height="height-1"/> - <rectangle color="blend/#000000/gtk:fg[NORMAL]/0.7" filled="false" x="0" y="0" width="width-1" height="height-1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.8" filled="true" x="0" y="0" width="1" height="1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.8" filled="true" x="width-1" y="0" width="1" height="1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.8" filled="true" x="0" y="height-1" width="1" height="1"/> - <rectangle color="blend/#000000/gtk:bg[NORMAL]/0.8" filled="true" x="width-1" y="height-1" width="1" height="1"/> -</draw_ops> - -<draw_ops name="title_text_focused"> - <clip x="0" y="0" width="width-SpacerWidth" height="height"/> - <title color="blend/gtk:fg[SELECTED]/#000000/0.7" - x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing + 1" - y="((height - title_height) / 2) `max` 0 + 1"/> - <title color="gtk:fg[SELECTED]" - x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing" - y="((height - title_height) / 2) `max` 0"/> -</draw_ops> - -<draw_ops name="title_text"> - <clip x="0" y="0" width="width-SpacerWidth" height="height"/> - <title color="gtk:fg[NORMAL]" - x="(0 `max` (width-title_width-mini_icon_width-IconTitleSpacing)) / 2 + mini_icon_width + IconTitleSpacing" - y="((height - title_height) / 2) `max` 0"/> -</draw_ops> - -<draw_ops name="title_normal"> - <include name="title_bg_unfocused"/> - <include name="title_text"/> -</draw_ops> - -<draw_ops name="title_focused"> - <include name="title_bg"/> - <include name="title_text_focused"/> -</draw_ops> - -<draw_ops name="title_utility"> - <include name="title_text"/> -</draw_ops> - -<draw_ops name="title_utility_focused"> - <include name="title_bg"/> - <include name="title_text_focused"/> -</draw_ops> - -<frame_style name="normal_unfocused" geometry="normal"> - <piece position="entire_background" draw_ops="outer_bevel"/> - <piece position="title" draw_ops="title_normal"/> - - <!-- we don't specify for prelight, so normal is used --> - <button function="close" state="normal" draw_ops="close_button"/> - <button function="close" state="pressed" draw_ops="close_button_pressed"/> - <button function="minimize" state="normal" draw_ops="minimize_button"/> - <button function="minimize" state="pressed" draw_ops="minimize_button_pressed"/> - <button function="maximize" state="normal" draw_ops="maximize_button"/> - <button function="maximize" state="pressed" draw_ops="maximize_button_pressed"/> - <button function="menu" state="normal" draw_ops="menu_button"/> - <button function="menu" state="pressed" draw_ops="menu_button_pressed"/> -</frame_style> - -<frame_style name="normal_focused" geometry="normal" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="focus_background"/> - <piece position="title" draw_ops="title_focused"/> -</frame_style> - -<frame_style name="shaded_focused" geometry="normal" parent="normal_unfocused"> - <piece position="title" draw_ops="title_focused"/> -</frame_style> - -<frame_style name="maximized_unfocused" geometry="normal_small_borders" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="blank"/> - <button function="maximize" state="normal" draw_ops="restore_button"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="maximized_focused" geometry="normal_small_borders" parent="normal_focused"> - <piece position="entire_background" draw_ops="focus_outline"/> - <button function="maximize" state="normal" draw_ops="restore_button"/> - <button function="maximize" state="pressed" draw_ops="restore_button_pressed"/> -</frame_style> - -<frame_style name="utility_unfocused" geometry="utility" parent="normal_unfocused"> - <piece position="title" draw_ops="title_utility"/> -</frame_style> - -<frame_style name="utility_focused" geometry="utility" parent="normal_focused"> - <piece position="title" draw_ops="title_utility_focused"/> -</frame_style> - -<frame_style name="border" geometry="border" parent="normal_unfocused"> - <piece position="entire_background" draw_ops="outer_bevel"/> - <piece position="title" draw_ops="blank"/> -</frame_style> - -<frame_style_set name="normal"> -<frame focus="yes" state="normal" resize="both" style="normal_focused"/> -<frame focus="no" state="normal" resize="both" style="normal_unfocused"/> -<frame focus="yes" state="maximized" style="maximized_focused"/> -<frame focus="no" state="maximized" style="maximized_unfocused"/> -<frame focus="yes" state="shaded" style="shaded_focused"/> -<frame focus="no" state="shaded" style="normal_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="maximized_focused"/> -<frame focus="no" state="maximized_and_shaded" style="maximized_unfocused"/> -</frame_style_set> - -<frame_style_set name="utility" parent="normal"> -<frame focus="yes" state="normal" resize="both" style="utility_focused"/> -<frame focus="no" state="normal" resize="both" style="utility_unfocused"/> -<!-- this is a bunch of crack since utility windows shouldn't be maximized --> -<frame focus="yes" state="maximized" style="utility_focused"/> -<frame focus="no" state="maximized" style="utility_unfocused"/> -<frame focus="yes" state="shaded" style="utility_focused"/> -<frame focus="no" state="shaded" style="utility_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="utility_focused"/> -<frame focus="no" state="maximized_and_shaded" style="utility_unfocused"/> -</frame_style_set> - -<frame_style_set name="border" parent="normal"> -<frame focus="yes" state="normal" resize="both" style="border"/> -<frame focus="no" state="normal" resize="both" style="border"/> -<!-- this is a bunch of crack since utility windows shouldn't be maximized --> -<frame focus="yes" state="maximized" style="utility_focused"/> -<frame focus="no" state="maximized" style="utility_unfocused"/> -<frame focus="yes" state="shaded" style="utility_focused"/> -<frame focus="no" state="shaded" style="utility_unfocused"/> -<frame focus="yes" state="maximized_and_shaded" style="utility_focused"/> -<frame focus="no" state="maximized_and_shaded" style="utility_unfocused"/> -</frame_style_set> - -<window type="normal" style_set="normal"/> -<window type="dialog" style_set="normal"/> -<window type="modal_dialog" style_set="normal"/> -<window type="menu" style_set="normal"/> -<window type="utility" style_set="utility"/> -<window type="border" style_set="border"/> - -<menu_icon function="close" state="normal" draw_ops="close_button"/> -<menu_icon function="maximize" state="normal" draw_ops="maximize_button"/> -<menu_icon function="unmaximize" state="normal" draw_ops="restore_button"/> -<menu_icon function="minimize" state="normal" draw_ops="minimize_button"/> - -</metacity_theme> diff --git a/src/themes/Simple/minimize.png b/src/themes/Simple/minimize.png Binary files differdeleted file mode 100644 index 608a633d..00000000 --- a/src/themes/Simple/minimize.png +++ /dev/null diff --git a/src/tools/.cvsignore b/src/tools/.cvsignore deleted file mode 100644 index 8ecc6b5e..00000000 --- a/src/tools/.cvsignore +++ /dev/null @@ -1,8 +0,0 @@ -Makefile -Makefile.in -metacity-grayscale -metacity-message -metacity-mag -metacity-properties -metacity-properties.desktop -metacity-window-demo diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am deleted file mode 100644 index fe02c2ca..00000000 --- a/src/tools/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -@INTLTOOL_DESKTOP_RULE@ - -icondir=$(pkgdatadir)/icons -icon_DATA=metacity-window-demo.png - -INCLUDES=@METACITY_WINDOW_DEMO_CFLAGS@ @METACITY_MESSAGE_CFLAGS@ \ - -DMETACITY_ICON_DIR=\"$(pkgdatadir)/icons\" \ - -DMETACITY_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" - -metacity_message_SOURCES= \ - metacity-message.c - -metacity_window_demo_SOURCES= \ - metacity-window-demo.c - -metacity_mag_SOURCES= \ - metacity-mag.c - -metacity_grayscale_SOURCES= \ - metacity-grayscale.c - -bin_PROGRAMS=metacity-message metacity-window-demo - -## cheesy hacks I use, don't really have any business existing. ;-) -noinst_PROGRAMS=metacity-mag metacity-grayscale - -metacity_message_LDADD= @METACITY_MESSAGE_LIBS@ -metacity_window_demo_LDADD= @METACITY_WINDOW_DEMO_LIBS@ -metacity_mag_LDADD= @METACITY_WINDOW_DEMO_LIBS@ -metacity_grayscale_LDADD = @METACITY_WINDOW_DEMO_LIBS@ - -EXTRA_DIST=$(icon_DATA) - diff --git a/src/tools/metacity-grayscale.c b/src/tools/metacity-grayscale.c deleted file mode 100644 index 8d0cd68c..00000000 --- a/src/tools/metacity-grayscale.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Hack for grayscaling an image */ - -/* - * Copyright (C) 2002 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <unistd.h> -#include <stdlib.h> -#include <math.h> - -#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) - -static GdkPixbuf* -grayscale_pixbuf (GdkPixbuf *pixbuf) -{ - GdkPixbuf *gray; - guchar *pixels; - int rowstride; - int pixstride; - int row; - int n_rows; - int width; - - gray = gdk_pixbuf_copy (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (gray); - pixstride = gdk_pixbuf_get_has_alpha (gray) ? 4 : 3; - - pixels = gdk_pixbuf_get_pixels (gray); - n_rows = gdk_pixbuf_get_height (gray); - width = gdk_pixbuf_get_width (gray); - - row = 0; - while (row < n_rows) - { - guchar *p = pixels + row * rowstride; - guchar *end = p + (pixstride * width); - - while (p != end) - { - double v = INTENSITY (p[0], p[1], p[2]); - - p[0] = (guchar) v; - p[1] = (guchar) v; - p[2] = (guchar) v; - - p += pixstride; - } - - ++row; - } - - return gray; -} - -int -main (int argc, char **argv) -{ - GdkPixbuf *pixbuf; - GdkPixbuf *gray; - GError *err; - - if (argc != 2) - { - g_printerr ("specify a single image on the command line\n"); - return 1; - } - - g_type_init (); - - err = NULL; - pixbuf = gdk_pixbuf_new_from_file (argv[1], &err); - if (err != NULL) - { - g_printerr ("failed to load image: %s\n", err->message); - g_error_free (err); - return 1; - } - - gray = grayscale_pixbuf (pixbuf); - - err = NULL; - gdk_pixbuf_save (gray, "grayscale.png", "png", &err, NULL); - if (err != NULL) - { - g_printerr ("failed to save image: %s\n", err->message); - g_error_free (err); - return 1; - } - - g_print ("wrote grayscale.png\n"); - - return 0; -} diff --git a/src/tools/metacity-mag.c b/src/tools/metacity-mag.c deleted file mode 100644 index a5f1b1b2..00000000 --- a/src/tools/metacity-mag.c +++ /dev/null @@ -1,285 +0,0 @@ -/* Hack for use instead of xmag */ - -/* - * Copyright (C) 2002 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#define _GNU_SOURCE -#define _XOPEN_SOURCE 600 /* C99 -- for rint() */ - -#include <gtk/gtk.h> -#include <gdk/gdkx.h> -#include <gdk/gdkkeysyms.h> -#include <unistd.h> -#include <stdlib.h> -#include <math.h> - -static GtkWidget *grab_widget = NULL; -static GtkWidget *display_window = NULL; -static int last_grab_x = 0; -static int last_grab_y = 0; -static int last_grab_width = 150; -static int last_grab_height = 150; -static GtkAllocation last_grab_allocation; -static double width_factor = 4.0; -static double height_factor = 4.0; -static GdkInterpType interp_mode = GDK_INTERP_NEAREST; -static guint regrab_idle_id = 0; - -static GdkPixbuf* -get_pixbuf (void) -{ - GdkPixbuf *screenshot; - GdkPixbuf *magnified; - -#if 0 - g_print ("Size %d x %d\n", - last_grab_width, last_grab_height); -#endif - - screenshot = gdk_pixbuf_get_from_drawable (NULL, gdk_get_default_root_window (), - NULL, - last_grab_x, last_grab_y, 0, 0, - last_grab_width, last_grab_height); - - if (screenshot == NULL) - { - g_printerr ("Screenshot failed\n"); - exit (1); - } - - magnified = gdk_pixbuf_scale_simple (screenshot, last_grab_width * width_factor, - last_grab_height * height_factor, - interp_mode); - - - g_object_unref (G_OBJECT (screenshot)); - - return magnified; -} - -static gboolean -regrab_idle (GtkWidget *image) -{ - GdkPixbuf *magnified; - - if (image->allocation.width != last_grab_allocation.width || - image->allocation.height != last_grab_allocation.height) - { - last_grab_width = rint (image->allocation.width / width_factor); - last_grab_height = rint (image->allocation.height / height_factor); - last_grab_allocation = image->allocation; - - magnified = get_pixbuf (); - - gtk_image_set_from_pixbuf (GTK_IMAGE (image), magnified); - - g_object_unref (G_OBJECT (magnified)); - } - - regrab_idle_id = 0; - - return FALSE; -} - -static void -image_resized (GtkWidget *image) -{ - if (regrab_idle_id == 0) - regrab_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, (GSourceFunc) regrab_idle, - image, NULL); -} - -static void -grab_area_at_mouse (GtkWidget *invisible, - int x_root, - int y_root) -{ - GdkPixbuf *magnified; - int width, height; - GtkWidget *widget; - - width = last_grab_width; - height = last_grab_height; - - last_grab_x = x_root; - last_grab_y = y_root; - last_grab_width = width; - last_grab_height = height; - - magnified = get_pixbuf (); - - display_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size (GTK_WINDOW (display_window), - last_grab_width, last_grab_height); - widget = gtk_image_new_from_pixbuf (magnified); - gtk_widget_set_size_request (widget, 40, 40); - gtk_container_add (GTK_CONTAINER (display_window), widget); - g_object_unref (G_OBJECT (magnified)); - - g_object_add_weak_pointer (G_OBJECT (display_window), - (gpointer) &display_window); - - g_signal_connect (G_OBJECT (display_window), "destroy", - G_CALLBACK (gtk_main_quit), NULL); - - g_signal_connect_after (G_OBJECT (widget), "size_allocate", G_CALLBACK (image_resized), NULL); - - gtk_widget_show_all (display_window); -} - -static void -shutdown_grab (void) -{ - gdk_keyboard_ungrab (gtk_get_current_event_time ()); - gdk_pointer_ungrab (gtk_get_current_event_time ()); - gtk_grab_remove (grab_widget); -} - -static void -mouse_motion (GtkWidget *invisible, - GdkEventMotion *event, - gpointer data) -{ - -} - -static gboolean -mouse_release (GtkWidget *invisible, - GdkEventButton *event, - gpointer data) -{ - if (event->button != 1) - return FALSE; - - grab_area_at_mouse (invisible, event->x_root, event->y_root); - - shutdown_grab (); - - gtk_signal_disconnect_by_func (GTK_OBJECT (invisible), - GTK_SIGNAL_FUNC (mouse_motion), NULL); - gtk_signal_disconnect_by_func (GTK_OBJECT (invisible), - GTK_SIGNAL_FUNC (mouse_release), NULL); - - return TRUE; -} - -/* Helper Functions */ - -static gboolean mouse_press (GtkWidget *invisible, - GdkEventButton *event, - gpointer data); - -static gboolean -key_press (GtkWidget *invisible, - GdkEventKey *event, - gpointer data) -{ - if (event->keyval == GDK_Escape) - { - shutdown_grab (); - - gtk_signal_disconnect_by_func (GTK_OBJECT (invisible), - GTK_SIGNAL_FUNC (mouse_press), - NULL); - gtk_signal_disconnect_by_func (GTK_OBJECT (invisible), - GTK_SIGNAL_FUNC (key_press), - NULL); - - return TRUE; - } - - return FALSE; -} - -static gboolean -mouse_press (GtkWidget *invisible, - GdkEventButton *event, - gpointer data) -{ - if (event->type == GDK_BUTTON_PRESS && - event->button == 1) - { - g_signal_connect (invisible, "motion_notify_event", - G_CALLBACK (mouse_motion), NULL); - g_signal_connect (invisible, "button_release_event", - G_CALLBACK (mouse_release), NULL); - gtk_signal_disconnect_by_func (GTK_OBJECT (invisible), - GTK_SIGNAL_FUNC (mouse_press), - NULL); - gtk_signal_disconnect_by_func (GTK_OBJECT (invisible), - GTK_SIGNAL_FUNC (key_press), - NULL); - return TRUE; - } - - return FALSE; -} - -static void -begin_area_grab (void) -{ - if (grab_widget == NULL) - { - grab_widget = gtk_invisible_new (); - - gtk_widget_add_events (grab_widget, - GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); - - gtk_widget_show (grab_widget); - } - - if (gdk_keyboard_grab (grab_widget->window, - FALSE, - gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS) - { - g_warning ("Failed to grab keyboard to do eyedropper"); - return; - } - - if (gdk_pointer_grab (grab_widget->window, - FALSE, - GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, - NULL, - NULL, - gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS) - { - gdk_keyboard_ungrab (GDK_CURRENT_TIME); - g_warning ("Failed to grab pointer to do eyedropper"); - return; - } - - gtk_grab_add (grab_widget); - - g_signal_connect (grab_widget, "button_press_event", - G_CALLBACK (mouse_press), NULL); - g_signal_connect (grab_widget, "key_press_event", - G_CALLBACK (key_press), NULL); -} - -int -main (int argc, char **argv) -{ - gtk_init (&argc, &argv); - - begin_area_grab (); - - gtk_main (); - - return 0; -} diff --git a/src/tools/metacity-message.c b/src/tools/metacity-message.c deleted file mode 100644 index 0df89912..00000000 --- a/src/tools/metacity-message.c +++ /dev/null @@ -1,187 +0,0 @@ -/* Metacity send-magic-messages app */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include <gtk/gtk.h> -#include <gdk/gdkx.h> -#include <stdlib.h> -#include <string.h> - -#include <libintl.h> -#define _(x) dgettext (GETTEXT_PACKAGE, x) -#define N_(x) x - - -static void -send_restart (void) -{ - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = gdk_display; - xev.xclient.window = gdk_x11_get_default_root_xwindow (); - xev.xclient.message_type = XInternAtom (gdk_display, - "_METACITY_RESTART_MESSAGE", - False); - xev.xclient.format = 32; - xev.xclient.data.l[0] = 0; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - - XSendEvent (gdk_display, - gdk_x11_get_default_root_xwindow (), - False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); - - XFlush (gdk_display); - XSync (gdk_display, False); -} - -static void -send_reload_theme (void) -{ - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = gdk_display; - xev.xclient.window = gdk_x11_get_default_root_xwindow (); - xev.xclient.message_type = XInternAtom (gdk_display, - "_METACITY_RELOAD_THEME_MESSAGE", - False); - xev.xclient.format = 32; - xev.xclient.data.l[0] = 0; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - - XSendEvent (gdk_display, - gdk_x11_get_default_root_xwindow (), - False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); - - XFlush (gdk_display); - XSync (gdk_display, False); -} - -static void -send_set_keybindings (gboolean enabled) -{ - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = gdk_display; - xev.xclient.window = gdk_x11_get_default_root_xwindow (); - xev.xclient.message_type = XInternAtom (gdk_display, - "_METACITY_SET_KEYBINDINGS_MESSAGE", - False); - xev.xclient.format = 32; - xev.xclient.data.l[0] = enabled; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - - XSendEvent (gdk_display, - gdk_x11_get_default_root_xwindow (), - False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); - - XFlush (gdk_display); - XSync (gdk_display, False); -} - -#ifdef WITH_VERBOSE_MODE -static void -send_toggle_verbose (void) -{ - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = gdk_display; - xev.xclient.window = gdk_x11_get_default_root_xwindow (); - xev.xclient.message_type = XInternAtom (gdk_display, - "_METACITY_TOGGLE_VERBOSE", - False); - xev.xclient.format = 32; - xev.xclient.data.l[0] = 0; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - - XSendEvent (gdk_display, - gdk_x11_get_default_root_xwindow (), - False, - SubstructureRedirectMask | SubstructureNotifyMask, - &xev); - - XFlush (gdk_display); - XSync (gdk_display, False); -} -#endif - -static void -usage (void) -{ - g_printerr (_("Usage: %s\n"), - "metacity-message (restart|reload-theme|enable-keybindings|disable-keybindings|toggle-verbose)"); - exit (1); -} - -int -main (int argc, char **argv) -{ - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - - gtk_init (&argc, &argv); - - if (argc < 2) - usage (); - - if (strcmp (argv[1], "restart") == 0) - send_restart (); - else if (strcmp (argv[1], "reload-theme") == 0) - send_reload_theme (); - else if (strcmp (argv[1], "enable-keybindings") == 0) - send_set_keybindings (TRUE); - else if (strcmp (argv[1], "disable-keybindings") == 0) - send_set_keybindings (FALSE); - else if (strcmp (argv[1], "toggle-verbose") == 0) - { -#ifndef WITH_VERBOSE_MODE - g_printerr (_("Metacity was compiled without support for verbose mode\n")); - return 1; -#else - send_toggle_verbose (); -#endif - } - else - usage (); - - return 0; -} - diff --git a/src/tools/metacity-window-demo.c b/src/tools/metacity-window-demo.c deleted file mode 100644 index 0685b1f3..00000000 --- a/src/tools/metacity-window-demo.c +++ /dev/null @@ -1,997 +0,0 @@ -/* Metacity window types/properties demo app */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <gtk/gtk.h> -#include <gdk/gdkx.h> -#include <X11/Xatom.h> -#include <unistd.h> - -static GtkWidget* do_appwindow (void); - -static gboolean aspect_on; - -static void -set_gdk_window_struts (GdkWindow *window, - int left, - int right, - int top, - int bottom) -{ - long vals[12]; - - vals[0] = left; - vals[1] = right; - vals[2] = top; - vals[3] = bottom; - vals[4] = 000; - vals[5] = 400; - vals[6] = 200; - vals[7] = 600; - vals[8] = 76; - vals[9] = 676; - vals[10] = 200; - vals[11] = 800; - - XChangeProperty (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XWINDOW (window), - XInternAtom (GDK_WINDOW_XDISPLAY (window), - "_NET_WM_STRUT_PARTIAL", False), - XA_CARDINAL, 32, PropModeReplace, - (guchar *)vals, 12); -} - -static void -on_realize_set_struts (GtkWindow *window, - gpointer data) -{ - int left; - int right; - int top; - int bottom; - - g_return_if_fail (GTK_WIDGET_REALIZED (window)); - - left = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-left")); - right = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-right")); - top = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-top")); - bottom = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "meta-strut-bottom")); - - set_gdk_window_struts (GTK_WIDGET (window)->window, - left, right, top, bottom); -} - -static void -set_gtk_window_struts (GtkWidget *window, - int left, - int right, - int top, - int bottom) -{ - g_object_set_data (G_OBJECT (window), "meta-strut-left", - GINT_TO_POINTER (left)); - g_object_set_data (G_OBJECT (window), "meta-strut-right", - GINT_TO_POINTER (right)); - g_object_set_data (G_OBJECT (window), "meta-strut-top", - GINT_TO_POINTER (top)); - g_object_set_data (G_OBJECT (window), "meta-strut-bottom", - GINT_TO_POINTER (bottom)); - - g_signal_handlers_disconnect_by_func (G_OBJECT (window), - on_realize_set_struts, - NULL); - - g_signal_connect_after (G_OBJECT (window), - "realize", - G_CALLBACK (on_realize_set_struts), - NULL); - - if (GTK_WIDGET_REALIZED (window)) - set_gdk_window_struts (GTK_WIDGET (window)->window, - left, right, top, bottom); -} - -static void -set_gdk_window_type (GdkWindow *window, - const char *type) -{ - Atom atoms[2] = { None, None }; - - atoms[0] = XInternAtom (GDK_WINDOW_XDISPLAY (window), - type, False); - - XChangeProperty (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XWINDOW (window), - XInternAtom (GDK_WINDOW_XDISPLAY (window), "_NET_WM_WINDOW_TYPE", False), - XA_ATOM, 32, PropModeReplace, - (guchar *)atoms, - 1); -} - -static void -on_realize_set_type (GtkWindow *window, - gpointer data) -{ - const char *type; - - g_return_if_fail (GTK_WIDGET_REALIZED (window)); - - type = g_object_get_data (G_OBJECT (window), "meta-window-type"); - - g_return_if_fail (type != NULL); - - set_gdk_window_type (GTK_WIDGET (window)->window, - type); -} - -static void -set_gtk_window_type (GtkWindow *window, - const char *type) -{ - g_object_set_data (G_OBJECT (window), "meta-window-type", (char*) type); - - g_signal_handlers_disconnect_by_func (G_OBJECT (window), - on_realize_set_type, - NULL); - - g_signal_connect_after (G_OBJECT (window), - "realize", - G_CALLBACK (on_realize_set_type), - NULL); - - if (GTK_WIDGET_REALIZED (window)) - set_gdk_window_type (GTK_WIDGET (window)->window, - type); -} - -static void -set_gdk_window_border_only (GdkWindow *window) -{ - gdk_window_set_decorations (window, GDK_DECOR_BORDER); -} - -static void -on_realize_set_border_only (GtkWindow *window, - gpointer data) -{ - g_return_if_fail (GTK_WIDGET_REALIZED (window)); - - set_gdk_window_border_only (GTK_WIDGET (window)->window); -} - -static void -set_gtk_window_border_only (GtkWindow *window) -{ - g_signal_handlers_disconnect_by_func (G_OBJECT (window), - on_realize_set_border_only, - NULL); - - g_signal_connect_after (G_OBJECT (window), - "realize", - G_CALLBACK (on_realize_set_border_only), - NULL); - - if (GTK_WIDGET_REALIZED (window)) - set_gdk_window_border_only (GTK_WIDGET (window)->window); -} - -int -main (int argc, char **argv) -{ - GList *list; - GdkPixbuf *pixbuf; - GError *err; - - gtk_init (&argc, &argv); - - err = NULL; - pixbuf = gdk_pixbuf_new_from_file (METACITY_ICON_DIR"/metacity-window-demo.png", - &err); - if (pixbuf) - { - list = g_list_prepend (NULL, pixbuf); - - gtk_window_set_default_icon_list (list); - g_list_free (list); - g_object_unref (G_OBJECT (pixbuf)); - } - else - { - g_printerr ("Could not load icon: %s\n", err->message); - g_error_free (err); - } - - do_appwindow (); - - gtk_main (); - - return 0; -} - -static void -response_cb (GtkDialog *dialog, - int response_id, - void *data); - -static void -make_dialog (GtkWidget *parent, - int depth) -{ - GtkWidget *dialog; - char *str; - - dialog = gtk_message_dialog_new (parent ? GTK_WINDOW (parent) : NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, - parent ? "Here is a dialog %d" : - "Here is a dialog %d with no transient parent", - depth); - - str = g_strdup_printf ("%d dialog", depth); - gtk_window_set_title (GTK_WINDOW (dialog), str); - g_free (str); - - gtk_dialog_add_button (GTK_DIALOG (dialog), - "Open child dialog", - GTK_RESPONSE_ACCEPT); - - /* Close dialog on user response */ - g_signal_connect (G_OBJECT (dialog), - "response", - G_CALLBACK (response_cb), - NULL); - - g_object_set_data (G_OBJECT (dialog), "depth", - GINT_TO_POINTER (depth)); - - gtk_widget_show (dialog); -} - -static void -response_cb (GtkDialog *dialog, - int response_id, - void *data) -{ - switch (response_id) - { - case GTK_RESPONSE_ACCEPT: - make_dialog (GTK_WIDGET (dialog), - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), - "depth")) + 1); - break; - - default: - gtk_widget_destroy (GTK_WIDGET (dialog)); - break; - } -} - -static void -dialog_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - make_dialog (GTK_WIDGET (callback_data), 1); -} - -static void -modal_dialog_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (GTK_WINDOW (callback_data), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, - "Here is a MODAL dialog"); - - set_gtk_window_type (GTK_WINDOW (dialog), "_NET_WM_WINDOW_TYPE_MODAL_DIALOG"); - - gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); -} - -static void -no_parent_dialog_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - make_dialog (NULL, 1); -} - -static void -utility_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *window; - GtkWidget *vbox; - GtkWidget *button; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_UTILITY"); - gtk_window_set_title (GTK_WINDOW (window), "Utility"); - - gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); - - vbox = gtk_vbox_new (FALSE, 0); - - gtk_container_add (GTK_CONTAINER (window), vbox); - - button = gtk_button_new_with_mnemonic ("_A button"); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - button = gtk_button_new_with_mnemonic ("_B button"); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - button = gtk_button_new_with_mnemonic ("_C button"); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - button = gtk_button_new_with_mnemonic ("_D button"); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - - gtk_widget_show_all (window); -} - -static void -toolbar_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *window; - GtkWidget *vbox; - GtkWidget *label; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_TOOLBAR"); - gtk_window_set_title (GTK_WINDOW (window), "Toolbar"); - - gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); - - vbox = gtk_vbox_new (FALSE, 0); - - gtk_container_add (GTK_CONTAINER (window), vbox); - - label = gtk_label_new ("FIXME this needs a resize grip, etc."); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - - gtk_widget_show_all (window); -} - -static void -menu_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *window; - GtkWidget *vbox; - GtkWidget *label; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_MENU"); - gtk_window_set_title (GTK_WINDOW (window), "Menu"); - - gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); - - vbox = gtk_vbox_new (FALSE, 0); - - gtk_container_add (GTK_CONTAINER (window), vbox); - - label = gtk_label_new ("FIXME this isn't a menu."); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - - gtk_widget_show_all (window); -} - -static void -override_redirect_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *window; - GtkWidget *vbox; - GtkWidget *label; - - window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_window_set_title (GTK_WINDOW (window), "Override Redirect"); - - vbox = gtk_vbox_new (FALSE, 0); - - gtk_container_add (GTK_CONTAINER (window), vbox); - - label = gtk_label_new ("This is an override\nredirect window\nand should not be managed"); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - - gtk_widget_show_all (window); -} - -static void -border_only_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *window; - GtkWidget *vbox; - GtkWidget *label; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - set_gtk_window_border_only (GTK_WINDOW (window)); - gtk_window_set_title (GTK_WINDOW (window), "Border only"); - - gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (callback_data)); - - vbox = gtk_vbox_new (FALSE, 0); - - gtk_container_add (GTK_CONTAINER (window), vbox); - - label = gtk_label_new ("This window is supposed to have a border but no titlebar."); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - - gtk_widget_show_all (window); -} - -#if 0 -static void -changing_icon_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *window; - GtkWidget *vbox; - GtkWidget *label; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "Changing Icon"); - - vbox = gtk_vbox_new (FALSE, 0); - - gtk_container_add (GTK_CONTAINER (window), vbox); - - label = gtk_label_new ("This window has an icon that changes over time"); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - - gtk_widget_show_all (window); -} -#endif - -static gboolean -focus_in_event_cb (GtkWidget *window, - GdkEvent *event, - gpointer data) -{ - GtkWidget *widget; - - widget = GTK_WIDGET (data); - - gtk_label_set_text (GTK_LABEL (widget), "Has focus"); - - return TRUE; -} - - -static gboolean -focus_out_event_cb (GtkWidget *window, - GdkEvent *event, - gpointer data) -{ - GtkWidget *widget; - - widget = GTK_WIDGET (data); - - gtk_label_set_text (GTK_LABEL (widget), "Not focused"); - - return TRUE; -} - -static GtkWidget* -focus_label (GtkWidget *window) -{ - GtkWidget *label; - - label = gtk_label_new ("Not focused"); - - g_signal_connect (G_OBJECT (window), "focus_in_event", - G_CALLBACK (focus_in_event_cb), label); - - g_signal_connect (G_OBJECT (window), "focus_out_event", - G_CALLBACK (focus_out_event_cb), label); - - return label; -} - -static void -splashscreen_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *window; - GtkWidget *image; - GtkWidget *vbox; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_SPLASHSCREEN"); - gtk_window_set_title (GTK_WINDOW (window), "Splashscreen"); - - vbox = gtk_vbox_new (FALSE, 0); - - image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0); - - gtk_box_pack_start (GTK_BOX (vbox), focus_label (window), FALSE, FALSE, 0); - - gtk_container_add (GTK_CONTAINER (window), vbox); - - gtk_widget_show_all (window); -} - -enum -{ - DOCK_TOP = 1, - DOCK_BOTTOM = 2, - DOCK_LEFT = 3, - DOCK_RIGHT = 4, - DOCK_ALL = 5 -}; - -static void -make_dock (int type) -{ - GtkWidget *window; - GtkWidget *image; - GtkWidget *box; - GtkWidget *button; - - g_return_if_fail (type != DOCK_ALL); - - box = NULL; - switch (type) - { - case DOCK_LEFT: - case DOCK_RIGHT: - box = gtk_vbox_new (FALSE, 0); - break; - case DOCK_TOP: - case DOCK_BOTTOM: - box = gtk_hbox_new (FALSE, 0); - break; - case DOCK_ALL: - break; - } - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_DOCK"); - - image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0); - - gtk_box_pack_start (GTK_BOX (box), focus_label (window), FALSE, FALSE, 0); - - button = gtk_button_new_with_label ("Close"); - gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); - - g_signal_connect_swapped (G_OBJECT (button), "clicked", - G_CALLBACK (gtk_widget_destroy), window); - - gtk_container_add (GTK_CONTAINER (window), box); - -#define DOCK_SIZE 48 - switch (type) - { - case DOCK_LEFT: - gtk_widget_set_size_request (window, DOCK_SIZE, 400); - gtk_window_move (GTK_WINDOW (window), 0, 000); - set_gtk_window_struts (window, DOCK_SIZE, 0, 0, 0); - gtk_window_set_title (GTK_WINDOW (window), "LeftDock"); - break; - case DOCK_RIGHT: - gtk_widget_set_size_request (window, DOCK_SIZE, 400); - gtk_window_move (GTK_WINDOW (window), gdk_screen_width () - DOCK_SIZE, 200); - set_gtk_window_struts (window, 0, DOCK_SIZE, 0, 0); - gtk_window_set_title (GTK_WINDOW (window), "RightDock"); - break; - case DOCK_TOP: - gtk_widget_set_size_request (window, 600, DOCK_SIZE); - gtk_window_move (GTK_WINDOW (window), 76, 0); - set_gtk_window_struts (window, 0, 0, DOCK_SIZE, 0); - gtk_window_set_title (GTK_WINDOW (window), "TopDock"); - break; - case DOCK_BOTTOM: - gtk_widget_set_size_request (window, 600, DOCK_SIZE); - gtk_window_move (GTK_WINDOW (window), 200, gdk_screen_height () - DOCK_SIZE); - set_gtk_window_struts (window, 0, 0, 0, DOCK_SIZE); - gtk_window_set_title (GTK_WINDOW (window), "BottomDock"); - break; - case DOCK_ALL: - break; - } - - gtk_widget_show_all (window); -} - -static void -dock_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - if (callback_action == DOCK_ALL) - { - make_dock (DOCK_TOP); - make_dock (DOCK_BOTTOM); - make_dock (DOCK_LEFT); - make_dock (DOCK_RIGHT); - } - else - { - make_dock (callback_action); - } -} - -static void -desktop_cb (gpointer callback_data, - guint callback_action, - GtkWidget *widget) -{ - GtkWidget *window; - GtkWidget *label; - GdkColor desktop_color; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - set_gtk_window_type (GTK_WINDOW (window), "_NET_WM_WINDOW_TYPE_DESKTOP"); - gtk_window_set_title (GTK_WINDOW (window), "Desktop"); - gtk_widget_set_size_request (window, - gdk_screen_width (), gdk_screen_height ()); - gtk_window_move (GTK_WINDOW (window), 0, 0); - - desktop_color.red = 0x5144; - desktop_color.green = 0x75D6; - desktop_color.blue = 0xA699; - - gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &desktop_color); - - label = focus_label (window); - - gtk_container_add (GTK_CONTAINER (window), label); - - gtk_widget_show_all (window); -} - -static GtkItemFactoryEntry menu_items[] = -{ - { "/_Windows", NULL, NULL, 0, "<Branch>" }, - { "/Windows/tearoff", NULL, NULL, 0, "<Tearoff>" }, - { "/Windows/_Dialog", "<control>d", dialog_cb, 0, NULL }, - { "/Windows/_Modal dialog", NULL, modal_dialog_cb, 0, NULL }, - { "/Windows/_Parentless dialog", NULL, no_parent_dialog_cb, 0, NULL }, - { "/Windows/_Utility", "<control>u", utility_cb, 0, NULL }, - { "/Windows/_Splashscreen", "<control>s", splashscreen_cb, 0, NULL }, - { "/Windows/_Top dock", NULL, dock_cb, DOCK_TOP, NULL }, - { "/Windows/_Bottom dock", NULL, dock_cb, DOCK_BOTTOM, NULL }, - { "/Windows/_Left dock", NULL, dock_cb, DOCK_LEFT, NULL }, - { "/Windows/_Right dock", NULL, dock_cb, DOCK_RIGHT, NULL }, - { "/Windows/_All docks", NULL, dock_cb, DOCK_ALL, NULL }, - { "/Windows/Des_ktop", NULL, desktop_cb, 0, NULL }, - { "/Windows/Me_nu", NULL, menu_cb, 0, NULL }, - { "/Windows/Tool_bar", NULL, toolbar_cb, 0, NULL }, - { "/Windows/Override Redirect", NULL, override_redirect_cb, 0, NULL }, - { "/Windows/Border Only", NULL, border_only_cb, 0, NULL } -}; - -static void -sleep_cb (GtkWidget *button, - gpointer data) -{ - sleep (1000); -} - -static void -toggle_aspect_ratio (GtkWidget *button, - gpointer data) -{ - GtkWidget *window; - GdkGeometry geom; - - if (aspect_on) - { - geom.min_aspect = 0; - geom.max_aspect = 65535; - } - else - { - geom.min_aspect = 1.777778; - geom.max_aspect = 1.777778; - } - - aspect_on = !aspect_on; - - window = gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW); - if (window) - gtk_window_set_geometry_hints (GTK_WINDOW (window), - GTK_WIDGET (data), - &geom, - GDK_HINT_ASPECT); - -} - -static void -toggle_decorated_cb (GtkWidget *button, - gpointer data) -{ - GtkWidget *window; - window = gtk_widget_get_ancestor (button, GTK_TYPE_WINDOW); - if (window) - gtk_window_set_decorated (GTK_WINDOW (window), - !gtk_window_get_decorated (GTK_WINDOW (window))); -} - -static void -clicked_toolbar_cb (GtkWidget *button, - gpointer data) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (GTK_WINDOW (data), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, - "Clicking the toolbar buttons doesn't do anything"); - - /* Close dialog on user response */ - g_signal_connect (G_OBJECT (dialog), - "response", - G_CALLBACK (gtk_widget_destroy), - NULL); - - gtk_widget_show (dialog); -} - -static void -update_statusbar (GtkTextBuffer *buffer, - GtkStatusbar *statusbar) -{ - gchar *msg; - gint row, col; - gint count; - GtkTextIter iter; - - gtk_statusbar_pop (statusbar, 0); /* clear any previous message, underflow is allowed */ - - count = gtk_text_buffer_get_char_count (buffer); - - gtk_text_buffer_get_iter_at_mark (buffer, - &iter, - gtk_text_buffer_get_insert (buffer)); - - row = gtk_text_iter_get_line (&iter); - col = gtk_text_iter_get_line_offset (&iter); - - msg = g_strdup_printf ("Cursor at row %d column %d - %d chars in document", - row, col, count); - - gtk_statusbar_push (statusbar, 0, msg); - - g_free (msg); -} - -static void -mark_set_callback (GtkTextBuffer *buffer, - const GtkTextIter *new_location, - GtkTextMark *mark, - gpointer data) -{ - update_statusbar (buffer, GTK_STATUSBAR (data)); -} - -static int window_count = 0; - -static void -destroy_cb (GtkWidget *w, gpointer data) -{ - --window_count; - if (window_count == 0) - gtk_main_quit (); -} - -static GtkWidget * -do_appwindow (void) -{ - GtkWidget *window; - GtkWidget *table; - GtkWidget *toolbar; - GtkWidget *handlebox; - GtkWidget *statusbar; - GtkWidget *contents; - GtkWidget *sw; - GtkTextBuffer *buffer; - GtkAccelGroup *accel_group; - GtkItemFactory *item_factory; - - /* Create the toplevel window - */ - - ++window_count; - - aspect_on = FALSE; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "Application Window"); - - g_signal_connect (G_OBJECT (window), "destroy", - G_CALLBACK (destroy_cb), NULL); - - table = gtk_table_new (1, 4, FALSE); - - gtk_container_add (GTK_CONTAINER (window), table); - - /* Create the menubar - */ - - accel_group = gtk_accel_group_new (); - gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - g_object_unref (accel_group); - - item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group); - - /* Set up item factory to go away with the window */ - g_object_ref (item_factory); - gtk_object_sink (GTK_OBJECT (item_factory)); - g_object_set_data_full (G_OBJECT (window), - "<main>", - item_factory, - (GDestroyNotify) g_object_unref); - - /* create menu items */ - gtk_item_factory_create_items (item_factory, G_N_ELEMENTS (menu_items), - menu_items, window); - - gtk_table_attach (GTK_TABLE (table), - gtk_item_factory_get_widget (item_factory, "<main>"), - /* X direction */ /* Y direction */ - 0, 1, 0, 1, - GTK_EXPAND | GTK_FILL, 0, - 0, 0); - - /* Create document - */ - - sw = gtk_scrolled_window_new (NULL, NULL); - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), - GTK_SHADOW_IN); - - gtk_table_attach (GTK_TABLE (table), - sw, - /* X direction */ /* Y direction */ - 0, 1, 2, 3, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 0, 0); - - gtk_window_set_default_size (GTK_WINDOW (window), - 200, 200); - - contents = gtk_text_view_new (); - gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (contents), - PANGO_WRAP_WORD); - - gtk_container_add (GTK_CONTAINER (sw), - contents); - - /* Create the toolbar - */ - toolbar = gtk_toolbar_new (); - - gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), - GTK_STOCK_NEW, - "Open another one of these windows", - NULL, - G_CALLBACK (do_appwindow), - window, /* user data for callback */ - -1); /* -1 means "append" */ - - gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), - GTK_STOCK_OPEN, - "This is a demo button that locks up the demo", - NULL, - G_CALLBACK (sleep_cb), - window, /* user data for callback */ - -1); /* -1 means "append" */ - - gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), - GTK_STOCK_OPEN, - "This is a demo button that toggles window decorations", - NULL, - G_CALLBACK (toggle_decorated_cb), - window, /* user data for callback */ - -1); /* -1 means "append" */ - - gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), - GTK_STOCK_OPEN, - "This is a demo button that locks the aspect ratio using a hint", - NULL, - G_CALLBACK (toggle_aspect_ratio), - contents, /* user data for callback */ - -1); /* -1 means "append" */ - - gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), - GTK_STOCK_QUIT, - "This is a demo button with a 'quit' icon", - NULL, - G_CALLBACK (clicked_toolbar_cb), - window, /* user data for callback */ - -1); /* -1 means "append" */ - - handlebox = gtk_handle_box_new (); - - gtk_container_add (GTK_CONTAINER (handlebox), toolbar); - - gtk_table_attach (GTK_TABLE (table), - handlebox, - /* X direction */ /* Y direction */ - 0, 1, 1, 2, - GTK_EXPAND | GTK_FILL, 0, - 0, 0); - - /* Create statusbar */ - - statusbar = gtk_statusbar_new (); - gtk_table_attach (GTK_TABLE (table), - statusbar, - /* X direction */ /* Y direction */ - 0, 1, 3, 4, - GTK_EXPAND | GTK_FILL, 0, - 0, 0); - - /* Show text widget info in the statusbar */ - buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (contents)); - - gtk_text_buffer_set_text (buffer, - "This demo demonstrates various kinds of windows that " - "window managers and window manager themes should handle. " - "Be sure to tear off the menu and toolbar, those are also " - "a special kind of window.", - -1); - - g_signal_connect_object (buffer, - "changed", - G_CALLBACK (update_statusbar), - statusbar, - 0); - - g_signal_connect_object (buffer, - "mark_set", /* cursor moved */ - G_CALLBACK (mark_set_callback), - statusbar, - 0); - - update_statusbar (buffer, GTK_STATUSBAR (statusbar)); - - gtk_widget_show_all (window); - - return window; -} - - diff --git a/src/tools/metacity-window-demo.png b/src/tools/metacity-window-demo.png Binary files differdeleted file mode 100644 index d87f8296..00000000 --- a/src/tools/metacity-window-demo.png +++ /dev/null diff --git a/src/ui/draw-workspace.c b/src/ui/draw-workspace.c deleted file mode 100644 index f7c98b68..00000000 --- a/src/ui/draw-workspace.c +++ /dev/null @@ -1,232 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Draw a workspace */ - -/* This file should not be modified to depend on other files in - * libwnck or metacity, since it's used in both of them - */ - -/* - * Copyright (C) 2002 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "draw-workspace.h" - - -static void -get_window_rect (const WnckWindowDisplayInfo *win, - int screen_width, - int screen_height, - const GdkRectangle *workspace_rect, - GdkRectangle *rect) -{ - double width_ratio, height_ratio; - int x, y, width, height; - - width_ratio = (double) workspace_rect->width / (double) screen_width; - height_ratio = (double) workspace_rect->height / (double) screen_height; - - x = win->x; - y = win->y; - width = win->width; - height = win->height; - - x *= width_ratio; - y *= height_ratio; - width *= width_ratio; - height *= height_ratio; - - x += workspace_rect->x; - y += workspace_rect->y; - - if (width < 3) - width = 3; - if (height < 3) - height = 3; - - rect->x = x; - rect->y = y; - rect->width = width; - rect->height = height; -} - -static void -draw_window (GtkWidget *widget, - GdkDrawable *drawable, - const WnckWindowDisplayInfo *win, - const GdkRectangle *winrect, - GtkStateType state) -{ - cairo_t *cr; - GdkPixbuf *icon; - int icon_x, icon_y, icon_w, icon_h; - gboolean is_active; - GdkColor *color; - - is_active = win->is_active; - - cr = gdk_cairo_create (drawable); - cairo_rectangle (cr, winrect->x, winrect->y, winrect->width, winrect->height); - cairo_clip (cr); - - if (is_active) - color = &widget->style->light[state]; - else - color = &widget->style->bg[state]; - cairo_set_source_rgb (cr, - color->red / 65535., - color->green / 65535., - color->blue / 65535.); - - cairo_rectangle (cr, - winrect->x + 1, winrect->y + 1, - MAX (0, winrect->width - 2), MAX (0, winrect->height - 2)); - cairo_fill (cr); - - - icon = win->icon; - - icon_w = icon_h = 0; - - if (icon) - { - icon_w = gdk_pixbuf_get_width (icon); - icon_h = gdk_pixbuf_get_height (icon); - - /* If the icon is too big, fall back to mini icon. - * We don't arbitrarily scale the icon, because it's - * just too slow on my Athlon 850. - */ - if (icon_w > (winrect->width - 2) || - icon_h > (winrect->height - 2)) - { - icon = win->mini_icon; - if (icon) - { - icon_w = gdk_pixbuf_get_width (icon); - icon_h = gdk_pixbuf_get_height (icon); - - /* Give up. */ - if (icon_w > (winrect->width - 2) || - icon_h > (winrect->height - 2)) - icon = NULL; - } - } - } - - if (icon) - { - icon_x = winrect->x + (winrect->width - icon_w) / 2; - icon_y = winrect->y + (winrect->height - icon_h) / 2; - - cairo_save (cr); - gdk_cairo_set_source_pixbuf (cr, icon, icon_x, icon_y); - cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h); - cairo_clip (cr); - cairo_paint (cr); - cairo_restore (cr); - } - - if (is_active) - color = &widget->style->fg[state]; - else - color = &widget->style->fg[state]; - - cairo_set_source_rgb (cr, - color->red / 65535., - color->green / 65535., - color->blue / 65535.); - cairo_set_line_width (cr, 1.0); - cairo_rectangle (cr, - winrect->x + 0.5, winrect->y + 0.5, - MAX (0, winrect->width - 1), MAX (0, winrect->height - 1)); - cairo_stroke (cr); - - cairo_destroy (cr); -} - -void -wnck_draw_workspace (GtkWidget *widget, - GdkDrawable *drawable, - int x, - int y, - int width, - int height, - int screen_width, - int screen_height, - GdkPixbuf *workspace_background, - gboolean is_active, - const WnckWindowDisplayInfo *windows, - int n_windows) -{ - int i; - GdkRectangle workspace_rect; - GtkStateType state; - - workspace_rect.x = x; - workspace_rect.y = y; - workspace_rect.width = width; - workspace_rect.height = height; - - if (is_active) - state = GTK_STATE_SELECTED; - else if (workspace_background) - state = GTK_STATE_PRELIGHT; - else - state = GTK_STATE_NORMAL; - - if (workspace_background) - { - gdk_draw_pixbuf (drawable, - GTK_WIDGET (widget)->style->dark_gc[state], - workspace_background, - 0, 0, - x, y, - -1, -1, - GDK_RGB_DITHER_MAX, - 0, 0); - } - else - { - cairo_t *cr; - - cr = gdk_cairo_create (widget->window); - gdk_cairo_set_source_color (cr, &widget->style->dark[state]); - cairo_rectangle (cr, x, y, width, height); - cairo_fill (cr); - cairo_destroy (cr); - } - - i = 0; - while (i < n_windows) - { - const WnckWindowDisplayInfo *win = &windows[i]; - GdkRectangle winrect; - - get_window_rect (win, screen_width, - screen_height, &workspace_rect, &winrect); - - draw_window (widget, - drawable, - win, - &winrect, - state); - - ++i; - } -} diff --git a/src/ui/draw-workspace.h b/src/ui/draw-workspace.h deleted file mode 100644 index 10018aa8..00000000 --- a/src/ui/draw-workspace.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Draw a workspace */ - -/* This file should not be modified to depend on other files in - * libwnck or metacity, since it's used in both of them - */ - -/* - * Copyright (C) 2002 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef WNCK_DRAW_WORKSPACE_H -#define WNCK_DRAW_WORKSPACE_H - -#include <gdk/gdk.h> -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gtk/gtk.h> - -typedef struct -{ - GdkPixbuf *icon; - GdkPixbuf *mini_icon; - int x; - int y; - int width; - int height; - - guint is_active : 1; - -} WnckWindowDisplayInfo; - -void wnck_draw_workspace (GtkWidget *widget, - GdkDrawable *drawable, - int x, - int y, - int width, - int height, - int screen_width, - int screen_height, - GdkPixbuf *workspace_background, - gboolean is_active, - const WnckWindowDisplayInfo *windows, - int n_windows); - -#endif diff --git a/src/ui/fixedtip.c b/src/ui/fixedtip.c deleted file mode 100644 index b4c5203c..00000000 --- a/src/ui/fixedtip.c +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity fixed tooltip routine */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "fixedtip.h" -#include "ui.h" - -/** - * The floating rectangle. This is a GtkWindow, and it contains - * the "label" widget, below. - */ -static GtkWidget *tip = NULL; - -/** - * The actual text that gets displayed. - */ -static GtkWidget *label = NULL; -/* - * X coordinate of the right-hand edge of the screen. - * - * \bug This appears to be a bug; screen_right_edge is calculated only when - * the window is redrawn. Actually we should never cache it because - * different windows are different sizes. - */ -static int screen_right_edge = 0; -/* - * Y coordinate of the bottom edge of the screen. - * - * \bug As with screen_right_edge. - */ -static int screen_bottom_edge = 0; - -static gint -expose_handler (GtkTooltips *tooltips) -{ - gtk_paint_flat_box (tip->style, tip->window, - GTK_STATE_NORMAL, GTK_SHADOW_OUT, - NULL, tip, "tooltip", - 0, 0, -1, -1); - - return FALSE; -} - -void -meta_fixed_tip_show (Display *xdisplay, int screen_number, - int root_x, int root_y, - const char *markup_text) -{ - int w, h; - - if (tip == NULL) - { - tip = gtk_window_new (GTK_WINDOW_POPUP); - { - GdkScreen *gdk_screen; - GdkRectangle monitor; - gint mon_num; - - gdk_screen = gdk_display_get_screen (gdk_display_get_default (), - screen_number); - gtk_window_set_screen (GTK_WINDOW (tip), - gdk_screen); - mon_num = gdk_screen_get_monitor_at_point (gdk_screen, root_x, root_y); - gdk_screen_get_monitor_geometry (gdk_screen, mon_num, &monitor); - screen_right_edge = monitor.x + monitor.width; - screen_bottom_edge = monitor.y + monitor.height; - } - - gtk_widget_set_app_paintable (tip, TRUE); - gtk_window_set_policy (GTK_WINDOW (tip), FALSE, FALSE, TRUE); - gtk_widget_set_name (tip, "gtk-tooltips"); - gtk_container_set_border_width (GTK_CONTAINER (tip), 4); - - g_signal_connect_swapped (tip, "expose_event", - G_CALLBACK (expose_handler), NULL); - - label = gtk_label_new (NULL); - gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_widget_show (label); - - gtk_container_add (GTK_CONTAINER (tip), label); - - g_signal_connect (tip, "destroy", - G_CALLBACK (gtk_widget_destroyed), &tip); - } - - gtk_label_set_markup (GTK_LABEL (label), markup_text); - - gtk_window_get_size (GTK_WINDOW (tip), &w, &h); - - if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - root_x = MAX(0, root_x - w); - - if ((root_x + w) > screen_right_edge) - root_x -= (root_x + w) - screen_right_edge; - - gtk_window_move (GTK_WINDOW (tip), root_x, root_y); - - gtk_widget_show (tip); -} - -void -meta_fixed_tip_hide (void) -{ - if (tip) - { - gtk_widget_destroy (tip); - tip = NULL; - } -} diff --git a/src/ui/fixedtip.h b/src/ui/fixedtip.h deleted file mode 100644 index c196389d..00000000 --- a/src/ui/fixedtip.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** - * \file fixedtip.h Metacity fixed tooltip routine - * - * Sometimes we want to display a small floating rectangle with helpful - * text near the pointer. For example, if the user holds the mouse over - * the maximise button, we can display a tooltip saying "Maximize". - * The text is localised, of course. - * - * This file contains the functions to create and delete these tooltips. - * - * \todo Since we now consider MetaDisplay a singleton, there can be - * only one tooltip per display; this might quite simply live in - * display.c. Alternatively, it could move to frames.c, which - * is the only place this business is called anyway. - * - * \todo Apparently some UI needs changing (check bugzilla) - */ - -#ifndef META_FIXED_TIP_H -#define META_FIXED_TIP_H - -#include <gtk/gtk.h> -#include <gdk/gdkx.h> - -/** - * Displays a tooltip. There can be only one across the entire system. - * This function behaves identically whether or not a tooltip is already - * displayed, but if it is the window will be reused rather than destroyed - * and recreated. - * - * \param xdisplay An X display. - * \param screen_number The number of the screen. - * \param root_x The X coordinate where the tooltip should appear - * \param root_y The Y coordinate where the tooltip should appear - * \param markup_text Text to display in the tooltip; can contain markup - */ -void meta_fixed_tip_show (Display *xdisplay, int screen_number, - int root_x, int root_y, - const char *markup_text); - -/** - * Removes the tooltip that was created by meta_fixed_tip_show(). If there - * is no tooltip currently visible, this is a no-op. - */ -void meta_fixed_tip_hide (void); - - -#endif diff --git a/src/ui/frames.c b/src/ui/frames.c deleted file mode 100644 index f4761d2a..00000000 --- a/src/ui/frames.c +++ /dev/null @@ -1,2848 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window frame manager widget */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Red Hat, Inc. - * Copyright (C) 2005, 2006 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include <math.h> -#include "boxes.h" -#include "frames.h" -#include "util.h" -#include "core.h" -#include "menu.h" -#include "fixedtip.h" -#include "theme.h" -#include "prefs.h" -#include "ui.h" - -#ifdef HAVE_SHAPE -#include <X11/extensions/shape.h> -#endif - -#define DEFAULT_INNER_BUTTON_BORDER 3 - -static void meta_frames_class_init (MetaFramesClass *klass); -static void meta_frames_init (MetaFrames *frames); -static void meta_frames_destroy (GtkObject *object); -static void meta_frames_finalize (GObject *object); -static void meta_frames_style_set (GtkWidget *widget, - GtkStyle *prev_style); -static void meta_frames_realize (GtkWidget *widget); -static void meta_frames_unrealize (GtkWidget *widget); - -static void meta_frames_update_prelit_control (MetaFrames *frames, - MetaUIFrame *frame, - MetaFrameControl control); -static gboolean meta_frames_button_press_event (GtkWidget *widget, - GdkEventButton *event); -static gboolean meta_frames_button_release_event (GtkWidget *widget, - GdkEventButton *event); -static gboolean meta_frames_motion_notify_event (GtkWidget *widget, - GdkEventMotion *event); -static gboolean meta_frames_destroy_event (GtkWidget *widget, - GdkEventAny *event); -static gboolean meta_frames_expose_event (GtkWidget *widget, - GdkEventExpose *event); -static gboolean meta_frames_enter_notify_event (GtkWidget *widget, - GdkEventCrossing *event); -static gboolean meta_frames_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event); - -static void meta_frames_paint_to_drawable (MetaFrames *frames, - MetaUIFrame *frame, - GdkDrawable *drawable, - GdkRegion *region, - int x_offset, - int y_offset); - -static void meta_frames_set_window_background (MetaFrames *frames, - MetaUIFrame *frame); - -static void meta_frames_calc_geometry (MetaFrames *frames, - MetaUIFrame *frame, - MetaFrameGeometry *fgeom); - -static void meta_frames_ensure_layout (MetaFrames *frames, - MetaUIFrame *frame); - -static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames, - Window xwindow); - -static void meta_frames_font_changed (MetaFrames *frames); -static void meta_frames_button_layout_changed (MetaFrames *frames); - - -static GdkRectangle* control_rect (MetaFrameControl control, - MetaFrameGeometry *fgeom); -static MetaFrameControl get_control (MetaFrames *frames, - MetaUIFrame *frame, - int x, - int y); -static void clear_tip (MetaFrames *frames); -static void invalidate_all_caches (MetaFrames *frames); -static void invalidate_whole_window (MetaFrames *frames, - MetaUIFrame *frame); - -static GtkWidgetClass *parent_class = NULL; - -GtkType -meta_frames_get_type (void) -{ - static GtkType frames_type = 0; - - if (!frames_type) - { - static const GtkTypeInfo frames_info = - { - "MetaFrames", - sizeof (MetaFrames), - sizeof (MetaFramesClass), - (GtkClassInitFunc) meta_frames_class_init, - (GtkObjectInitFunc) meta_frames_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - frames_type = gtk_type_unique (GTK_TYPE_WINDOW, &frames_info); - } - - return frames_type; -} - -static void -meta_frames_class_init (MetaFramesClass *class) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - gobject_class = G_OBJECT_CLASS (class); - object_class = (GtkObjectClass*) class; - widget_class = (GtkWidgetClass*) class; - - parent_class = g_type_class_peek_parent (class); - - gobject_class->finalize = meta_frames_finalize; - object_class->destroy = meta_frames_destroy; - - widget_class->style_set = meta_frames_style_set; - - widget_class->realize = meta_frames_realize; - widget_class->unrealize = meta_frames_unrealize; - - widget_class->expose_event = meta_frames_expose_event; - widget_class->destroy_event = meta_frames_destroy_event; - widget_class->button_press_event = meta_frames_button_press_event; - widget_class->button_release_event = meta_frames_button_release_event; - widget_class->motion_notify_event = meta_frames_motion_notify_event; - widget_class->enter_notify_event = meta_frames_enter_notify_event; - widget_class->leave_notify_event = meta_frames_leave_notify_event; -} - -static gint -unsigned_long_equal (gconstpointer v1, - gconstpointer v2) -{ - return *((const gulong*) v1) == *((const gulong*) v2); -} - -static guint -unsigned_long_hash (gconstpointer v) -{ - gulong val = * (const gulong *) v; - - /* I'm not sure this works so well. */ -#if GLIB_SIZEOF_LONG > 4 - return (guint) (val ^ (val >> 32)); -#else - return val; -#endif -} - -static void -prefs_changed_callback (MetaPreference pref, - void *data) -{ - switch (pref) - { - case META_PREF_TITLEBAR_FONT: - meta_frames_font_changed (META_FRAMES (data)); - break; - case META_PREF_BUTTON_LAYOUT: - meta_frames_button_layout_changed (META_FRAMES (data)); - break; - default: - break; - } -} - -static void -meta_frames_init (MetaFrames *frames) -{ - GTK_WINDOW (frames)->type = GTK_WINDOW_POPUP; - - frames->text_heights = g_hash_table_new (NULL, NULL); - - frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); - - frames->tooltip_timeout = 0; - - frames->expose_delay_count = 0; - - frames->invalidate_cache_timeout_id = 0; - frames->invalidate_frames = NULL; - frames->cache = g_hash_table_new (g_direct_hash, g_direct_equal); - - gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE); - - meta_prefs_add_listener (prefs_changed_callback, frames); -} - -static void -listify_func (gpointer key, gpointer value, gpointer data) -{ - GSList **listp; - - listp = data; - *listp = g_slist_prepend (*listp, value); -} - -static void -meta_frames_destroy (GtkObject *object) -{ - GSList *winlist; - GSList *tmp; - MetaFrames *frames; - - frames = META_FRAMES (object); - - clear_tip (frames); - - winlist = NULL; - g_hash_table_foreach (frames->frames, listify_func, &winlist); - - /* Unmanage all frames */ - for (tmp = winlist; tmp != NULL; tmp = tmp->next) - { - MetaUIFrame *frame; - - frame = tmp->data; - - meta_frames_unmanage_window (frames, frame->xwindow); - } - g_slist_free (winlist); - - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - -static void -meta_frames_finalize (GObject *object) -{ - MetaFrames *frames; - - frames = META_FRAMES (object); - - meta_prefs_remove_listener (prefs_changed_callback, frames); - - g_hash_table_destroy (frames->text_heights); - - invalidate_all_caches (frames); - if (frames->invalidate_cache_timeout_id) - g_source_remove (frames->invalidate_cache_timeout_id); - - g_assert (g_hash_table_size (frames->frames) == 0); - g_hash_table_destroy (frames->frames); - g_hash_table_destroy (frames->cache); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -typedef struct -{ - MetaRectangle rect; - GdkPixmap *pixmap; -} CachedFramePiece; - -typedef struct -{ - /* Caches of the four rendered sides in a MetaFrame. - * Order: top (titlebar), left, right, bottom. - */ - CachedFramePiece piece[4]; -} CachedPixels; - -static CachedPixels * -get_cache (MetaFrames *frames, - MetaUIFrame *frame) -{ - CachedPixels *pixels; - - pixels = g_hash_table_lookup (frames->cache, frame); - - if (!pixels) - { - pixels = g_new0 (CachedPixels, 1); - g_hash_table_insert (frames->cache, frame, pixels); - } - - return pixels; -} - -static void -invalidate_cache (MetaFrames *frames, - MetaUIFrame *frame) -{ - CachedPixels *pixels = get_cache (frames, frame); - int i; - - for (i = 0; i < 4; i++) - if (pixels->piece[i].pixmap) - g_object_unref (pixels->piece[i].pixmap); - - g_free (pixels); - g_hash_table_remove (frames->cache, frame); -} - -static void -invalidate_all_caches (MetaFrames *frames) -{ - GList *l; - - for (l = frames->invalidate_frames; l; l = l->next) - { - MetaUIFrame *frame = l->data; - - invalidate_cache (frames, frame); - } - - g_list_free (frames->invalidate_frames); - frames->invalidate_frames = NULL; -} - -static gboolean -invalidate_cache_timeout (gpointer data) -{ - MetaFrames *frames = data; - - invalidate_all_caches (frames); - frames->invalidate_cache_timeout_id = 0; - return FALSE; -} - -static void -queue_recalc_func (gpointer key, gpointer value, gpointer data) -{ - MetaUIFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (data); - frame = value; - - /* If a resize occurs it will cause a redraw, but the - * resize may not actually be needed so we always redraw - * in case of color change. - */ - meta_frames_set_window_background (frames, frame); - - invalidate_whole_window (frames, frame); - meta_core_queue_frame_resize (gdk_display, - frame->xwindow); - if (frame->layout) - { - /* save title to recreate layout */ - g_free (frame->title); - - frame->title = g_strdup (pango_layout_get_text (frame->layout)); - - g_object_unref (G_OBJECT (frame->layout)); - frame->layout = NULL; - } -} - -static void -meta_frames_font_changed (MetaFrames *frames) -{ - if (g_hash_table_size (frames->text_heights) > 0) - { - g_hash_table_destroy (frames->text_heights); - frames->text_heights = g_hash_table_new (NULL, NULL); - } - - /* Queue a draw/resize on all frames */ - g_hash_table_foreach (frames->frames, - queue_recalc_func, frames); - -} - -static void -queue_draw_func (gpointer key, gpointer value, gpointer data) -{ - MetaUIFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (data); - frame = value; - - /* If a resize occurs it will cause a redraw, but the - * resize may not actually be needed so we always redraw - * in case of color change. - */ - meta_frames_set_window_background (frames, frame); - - invalidate_whole_window (frames, frame); -} - -static void -meta_frames_button_layout_changed (MetaFrames *frames) -{ - g_hash_table_foreach (frames->frames, - queue_draw_func, frames); -} - -static void -meta_frames_style_set (GtkWidget *widget, - GtkStyle *prev_style) -{ - MetaFrames *frames; - - frames = META_FRAMES (widget); - - meta_frames_font_changed (frames); - - GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style); -} - -static void -meta_frames_ensure_layout (MetaFrames *frames, - MetaUIFrame *frame) -{ - GtkWidget *widget; - MetaFrameFlags flags; - MetaFrameType type; - MetaFrameStyle *style; - - g_return_if_fail (GTK_WIDGET_REALIZED (frames)); - - widget = GTK_WIDGET (frames); - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_FRAME_TYPE, &type, - META_CORE_GET_END); - - style = meta_theme_get_frame_style (meta_theme_get_current (), - type, flags); - - if (style != frame->cache_style) - { - if (frame->layout) - { - /* save title to recreate layout */ - g_free (frame->title); - - frame->title = g_strdup (pango_layout_get_text (frame->layout)); - - g_object_unref (G_OBJECT (frame->layout)); - frame->layout = NULL; - } - } - - frame->cache_style = style; - - if (frame->layout == NULL) - { - gpointer key, value; - PangoFontDescription *font_desc; - double scale; - int size; - - scale = meta_theme_get_title_scale (meta_theme_get_current (), - type, - flags); - - frame->layout = gtk_widget_create_pango_layout (widget, frame->title); - - pango_layout_set_auto_dir (frame->layout, FALSE); - - font_desc = meta_gtk_widget_get_font_desc (widget, scale, - meta_prefs_get_titlebar_font ()); - - size = pango_font_description_get_size (font_desc); - - if (g_hash_table_lookup_extended (frames->text_heights, - GINT_TO_POINTER (size), - &key, &value)) - { - frame->text_height = GPOINTER_TO_INT (value); - } - else - { - frame->text_height = - meta_pango_font_desc_get_text_height (font_desc, - gtk_widget_get_pango_context (widget)); - - g_hash_table_replace (frames->text_heights, - GINT_TO_POINTER (size), - GINT_TO_POINTER (frame->text_height)); - } - - pango_layout_set_font_description (frame->layout, - font_desc); - - pango_font_description_free (font_desc); - - /* Save some RAM */ - g_free (frame->title); - frame->title = NULL; - } -} - -static void -meta_frames_calc_geometry (MetaFrames *frames, - MetaUIFrame *frame, - MetaFrameGeometry *fgeom) -{ - int width, height; - MetaFrameFlags flags; - MetaFrameType type; - MetaButtonLayout button_layout; - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_CLIENT_WIDTH, &width, - META_CORE_GET_CLIENT_HEIGHT, &height, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_FRAME_TYPE, &type, - META_CORE_GET_END); - - meta_frames_ensure_layout (frames, frame); - - meta_prefs_get_button_layout (&button_layout); - - meta_theme_calc_geometry (meta_theme_get_current (), - type, - frame->text_height, - flags, - width, height, - &button_layout, - fgeom); -} - -MetaFrames* -meta_frames_new (int screen_number) -{ - GdkScreen *screen; - - screen = gdk_display_get_screen (gdk_display_get_default (), - screen_number); - - return g_object_new (META_TYPE_FRAMES, - "screen", screen, - NULL); -} - -void -meta_frames_manage_window (MetaFrames *frames, - Window xwindow, - GdkWindow *window) -{ - MetaUIFrame *frame; - - g_assert (window); - - frame = g_new (MetaUIFrame, 1); - - frame->window = window; - - gdk_window_set_user_data (frame->window, frames); - - /* Don't set event mask here, it's in frame.c */ - - frame->xwindow = xwindow; - frame->cache_style = NULL; - frame->layout = NULL; - frame->text_height = -1; - frame->title = NULL; - frame->expose_delayed = FALSE; - frame->shape_applied = FALSE; - frame->prelit_control = META_FRAME_CONTROL_NONE; - - /* Don't set the window background yet; we need frame->xwindow to be - * registered with its MetaWindow, which happens after this function - * and meta_ui_create_frame_window() return to meta_window_ensure_frame(). - */ - - meta_core_grab_buttons (gdk_display, frame->xwindow); - - g_hash_table_replace (frames->frames, &frame->xwindow, frame); -} - -void -meta_frames_unmanage_window (MetaFrames *frames, - Window xwindow) -{ - MetaUIFrame *frame; - - clear_tip (frames); - - frame = g_hash_table_lookup (frames->frames, &xwindow); - - if (frame) - { - /* invalidating all caches ensures the frame - * is not actually referenced anymore - */ - invalidate_all_caches (frames); - - /* restore the cursor */ - meta_core_set_screen_cursor (gdk_display, - frame->xwindow, - META_CURSOR_DEFAULT); - - gdk_window_set_user_data (frame->window, NULL); - - if (frames->last_motion_frame == frame) - frames->last_motion_frame = NULL; - - g_hash_table_remove (frames->frames, &frame->xwindow); - - gdk_window_destroy (frame->window); - - if (frame->layout) - g_object_unref (G_OBJECT (frame->layout)); - - if (frame->title) - g_free (frame->title); - - g_free (frame); - } - else - meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow); -} - -static void -meta_frames_realize (GtkWidget *widget) -{ - if (GTK_WIDGET_CLASS (parent_class)->realize) - GTK_WIDGET_CLASS (parent_class)->realize (widget); -} - -static void -meta_frames_unrealize (GtkWidget *widget) -{ - if (GTK_WIDGET_CLASS (parent_class)->unrealize) - GTK_WIDGET_CLASS (parent_class)->unrealize (widget); -} - -static MetaUIFrame* -meta_frames_lookup_window (MetaFrames *frames, - Window xwindow) -{ - MetaUIFrame *frame; - - frame = g_hash_table_lookup (frames->frames, &xwindow); - - return frame; -} - -void -meta_frames_get_geometry (MetaFrames *frames, - Window xwindow, - int *top_height, int *bottom_height, - int *left_width, int *right_width) -{ - MetaFrameFlags flags; - MetaUIFrame *frame; - MetaFrameType type; - - frame = meta_frames_lookup_window (frames, xwindow); - - if (frame == NULL) - meta_bug ("No such frame 0x%lx\n", xwindow); - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_FRAME_TYPE, &type, - META_CORE_GET_END); - - g_return_if_fail (type < META_FRAME_TYPE_LAST); - - meta_frames_ensure_layout (frames, frame); - - /* We can't get the full geometry, because that depends on - * the client window size and probably we're being called - * by the core move/resize code to decide on the client - * window size - */ - meta_theme_get_frame_borders (meta_theme_get_current (), - type, - frame->text_height, - flags, - top_height, bottom_height, - left_width, right_width); -} - -void -meta_frames_reset_bg (MetaFrames *frames, - Window xwindow) -{ - MetaUIFrame *frame; - - frame = meta_frames_lookup_window (frames, xwindow); - - meta_frames_set_window_background (frames, frame); -} - -static void -set_background_none (Display *xdisplay, - Window xwindow) -{ - XSetWindowAttributes attrs; - - attrs.background_pixmap = None; - XChangeWindowAttributes (xdisplay, xwindow, - CWBackPixmap, &attrs); -} - -void -meta_frames_unflicker_bg (MetaFrames *frames, - Window xwindow, - int target_width, - int target_height) -{ - MetaUIFrame *frame; - - frame = meta_frames_lookup_window (frames, xwindow); - g_return_if_fail (frame != NULL); - -#if 0 - pixmap = gdk_pixmap_new (frame->window, - width, height, - -1); - - /* Oops, no way to get the background here */ - - meta_frames_paint_to_drawable (frames, frame, pixmap); -#endif - - set_background_none (gdk_display, frame->xwindow); -} - -void -meta_frames_apply_shapes (MetaFrames *frames, - Window xwindow, - int new_window_width, - int new_window_height, - gboolean window_has_shape) -{ -#ifdef HAVE_SHAPE - /* Apply shapes as if window had new_window_width, new_window_height */ - MetaUIFrame *frame; - MetaFrameGeometry fgeom; - XRectangle xrect; - Region corners_xregion; - Region window_xregion; - - frame = meta_frames_lookup_window (frames, xwindow); - g_return_if_fail (frame != NULL); - - meta_frames_calc_geometry (frames, frame, &fgeom); - - if (!(fgeom.top_left_corner_rounded_radius != 0 || - fgeom.top_right_corner_rounded_radius != 0 || - fgeom.bottom_left_corner_rounded_radius != 0 || - fgeom.bottom_right_corner_rounded_radius != 0 || - window_has_shape)) - { - if (frame->shape_applied) - { - meta_topic (META_DEBUG_SHAPES, - "Unsetting shape mask on frame 0x%lx\n", - frame->xwindow); - - XShapeCombineMask (gdk_display, frame->xwindow, - ShapeBounding, 0, 0, None, ShapeSet); - frame->shape_applied = FALSE; - } - else - { - meta_topic (META_DEBUG_SHAPES, - "Frame 0x%lx still doesn't need a shape mask\n", - frame->xwindow); - } - - return; /* nothing to do */ - } - - corners_xregion = XCreateRegion (); - - if (fgeom.top_left_corner_rounded_radius != 0) - { - const int corner = fgeom.top_left_corner_rounded_radius; - const float radius = sqrt(corner) + corner; - int i; - - for (i=0; i<corner; i++) - { - const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); - xrect.x = 0; - xrect.y = i; - xrect.width = width; - xrect.height = 1; - - XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); - } - } - - if (fgeom.top_right_corner_rounded_radius != 0) - { - const int corner = fgeom.top_right_corner_rounded_radius; - const float radius = sqrt(corner) + corner; - int i; - - for (i=0; i<corner; i++) - { - const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); - xrect.x = new_window_width - width; - xrect.y = i; - xrect.width = width; - xrect.height = 1; - - XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); - } - } - - if (fgeom.bottom_left_corner_rounded_radius != 0) - { - const int corner = fgeom.bottom_left_corner_rounded_radius; - const float radius = sqrt(corner) + corner; - int i; - - for (i=0; i<corner; i++) - { - const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); - xrect.x = 0; - xrect.y = new_window_height - i - 1; - xrect.width = width; - xrect.height = 1; - - XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); - } - } - - if (fgeom.bottom_right_corner_rounded_radius != 0) - { - const int corner = fgeom.bottom_right_corner_rounded_radius; - const float radius = sqrt(corner) + corner; - int i; - - for (i=0; i<corner; i++) - { - const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); - xrect.x = new_window_width - width; - xrect.y = new_window_height - i - 1; - xrect.width = width; - xrect.height = 1; - - XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion); - } - } - - window_xregion = XCreateRegion (); - - xrect.x = 0; - xrect.y = 0; - xrect.width = new_window_width; - xrect.height = new_window_height; - - XUnionRectWithRegion (&xrect, window_xregion, window_xregion); - - XSubtractRegion (window_xregion, corners_xregion, window_xregion); - - XDestroyRegion (corners_xregion); - - if (window_has_shape) - { - /* The client window is oclock or something and has a shape - * mask. To avoid a round trip to get its shape region, we - * create a fake window that's never mapped, build up our shape - * on that, then combine. Wasting the window is assumed cheaper - * than a round trip, but who really knows for sure. - */ - XSetWindowAttributes attrs; - Window shape_window; - Window client_window; - Region client_xregion; - GdkScreen *screen; - int screen_number; - - meta_topic (META_DEBUG_SHAPES, - "Frame 0x%lx needs to incorporate client shape\n", - frame->xwindow); - - screen = gtk_widget_get_screen (GTK_WIDGET (frames)); - screen_number = gdk_x11_screen_get_screen_number (screen); - - attrs.override_redirect = True; - - shape_window = XCreateWindow (gdk_display, - RootWindow (gdk_display, screen_number), - -5000, -5000, - new_window_width, - new_window_height, - 0, - CopyFromParent, - CopyFromParent, - (Visual *)CopyFromParent, - CWOverrideRedirect, - &attrs); - - /* Copy the client's shape to the temporary shape_window */ - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_CLIENT_XWINDOW, &client_window, - META_CORE_GET_END); - - XShapeCombineShape (gdk_display, shape_window, ShapeBounding, - fgeom.left_width, - fgeom.top_height, - client_window, - ShapeBounding, - ShapeSet); - - /* Punch the client area out of the normal frame shape, - * then union it with the shape_window's existing shape - */ - client_xregion = XCreateRegion (); - - xrect.x = fgeom.left_width; - xrect.y = fgeom.top_height; - xrect.width = new_window_width - fgeom.right_width - xrect.x; - xrect.height = new_window_height - fgeom.bottom_height - xrect.y; - - XUnionRectWithRegion (&xrect, client_xregion, client_xregion); - - XSubtractRegion (window_xregion, client_xregion, window_xregion); - - XDestroyRegion (client_xregion); - - XShapeCombineRegion (gdk_display, shape_window, - ShapeBounding, 0, 0, window_xregion, ShapeUnion); - - /* Now copy shape_window shape to the real frame */ - XShapeCombineShape (gdk_display, frame->xwindow, ShapeBounding, - 0, 0, - shape_window, - ShapeBounding, - ShapeSet); - - XDestroyWindow (gdk_display, shape_window); - } - else - { - /* No shape on the client, so just do simple stuff */ - - meta_topic (META_DEBUG_SHAPES, - "Frame 0x%lx has shaped corners\n", - frame->xwindow); - - XShapeCombineRegion (gdk_display, frame->xwindow, - ShapeBounding, 0, 0, window_xregion, ShapeSet); - } - - frame->shape_applied = TRUE; - - XDestroyRegion (window_xregion); -#endif /* HAVE_SHAPE */ -} - -void -meta_frames_move_resize_frame (MetaFrames *frames, - Window xwindow, - int x, - int y, - int width, - int height) -{ - MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow); - int old_x, old_y, old_width, old_height; - - gdk_drawable_get_size (frame->window, &old_width, &old_height); - gdk_window_get_position (frame->window, &old_x, &old_y); - - gdk_window_move_resize (frame->window, x, y, width, height); - - if (old_width != width || old_height != height) - invalidate_whole_window (frames, frame); -} - -void -meta_frames_queue_draw (MetaFrames *frames, - Window xwindow) -{ - MetaUIFrame *frame; - - frame = meta_frames_lookup_window (frames, xwindow); - - invalidate_whole_window (frames, frame); -} - -void -meta_frames_set_title (MetaFrames *frames, - Window xwindow, - const char *title) -{ - MetaUIFrame *frame; - - frame = meta_frames_lookup_window (frames, xwindow); - - g_assert (frame); - - g_free (frame->title); - frame->title = g_strdup (title); - - if (frame->layout) - { - g_object_unref (frame->layout); - frame->layout = NULL; - } - - invalidate_whole_window (frames, frame); -} - -void -meta_frames_repaint_frame (MetaFrames *frames, - Window xwindow) -{ - MetaUIFrame *frame; - - frame = meta_frames_lookup_window (frames, xwindow); - - g_assert (frame); - - /* repaint everything, so the other frame don't - * lag behind if they are exposed - */ - gdk_window_process_all_updates (); -} - -static void -show_tip_now (MetaFrames *frames) -{ - const char *tiptext; - MetaUIFrame *frame; - int x, y, root_x, root_y; - Window root, child; - guint mask; - MetaFrameControl control; - - frame = frames->last_motion_frame; - if (frame == NULL) - return; - - XQueryPointer (gdk_display, - frame->xwindow, - &root, &child, - &root_x, &root_y, - &x, &y, - &mask); - - control = get_control (frames, frame, x, y); - - tiptext = NULL; - switch (control) - { - case META_FRAME_CONTROL_TITLE: - break; - case META_FRAME_CONTROL_DELETE: - tiptext = _("Close Window"); - break; - case META_FRAME_CONTROL_MENU: - tiptext = _("Window Menu"); - break; - case META_FRAME_CONTROL_MINIMIZE: - tiptext = _("Minimize Window"); - break; - case META_FRAME_CONTROL_MAXIMIZE: - tiptext = _("Maximize Window"); - break; - case META_FRAME_CONTROL_UNMAXIMIZE: - tiptext = _("Restore Window"); - break; - case META_FRAME_CONTROL_SHADE: - tiptext = _("Roll Up Window"); - break; - case META_FRAME_CONTROL_UNSHADE: - tiptext = _("Unroll Window"); - break; - case META_FRAME_CONTROL_ABOVE: - tiptext = _("Keep Window On Top"); - break; - case META_FRAME_CONTROL_UNABOVE: - tiptext = _("Remove Window From Top"); - break; - case META_FRAME_CONTROL_STICK: - tiptext = _("Always On Visible Workspace"); - break; - case META_FRAME_CONTROL_UNSTICK: - tiptext = _("Put Window On Only One Workspace"); - break; - case META_FRAME_CONTROL_RESIZE_SE: - break; - case META_FRAME_CONTROL_RESIZE_S: - break; - case META_FRAME_CONTROL_RESIZE_SW: - break; - case META_FRAME_CONTROL_RESIZE_N: - break; - case META_FRAME_CONTROL_RESIZE_NE: - break; - case META_FRAME_CONTROL_RESIZE_NW: - break; - case META_FRAME_CONTROL_RESIZE_W: - break; - case META_FRAME_CONTROL_RESIZE_E: - break; - case META_FRAME_CONTROL_NONE: - break; - case META_FRAME_CONTROL_CLIENT_AREA: - break; - } - - if (tiptext) - { - MetaFrameGeometry fgeom; - GdkRectangle *rect; - int dx, dy; - int screen_number; - - meta_frames_calc_geometry (frames, frame, &fgeom); - - rect = control_rect (control, &fgeom); - - /* get conversion delta for root-to-frame coords */ - dx = root_x - x; - dy = root_y - y; - - /* Align the tooltip to the button right end if RTL */ - if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - dx += rect->width; - - screen_number = gdk_screen_get_number (gtk_widget_get_screen (GTK_WIDGET (frames))); - - meta_fixed_tip_show (gdk_display, - screen_number, - rect->x + dx, - rect->y + rect->height + 2 + dy, - tiptext); - } -} - -static gboolean -tip_timeout_func (gpointer data) -{ - MetaFrames *frames; - - frames = data; - - show_tip_now (frames); - - return FALSE; -} - -#define TIP_DELAY 450 -static void -queue_tip (MetaFrames *frames) -{ - clear_tip (frames); - - frames->tooltip_timeout = g_timeout_add (TIP_DELAY, - tip_timeout_func, - frames); -} - -static void -clear_tip (MetaFrames *frames) -{ - if (frames->tooltip_timeout) - { - g_source_remove (frames->tooltip_timeout); - frames->tooltip_timeout = 0; - } - meta_fixed_tip_hide (); -} - -static void -redraw_control (MetaFrames *frames, - MetaUIFrame *frame, - MetaFrameControl control) -{ - MetaFrameGeometry fgeom; - GdkRectangle *rect; - - meta_frames_calc_geometry (frames, frame, &fgeom); - - rect = control_rect (control, &fgeom); - - gdk_window_invalidate_rect (frame->window, rect, FALSE); - invalidate_cache (frames, frame); -} - -static gboolean -meta_frame_titlebar_event (MetaUIFrame *frame, - GdkEventButton *event, - int action) -{ - MetaFrameFlags flags; - - switch (action) - { - case META_ACTION_TITLEBAR_TOGGLE_SHADE: - { - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_END); - - if (flags & META_FRAME_ALLOWS_SHADE) - { - if (flags & META_FRAME_SHADED) - meta_core_unshade (gdk_display, - frame->xwindow, - event->time); - else - meta_core_shade (gdk_display, - frame->xwindow, - event->time); - } - } - break; - - case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE: - { - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_END); - - if (flags & META_FRAME_ALLOWS_MAXIMIZE) - { - meta_core_toggle_maximize (gdk_display, frame->xwindow); - } - } - break; - - case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_HORIZONTALLY: - { - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_END); - - if (flags & META_FRAME_ALLOWS_MAXIMIZE) - { - meta_core_toggle_maximize_horizontally (gdk_display, frame->xwindow); - } - } - break; - - case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_VERTICALLY: - { - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_END); - - if (flags & META_FRAME_ALLOWS_MAXIMIZE) - { - meta_core_toggle_maximize_vertically (gdk_display, frame->xwindow); - } - } - break; - - case META_ACTION_TITLEBAR_MINIMIZE: - { - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_END); - - if (flags & META_FRAME_ALLOWS_MINIMIZE) - { - meta_core_minimize (gdk_display, frame->xwindow); - } - } - break; - - case META_ACTION_TITLEBAR_NONE: - /* Yaay, a sane user that doesn't use that other weird crap! */ - break; - - case META_ACTION_TITLEBAR_LOWER: - meta_core_user_lower_and_unfocus (gdk_display, - frame->xwindow, - event->time); - break; - - case META_ACTION_TITLEBAR_MENU: - meta_core_show_window_menu (gdk_display, - frame->xwindow, - event->x_root, - event->y_root, - event->button, - event->time); - break; - - case META_ACTION_TITLEBAR_LAST: - break; - } - - return TRUE; -} - -static gboolean -meta_frame_double_click_event (MetaUIFrame *frame, - GdkEventButton *event) -{ - int action = meta_prefs_get_action_double_click_titlebar (); - - return meta_frame_titlebar_event (frame, event, action); -} - -static gboolean -meta_frame_middle_click_event (MetaUIFrame *frame, - GdkEventButton *event) -{ - int action = meta_prefs_get_action_middle_click_titlebar(); - - return meta_frame_titlebar_event (frame, event, action); -} - -static gboolean -meta_frame_right_click_event(MetaUIFrame *frame, - GdkEventButton *event) -{ - int action = meta_prefs_get_action_right_click_titlebar(); - - return meta_frame_titlebar_event (frame, event, action); -} - -static gboolean -meta_frames_button_press_event (GtkWidget *widget, - GdkEventButton *event) -{ - MetaUIFrame *frame; - MetaFrames *frames; - MetaFrameControl control; - - frames = META_FRAMES (widget); - - /* Remember that the display may have already done something with this event. - * If so there's probably a GrabOp in effect. - */ - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - clear_tip (frames); - - control = get_control (frames, frame, event->x, event->y); - - /* focus on click, even if click was on client area */ - if (event->button == 1 && - !(control == META_FRAME_CONTROL_MINIMIZE || - control == META_FRAME_CONTROL_DELETE || - control == META_FRAME_CONTROL_MAXIMIZE)) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing window with frame 0x%lx due to button 1 press\n", - frame->xwindow); - meta_core_user_focus (gdk_display, - frame->xwindow, - event->time); - } - - /* don't do the rest of this if on client area */ - if (control == META_FRAME_CONTROL_CLIENT_AREA) - return FALSE; /* not on the frame, just passed through from client */ - - /* We want to shade even if we have a GrabOp, since we'll have a move grab - * if we double click the titlebar. - */ - if (control == META_FRAME_CONTROL_TITLE && - event->button == 1 && - event->type == GDK_2BUTTON_PRESS) - { - meta_core_end_grab_op (gdk_display, event->time); - return meta_frame_double_click_event (frame, event); - } - - if (meta_core_get_grab_op (gdk_display) != - META_GRAB_OP_NONE) - return FALSE; /* already up to something */ - - if (event->button == 1 && - (control == META_FRAME_CONTROL_MAXIMIZE || - control == META_FRAME_CONTROL_UNMAXIMIZE || - control == META_FRAME_CONTROL_MINIMIZE || - control == META_FRAME_CONTROL_DELETE || - control == META_FRAME_CONTROL_SHADE || - control == META_FRAME_CONTROL_UNSHADE || - control == META_FRAME_CONTROL_ABOVE || - control == META_FRAME_CONTROL_UNABOVE || - control == META_FRAME_CONTROL_STICK || - control == META_FRAME_CONTROL_UNSTICK || - control == META_FRAME_CONTROL_MENU)) - { - MetaGrabOp op = META_GRAB_OP_NONE; - - switch (control) - { - case META_FRAME_CONTROL_MINIMIZE: - op = META_GRAB_OP_CLICKING_MINIMIZE; - break; - case META_FRAME_CONTROL_MAXIMIZE: - op = META_GRAB_OP_CLICKING_MAXIMIZE; - break; - case META_FRAME_CONTROL_UNMAXIMIZE: - op = META_GRAB_OP_CLICKING_UNMAXIMIZE; - break; - case META_FRAME_CONTROL_DELETE: - op = META_GRAB_OP_CLICKING_DELETE; - break; - case META_FRAME_CONTROL_MENU: - op = META_GRAB_OP_CLICKING_MENU; - break; - case META_FRAME_CONTROL_SHADE: - op = META_GRAB_OP_CLICKING_SHADE; - break; - case META_FRAME_CONTROL_UNSHADE: - op = META_GRAB_OP_CLICKING_UNSHADE; - break; - case META_FRAME_CONTROL_ABOVE: - op = META_GRAB_OP_CLICKING_ABOVE; - break; - case META_FRAME_CONTROL_UNABOVE: - op = META_GRAB_OP_CLICKING_UNABOVE; - break; - case META_FRAME_CONTROL_STICK: - op = META_GRAB_OP_CLICKING_STICK; - break; - case META_FRAME_CONTROL_UNSTICK: - op = META_GRAB_OP_CLICKING_UNSTICK; - break; - default: - g_assert_not_reached (); - break; - } - - meta_core_begin_grab_op (gdk_display, - frame->xwindow, - op, - TRUE, - TRUE, - event->button, - 0, - event->time, - event->x_root, - event->y_root); - - frame->prelit_control = control; - redraw_control (frames, frame, control); - - if (op == META_GRAB_OP_CLICKING_MENU) - { - MetaFrameGeometry fgeom; - GdkRectangle *rect; - int dx, dy; - - meta_frames_calc_geometry (frames, frame, &fgeom); - - rect = control_rect (META_FRAME_CONTROL_MENU, &fgeom); - - /* get delta to convert to root coords */ - dx = event->x_root - event->x; - dy = event->y_root - event->y; - - /* Align to the right end of the menu rectangle if RTL */ - if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - dx += rect->width; - - meta_core_show_window_menu (gdk_display, - frame->xwindow, - rect->x + dx, - rect->y + rect->height + dy, - event->button, - event->time); - } - } - else if (event->button == 1 && - (control == META_FRAME_CONTROL_RESIZE_SE || - control == META_FRAME_CONTROL_RESIZE_S || - control == META_FRAME_CONTROL_RESIZE_SW || - control == META_FRAME_CONTROL_RESIZE_NE || - control == META_FRAME_CONTROL_RESIZE_N || - control == META_FRAME_CONTROL_RESIZE_NW || - control == META_FRAME_CONTROL_RESIZE_E || - control == META_FRAME_CONTROL_RESIZE_W)) - { - MetaGrabOp op; - gboolean titlebar_is_onscreen; - - op = META_GRAB_OP_NONE; - - switch (control) - { - case META_FRAME_CONTROL_RESIZE_SE: - op = META_GRAB_OP_RESIZING_SE; - break; - case META_FRAME_CONTROL_RESIZE_S: - op = META_GRAB_OP_RESIZING_S; - break; - case META_FRAME_CONTROL_RESIZE_SW: - op = META_GRAB_OP_RESIZING_SW; - break; - case META_FRAME_CONTROL_RESIZE_NE: - op = META_GRAB_OP_RESIZING_NE; - break; - case META_FRAME_CONTROL_RESIZE_N: - op = META_GRAB_OP_RESIZING_N; - break; - case META_FRAME_CONTROL_RESIZE_NW: - op = META_GRAB_OP_RESIZING_NW; - break; - case META_FRAME_CONTROL_RESIZE_E: - op = META_GRAB_OP_RESIZING_E; - break; - case META_FRAME_CONTROL_RESIZE_W: - op = META_GRAB_OP_RESIZING_W; - break; - default: - g_assert_not_reached (); - break; - } - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_IS_TITLEBAR_ONSCREEN, &titlebar_is_onscreen, - META_CORE_GET_END); - - if (!titlebar_is_onscreen) - meta_core_show_window_menu (gdk_display, - frame->xwindow, - event->x_root, - event->y_root, - event->button, - event->time); - else - meta_core_begin_grab_op (gdk_display, - frame->xwindow, - op, - TRUE, - TRUE, - event->button, - 0, - event->time, - event->x_root, - event->y_root); - } - else if (control == META_FRAME_CONTROL_TITLE && - event->button == 1) - { - MetaFrameFlags flags; - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_END); - - if (flags & META_FRAME_ALLOWS_MOVE) - { - meta_core_begin_grab_op (gdk_display, - frame->xwindow, - META_GRAB_OP_MOVING, - TRUE, - TRUE, - event->button, - 0, - event->time, - event->x_root, - event->y_root); - } - } - else if (event->button == 2) - { - return meta_frame_middle_click_event (frame, event); - } - else if (event->button == 3) - { - return meta_frame_right_click_event (frame, event); - } - - return TRUE; -} - -void -meta_frames_notify_menu_hide (MetaFrames *frames) -{ - if (meta_core_get_grab_op (gdk_display) == - META_GRAB_OP_CLICKING_MENU) - { - Window grab_frame; - - grab_frame = meta_core_get_grab_frame (gdk_display); - - if (grab_frame != None) - { - MetaUIFrame *frame; - - frame = meta_frames_lookup_window (frames, grab_frame); - - if (frame) - { - redraw_control (frames, frame, - META_FRAME_CONTROL_MENU); - meta_core_end_grab_op (gdk_display, CurrentTime); - } - } - } -} - -static gboolean -meta_frames_button_release_event (GtkWidget *widget, - GdkEventButton *event) -{ - MetaUIFrame *frame; - MetaFrames *frames; - MetaGrabOp op; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - clear_tip (frames); - - op = meta_core_get_grab_op (gdk_display); - - if (op == META_GRAB_OP_NONE) - return FALSE; - - /* We only handle the releases we handled the presses for (things - * involving frame controls). Window ops that don't require a - * frame are handled in the Xlib part of the code, display.c/window.c - */ - if (frame->xwindow == meta_core_get_grab_frame (gdk_display) && - ((int) event->button) == meta_core_get_grab_button (gdk_display)) - { - MetaFrameControl control; - - control = get_control (frames, frame, event->x, event->y); - - switch (op) - { - case META_GRAB_OP_CLICKING_MINIMIZE: - if (control == META_FRAME_CONTROL_MINIMIZE) - meta_core_minimize (gdk_display, frame->xwindow); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_MAXIMIZE: - if (control == META_FRAME_CONTROL_MAXIMIZE) - { - /* Focus the window on the maximize */ - meta_core_user_focus (gdk_display, - frame->xwindow, - event->time); - meta_core_maximize (gdk_display, frame->xwindow); - } - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_UNMAXIMIZE: - if (control == META_FRAME_CONTROL_UNMAXIMIZE) - meta_core_unmaximize (gdk_display, frame->xwindow); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_DELETE: - if (control == META_FRAME_CONTROL_DELETE) - meta_core_delete (gdk_display, frame->xwindow, event->time); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_MENU: - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_SHADE: - if (control == META_FRAME_CONTROL_SHADE) - meta_core_shade (gdk_display, frame->xwindow, event->time); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_UNSHADE: - if (control == META_FRAME_CONTROL_UNSHADE) - meta_core_unshade (gdk_display, frame->xwindow, event->time); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_ABOVE: - if (control == META_FRAME_CONTROL_ABOVE) - meta_core_make_above (gdk_display, frame->xwindow); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_UNABOVE: - if (control == META_FRAME_CONTROL_UNABOVE) - meta_core_unmake_above (gdk_display, frame->xwindow); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_STICK: - if (control == META_FRAME_CONTROL_STICK) - meta_core_stick (gdk_display, frame->xwindow); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - case META_GRAB_OP_CLICKING_UNSTICK: - if (control == META_FRAME_CONTROL_UNSTICK) - meta_core_unstick (gdk_display, frame->xwindow); - - meta_core_end_grab_op (gdk_display, event->time); - break; - - default: - break; - } - - /* Update the prelit control regardless of what button the mouse - * was released over; needed so that the new button can become - * prelit so to let the user know that it can now be pressed. - * :) - */ - meta_frames_update_prelit_control (frames, frame, control); - } - - return TRUE; -} - -static void -meta_frames_update_prelit_control (MetaFrames *frames, - MetaUIFrame *frame, - MetaFrameControl control) -{ - MetaFrameControl old_control; - MetaCursor cursor; - - - meta_verbose ("Updating prelit control from %u to %u\n", - frame->prelit_control, control); - - cursor = META_CURSOR_DEFAULT; - - switch (control) - { - case META_FRAME_CONTROL_CLIENT_AREA: - break; - case META_FRAME_CONTROL_NONE: - break; - case META_FRAME_CONTROL_TITLE: - break; - case META_FRAME_CONTROL_DELETE: - break; - case META_FRAME_CONTROL_MENU: - break; - case META_FRAME_CONTROL_MINIMIZE: - break; - case META_FRAME_CONTROL_MAXIMIZE: - break; - case META_FRAME_CONTROL_UNMAXIMIZE: - break; - case META_FRAME_CONTROL_SHADE: - break; - case META_FRAME_CONTROL_UNSHADE: - break; - case META_FRAME_CONTROL_ABOVE: - break; - case META_FRAME_CONTROL_UNABOVE: - break; - case META_FRAME_CONTROL_STICK: - break; - case META_FRAME_CONTROL_UNSTICK: - break; - case META_FRAME_CONTROL_RESIZE_SE: - cursor = META_CURSOR_SE_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_S: - cursor = META_CURSOR_SOUTH_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_SW: - cursor = META_CURSOR_SW_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_N: - cursor = META_CURSOR_NORTH_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_NE: - cursor = META_CURSOR_NE_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_NW: - cursor = META_CURSOR_NW_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_W: - cursor = META_CURSOR_WEST_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_E: - cursor = META_CURSOR_EAST_RESIZE; - break; - } - - /* set/unset the prelight cursor */ - meta_core_set_screen_cursor (gdk_display, - frame->xwindow, - cursor); - - switch (control) - { - case META_FRAME_CONTROL_MENU: - case META_FRAME_CONTROL_MINIMIZE: - case META_FRAME_CONTROL_MAXIMIZE: - case META_FRAME_CONTROL_DELETE: - case META_FRAME_CONTROL_SHADE: - case META_FRAME_CONTROL_UNSHADE: - case META_FRAME_CONTROL_ABOVE: - case META_FRAME_CONTROL_UNABOVE: - case META_FRAME_CONTROL_STICK: - case META_FRAME_CONTROL_UNSTICK: - case META_FRAME_CONTROL_UNMAXIMIZE: - /* leave control set */ - break; - default: - /* Only prelight buttons */ - control = META_FRAME_CONTROL_NONE; - break; - } - - if (control == frame->prelit_control) - return; - - /* Save the old control so we can unprelight it */ - old_control = frame->prelit_control; - - frame->prelit_control = control; - - redraw_control (frames, frame, old_control); - redraw_control (frames, frame, control); -} - -static gboolean -meta_frames_motion_notify_event (GtkWidget *widget, - GdkEventMotion *event) -{ - MetaUIFrame *frame; - MetaFrames *frames; - MetaGrabOp grab_op; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - clear_tip (frames); - - frames->last_motion_frame = frame; - - grab_op = meta_core_get_grab_op (gdk_display); - - switch (grab_op) - { - case META_GRAB_OP_CLICKING_MENU: - case META_GRAB_OP_CLICKING_DELETE: - case META_GRAB_OP_CLICKING_MINIMIZE: - case META_GRAB_OP_CLICKING_MAXIMIZE: - case META_GRAB_OP_CLICKING_UNMAXIMIZE: - case META_GRAB_OP_CLICKING_SHADE: - case META_GRAB_OP_CLICKING_UNSHADE: - case META_GRAB_OP_CLICKING_ABOVE: - case META_GRAB_OP_CLICKING_UNABOVE: - case META_GRAB_OP_CLICKING_STICK: - case META_GRAB_OP_CLICKING_UNSTICK: - { - MetaFrameControl control; - int x, y; - - gdk_window_get_pointer (frame->window, &x, &y, NULL); - - /* Control is set to none unless it matches - * the current grab - */ - control = get_control (frames, frame, x, y); - if (! ((control == META_FRAME_CONTROL_MENU && - grab_op == META_GRAB_OP_CLICKING_MENU) || - (control == META_FRAME_CONTROL_DELETE && - grab_op == META_GRAB_OP_CLICKING_DELETE) || - (control == META_FRAME_CONTROL_MINIMIZE && - grab_op == META_GRAB_OP_CLICKING_MINIMIZE) || - ((control == META_FRAME_CONTROL_MAXIMIZE || - control == META_FRAME_CONTROL_UNMAXIMIZE) && - (grab_op == META_GRAB_OP_CLICKING_MAXIMIZE || - grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE)) || - (control == META_FRAME_CONTROL_SHADE && - grab_op == META_GRAB_OP_CLICKING_SHADE) || - (control == META_FRAME_CONTROL_UNSHADE && - grab_op == META_GRAB_OP_CLICKING_UNSHADE) || - (control == META_FRAME_CONTROL_ABOVE && - grab_op == META_GRAB_OP_CLICKING_ABOVE) || - (control == META_FRAME_CONTROL_UNABOVE && - grab_op == META_GRAB_OP_CLICKING_UNABOVE) || - (control == META_FRAME_CONTROL_STICK && - grab_op == META_GRAB_OP_CLICKING_STICK) || - (control == META_FRAME_CONTROL_UNSTICK && - grab_op == META_GRAB_OP_CLICKING_UNSTICK))) - control = META_FRAME_CONTROL_NONE; - - /* Update prelit control and cursor */ - meta_frames_update_prelit_control (frames, frame, control); - - /* No tooltip while in the process of clicking */ - } - break; - case META_GRAB_OP_NONE: - { - MetaFrameControl control; - int x, y; - - gdk_window_get_pointer (frame->window, &x, &y, NULL); - - control = get_control (frames, frame, x, y); - - /* Update prelit control and cursor */ - meta_frames_update_prelit_control (frames, frame, control); - - queue_tip (frames); - } - break; - - default: - break; - } - - return TRUE; -} - -static gboolean -meta_frames_destroy_event (GtkWidget *widget, - GdkEventAny *event) -{ - MetaUIFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - return TRUE; -} - -/* Cut and paste from GDK */ -static GdkGC * -get_bg_gc (GdkWindow *window, int x_offset, int y_offset) -{ - GdkWindowObject *private = (GdkWindowObject *)window; - guint gc_mask = 0; - GdkGCValues gc_values; - - if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent) - { - return get_bg_gc (GDK_WINDOW (private->parent), - x_offset + private->x, - y_offset + private->y); - } - else if (private->bg_pixmap && - private->bg_pixmap != GDK_PARENT_RELATIVE_BG && - private->bg_pixmap != GDK_NO_BG) - { - gc_values.fill = GDK_TILED; - gc_values.tile = private->bg_pixmap; - gc_values.ts_x_origin = x_offset; - gc_values.ts_y_origin = y_offset; - - gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN; - - return gdk_gc_new_with_values (window, &gc_values, gc_mask); - } - else - { - GdkGC *gc = gdk_gc_new (window); - - gdk_gc_set_foreground (gc, &(private->bg_color)); - - return gc; - } -} - -static void -clear_backing (GdkPixmap *pixmap, - GdkWindow *window, - int xoffset, int yoffset) -{ - GdkGC *tmp_gc = get_bg_gc (window, xoffset, yoffset); - - gdk_draw_rectangle (pixmap, tmp_gc, TRUE, - 0, 0, -1, -1); - - g_object_unref (tmp_gc); -} - -/* Returns a pixmap with a piece of the windows frame painted on it. -*/ - -static GdkPixmap * -generate_pixmap (MetaFrames *frames, - MetaUIFrame *frame, - MetaRectangle rect) -{ - GdkRectangle rectangle; - GdkRegion *region; - GdkPixmap *result; - - rectangle.x = rect.x; - rectangle.y = rect.y; - rectangle.width = MAX (rect.width, 1); - rectangle.height = MAX (rect.height, 1); - - result = gdk_pixmap_new (frame->window, - rectangle.width, rectangle.height, -1); - - clear_backing (result, frame->window, rectangle.x, rectangle.y); - - region = gdk_region_rectangle (&rectangle); - - meta_frames_paint_to_drawable (frames, frame, result, region, - -rectangle.x, -rectangle.y); - - gdk_region_destroy (region); - - return result; -} - - -static void -populate_cache (MetaFrames *frames, - MetaUIFrame *frame) -{ - int top, bottom, left, right; - int width, height; - int frame_width, frame_height, screen_width, screen_height; - CachedPixels *pixels; - MetaFrameType frame_type; - MetaFrameFlags frame_flags; - int i; - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_WIDTH, &frame_width, - META_CORE_GET_FRAME_HEIGHT, &frame_height, - META_CORE_GET_SCREEN_WIDTH, &screen_width, - META_CORE_GET_SCREEN_HEIGHT, &screen_height, - META_CORE_GET_CLIENT_WIDTH, &width, - META_CORE_GET_CLIENT_HEIGHT, &height, - META_CORE_GET_FRAME_TYPE, &frame_type, - META_CORE_GET_FRAME_FLAGS, &frame_flags, - META_CORE_GET_END); - - /* don't cache extremely large windows */ - if (frame_width > 2 * screen_width || - frame_height > 2 * screen_height) - { - return; - } - - meta_theme_get_frame_borders (meta_theme_get_current (), - frame_type, - frame->text_height, - frame_flags, - &top, &bottom, &left, &right); - - pixels = get_cache (frames, frame); - - /* Setup the rectangles for the four frame borders. First top, then - left, right and bottom. */ - pixels->piece[0].rect.x = 0; - pixels->piece[0].rect.y = 0; - pixels->piece[0].rect.width = left + width + right; - pixels->piece[0].rect.height = top; - - pixels->piece[1].rect.x = 0; - pixels->piece[1].rect.y = top; - pixels->piece[1].rect.width = left; - pixels->piece[1].rect.height = height; - - pixels->piece[2].rect.x = left + width; - pixels->piece[2].rect.y = top; - pixels->piece[2].rect.width = right; - pixels->piece[2].rect.height = height; - - pixels->piece[3].rect.x = 0; - pixels->piece[3].rect.y = top + height; - pixels->piece[3].rect.width = left + width + right; - pixels->piece[3].rect.height = bottom; - - for (i = 0; i < 4; i++) - { - CachedFramePiece *piece = &pixels->piece[i]; - if (!piece->pixmap) - piece->pixmap = generate_pixmap (frames, frame, piece->rect); - } - - if (frames->invalidate_cache_timeout_id) - g_source_remove (frames->invalidate_cache_timeout_id); - - frames->invalidate_cache_timeout_id = g_timeout_add (1000, invalidate_cache_timeout, frames); - - if (!g_list_find (frames->invalidate_frames, frame)) - frames->invalidate_frames = - g_list_prepend (frames->invalidate_frames, frame); -} - -static void -clip_to_screen (GdkRegion *region, MetaUIFrame *frame) -{ - GdkRectangle frame_area; - GdkRectangle screen_area = { 0, 0, 0, 0 }; - GdkRegion *tmp_region; - - /* Chop off stuff outside the screen; this optimization - * is crucial to handle huge client windows, - * like "xterm -geometry 1000x1000" - */ - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_X, &frame_area.x, - META_CORE_GET_FRAME_Y, &frame_area.y, - META_CORE_GET_FRAME_WIDTH, &frame_area.width, - META_CORE_GET_FRAME_HEIGHT, &frame_area.height, - META_CORE_GET_SCREEN_WIDTH, &screen_area.height, - META_CORE_GET_SCREEN_HEIGHT, &screen_area.height, - META_CORE_GET_END); - - gdk_region_offset (region, frame_area.x, frame_area.y); - - tmp_region = gdk_region_rectangle (&frame_area); - gdk_region_intersect (region, tmp_region); - gdk_region_destroy (tmp_region); - - gdk_region_offset (region, - frame_area.x, - frame_area.y); -} - -static void -subtract_from_region (GdkRegion *region, GdkDrawable *drawable, - gint x, gint y) -{ - GdkRectangle rect; - GdkRegion *reg_rect; - - gdk_drawable_get_size (drawable, &rect.width, &rect.height); - rect.x = x; - rect.y = y; - - reg_rect = gdk_region_rectangle (&rect); - gdk_region_subtract (region, reg_rect); - gdk_region_destroy (reg_rect); -} - -static void -cached_pixels_draw (CachedPixels *pixels, - GdkWindow *window, - GdkRegion *region) -{ - GdkGC *gc; - int i; - - gc = gdk_gc_new (window); - - for (i = 0; i < 4; i++) - { - CachedFramePiece *piece; - piece = &pixels->piece[i]; - - if (piece->pixmap) - { - gdk_draw_drawable (window, gc, piece->pixmap, - 0, 0, - piece->rect.x, piece->rect.y, - -1, -1); - subtract_from_region (region, piece->pixmap, - piece->rect.x, piece->rect.y); - } - } - - g_object_unref (gc); -} - -static gboolean -meta_frames_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - MetaUIFrame *frame; - MetaFrames *frames; - GdkRegion *region; - CachedPixels *pixels; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - if (frames->expose_delay_count > 0) - { - /* Redraw this entire frame later */ - frame->expose_delayed = TRUE; - return TRUE; - } - - populate_cache (frames, frame); - - region = gdk_region_copy (event->region); - - pixels = get_cache (frames, frame); - - cached_pixels_draw (pixels, frame->window, region); - - clip_to_screen (region, frame); - meta_frames_paint_to_drawable (frames, frame, frame->window, region, 0, 0); - - gdk_region_destroy (region); - - return TRUE; -} - -/* How far off the screen edge the window decorations should - * be drawn. Used only in meta_frames_paint_to_drawable, below. - */ -#define DECORATING_BORDER 100 - -static void -meta_frames_paint_to_drawable (MetaFrames *frames, - MetaUIFrame *frame, - GdkDrawable *drawable, - GdkRegion *region, - int x_offset, - int y_offset) -{ - GtkWidget *widget; - MetaFrameFlags flags; - MetaFrameType type; - GdkPixbuf *mini_icon; - GdkPixbuf *icon; - int w, h; - MetaButtonState button_states[META_BUTTON_TYPE_LAST]; - Window grab_frame; - int i; - MetaButtonLayout button_layout; - MetaGrabOp grab_op; - - widget = GTK_WIDGET (frames); - - for (i = 0; i < META_BUTTON_TYPE_LAST; i++) - button_states[i] = META_BUTTON_STATE_NORMAL; - - grab_frame = meta_core_get_grab_frame (gdk_display); - grab_op = meta_core_get_grab_op (gdk_display); - if (grab_frame != frame->xwindow) - grab_op = META_GRAB_OP_NONE; - - /* Set prelight state */ - switch (frame->prelit_control) - { - case META_FRAME_CONTROL_MENU: - if (grab_op == META_GRAB_OP_CLICKING_MENU) - button_states[META_BUTTON_TYPE_MENU] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_MENU] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_MINIMIZE: - if (grab_op == META_GRAB_OP_CLICKING_MINIMIZE) - button_states[META_BUTTON_TYPE_MINIMIZE] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_MINIMIZE] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_MAXIMIZE: - if (grab_op == META_GRAB_OP_CLICKING_MAXIMIZE) - button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_UNMAXIMIZE: - if (grab_op == META_GRAB_OP_CLICKING_UNMAXIMIZE) - button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_MAXIMIZE] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_SHADE: - if (grab_op == META_GRAB_OP_CLICKING_SHADE) - button_states[META_BUTTON_TYPE_SHADE] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_SHADE] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_UNSHADE: - if (grab_op == META_GRAB_OP_CLICKING_UNSHADE) - button_states[META_BUTTON_TYPE_UNSHADE] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_UNSHADE] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_ABOVE: - if (grab_op == META_GRAB_OP_CLICKING_ABOVE) - button_states[META_BUTTON_TYPE_ABOVE] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_ABOVE] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_UNABOVE: - if (grab_op == META_GRAB_OP_CLICKING_UNABOVE) - button_states[META_BUTTON_TYPE_UNABOVE] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_UNABOVE] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_STICK: - if (grab_op == META_GRAB_OP_CLICKING_STICK) - button_states[META_BUTTON_TYPE_STICK] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_STICK] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_UNSTICK: - if (grab_op == META_GRAB_OP_CLICKING_UNSTICK) - button_states[META_BUTTON_TYPE_UNSTICK] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_UNSTICK] = META_BUTTON_STATE_PRELIGHT; - break; - case META_FRAME_CONTROL_DELETE: - if (grab_op == META_GRAB_OP_CLICKING_DELETE) - button_states[META_BUTTON_TYPE_CLOSE] = META_BUTTON_STATE_PRESSED; - else - button_states[META_BUTTON_TYPE_CLOSE] = META_BUTTON_STATE_PRELIGHT; - break; - default: - break; - } - - /* Map button function states to button position states */ - button_states[META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND] = - button_states[META_BUTTON_TYPE_MENU]; - button_states[META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND] = - META_BUTTON_STATE_NORMAL; - button_states[META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND] = - META_BUTTON_STATE_NORMAL; - button_states[META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND] = - button_states[META_BUTTON_TYPE_MINIMIZE]; - button_states[META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND] = - button_states[META_BUTTON_TYPE_MAXIMIZE]; - button_states[META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND] = - button_states[META_BUTTON_TYPE_CLOSE]; - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_FRAME_TYPE, &type, - META_CORE_GET_MINI_ICON, &mini_icon, - META_CORE_GET_ICON, &icon, - META_CORE_GET_CLIENT_WIDTH, &w, - META_CORE_GET_CLIENT_HEIGHT, &h, - META_CORE_GET_END); - - meta_frames_ensure_layout (frames, frame); - - meta_prefs_get_button_layout (&button_layout); - - if (G_LIKELY (GDK_IS_WINDOW (drawable))) - { - /* A window; happens about 2/3 of the time */ - - GdkRectangle area, *areas; - int n_areas; - int screen_width, screen_height; - GdkRegion *edges, *tmp_region; - int top, bottom, left, right; - - /* Repaint each side of the frame */ - - meta_theme_get_frame_borders (meta_theme_get_current (), - type, frame->text_height, flags, - &top, &bottom, &left, &right); - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_SCREEN_WIDTH, &screen_width, - META_CORE_GET_SCREEN_HEIGHT, &screen_height, - META_CORE_GET_END); - - edges = gdk_region_copy (region); - - /* Punch out the client area */ - - area.x = left; - area.y = top; - area.width = w; - area.height = h; - tmp_region = gdk_region_rectangle (&area); - gdk_region_subtract (edges, tmp_region); - gdk_region_destroy (tmp_region); - - /* Now draw remaining portion of region */ - - gdk_region_get_rectangles (edges, &areas, &n_areas); - - for (i = 0; i < n_areas; i++) - { - /* Bug 399529: clamp areas[i] so that it doesn't go too far - * off the edge of the screen. This works around a GDK bug - * which makes gdk_window_begin_paint_rect cause an X error - * if the window is insanely huge. If the client is a GDK program - * and does this, it will still probably cause an X error in that - * program, but the last thing we want is for Metacity to crash - * because it attempted to decorate the silly window. - */ - - areas[i].x = MAX (areas[i].x, -DECORATING_BORDER); - areas[i].y = MAX (areas[i].y, -DECORATING_BORDER); - if (areas[i].x+areas[i].width > screen_width + DECORATING_BORDER) - areas[i].width = MIN (0, screen_width - areas[i].x); - if (areas[i].y+areas[i].height > screen_height + DECORATING_BORDER) - areas[i].height = MIN (0, screen_height - areas[i].y); - - /* Okay, so let's start painting. */ - - gdk_window_begin_paint_rect (drawable, &areas[i]); - - meta_theme_draw_frame (meta_theme_get_current (), - widget, - drawable, - NULL, /* &areas[i], */ - x_offset, y_offset, - type, - flags, - w, h, - frame->layout, - frame->text_height, - &button_layout, - button_states, - mini_icon, icon); - - gdk_window_end_paint (drawable); - } - - g_free (areas); - gdk_region_destroy (edges); - - } - else - { - /* Not a window; happens about 1/3 of the time */ - - meta_theme_draw_frame (meta_theme_get_current (), - widget, - drawable, - NULL, - x_offset, y_offset, - type, - flags, - w, h, - frame->layout, - frame->text_height, - &button_layout, - button_states, - mini_icon, icon); - } - -} - -static void -meta_frames_set_window_background (MetaFrames *frames, - MetaUIFrame *frame) -{ - MetaFrameFlags flags; - MetaFrameType type; - MetaFrameStyle *style; - gboolean frame_exists; - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_WINDOW_HAS_FRAME, &frame_exists, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_FRAME_TYPE, &type, - META_CORE_GET_END); - - if (frame_exists) - { - style = meta_theme_get_frame_style (meta_theme_get_current (), - type, flags); - } - - if (frame_exists && style->window_background_color != NULL) - { - GdkColor color; - GdkVisual *visual; - - meta_color_spec_render (style->window_background_color, - GTK_WIDGET (frames), - &color); - - /* Fill in color.pixel */ - - gdk_rgb_find_color (gtk_widget_get_colormap (GTK_WIDGET (frames)), - &color); - - /* Set A in ARGB to window_background_alpha, if we have ARGB */ - - visual = gtk_widget_get_visual (GTK_WIDGET (frames)); - if (visual->depth == 32) /* we have ARGB */ - { - color.pixel = (color.pixel & 0xffffff) & - style->window_background_alpha << 24; - } - - gdk_window_set_background (frame->window, &color); - } - else - { - gtk_style_set_background (GTK_WIDGET (frames)->style, - frame->window, GTK_STATE_NORMAL); - } - } - -static gboolean -meta_frames_enter_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - MetaUIFrame *frame; - MetaFrames *frames; - MetaFrameControl control; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - control = get_control (frames, frame, event->x, event->y); - meta_frames_update_prelit_control (frames, frame, control); - - return TRUE; -} - -static gboolean -meta_frames_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - MetaUIFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (widget); - - frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); - if (frame == NULL) - return FALSE; - - meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE); - - clear_tip (frames); - - return TRUE; -} - -static GdkRectangle* -control_rect (MetaFrameControl control, - MetaFrameGeometry *fgeom) -{ - GdkRectangle *rect; - - rect = NULL; - switch (control) - { - case META_FRAME_CONTROL_TITLE: - rect = &fgeom->title_rect; - break; - case META_FRAME_CONTROL_DELETE: - rect = &fgeom->close_rect.visible; - break; - case META_FRAME_CONTROL_MENU: - rect = &fgeom->menu_rect.visible; - break; - case META_FRAME_CONTROL_MINIMIZE: - rect = &fgeom->min_rect.visible; - break; - case META_FRAME_CONTROL_MAXIMIZE: - case META_FRAME_CONTROL_UNMAXIMIZE: - rect = &fgeom->max_rect.visible; - break; - case META_FRAME_CONTROL_SHADE: - rect = &fgeom->shade_rect.visible; - break; - case META_FRAME_CONTROL_UNSHADE: - rect = &fgeom->unshade_rect.visible; - break; - case META_FRAME_CONTROL_ABOVE: - rect = &fgeom->above_rect.visible; - break; - case META_FRAME_CONTROL_UNABOVE: - rect = &fgeom->unabove_rect.visible; - break; - case META_FRAME_CONTROL_STICK: - rect = &fgeom->stick_rect.visible; - break; - case META_FRAME_CONTROL_UNSTICK: - rect = &fgeom->unstick_rect.visible; - break; - case META_FRAME_CONTROL_RESIZE_SE: - break; - case META_FRAME_CONTROL_RESIZE_S: - break; - case META_FRAME_CONTROL_RESIZE_SW: - break; - case META_FRAME_CONTROL_RESIZE_N: - break; - case META_FRAME_CONTROL_RESIZE_NE: - break; - case META_FRAME_CONTROL_RESIZE_NW: - break; - case META_FRAME_CONTROL_RESIZE_W: - break; - case META_FRAME_CONTROL_RESIZE_E: - break; - case META_FRAME_CONTROL_NONE: - break; - case META_FRAME_CONTROL_CLIENT_AREA: - break; - } - - return rect; -} - -#define RESIZE_EXTENDS 15 -#define TOP_RESIZE_HEIGHT 2 -static MetaFrameControl -get_control (MetaFrames *frames, - MetaUIFrame *frame, - int x, int y) -{ - MetaFrameGeometry fgeom; - MetaFrameFlags flags; - gboolean has_vert, has_horiz; - GdkRectangle client; - - meta_frames_calc_geometry (frames, frame, &fgeom); - - client.x = fgeom.left_width; - client.y = fgeom.top_height; - client.width = fgeom.width - fgeom.left_width - fgeom.right_width; - client.height = fgeom.height - fgeom.top_height - fgeom.bottom_height; - - if (POINT_IN_RECT (x, y, client)) - return META_FRAME_CONTROL_CLIENT_AREA; - - if (POINT_IN_RECT (x, y, fgeom.close_rect.clickable)) - return META_FRAME_CONTROL_DELETE; - - if (POINT_IN_RECT (x, y, fgeom.min_rect.clickable)) - return META_FRAME_CONTROL_MINIMIZE; - - if (POINT_IN_RECT (x, y, fgeom.menu_rect.clickable)) - return META_FRAME_CONTROL_MENU; - - meta_core_get (gdk_display, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_END); - - has_vert = (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) != 0; - has_horiz = (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) != 0; - - if (POINT_IN_RECT (x, y, fgeom.title_rect)) - { - if (has_vert && y <= TOP_RESIZE_HEIGHT) - return META_FRAME_CONTROL_RESIZE_N; - else - return META_FRAME_CONTROL_TITLE; - } - - if (POINT_IN_RECT (x, y, fgeom.max_rect.clickable)) - { - if (flags & META_FRAME_MAXIMIZED) - return META_FRAME_CONTROL_UNMAXIMIZE; - else - return META_FRAME_CONTROL_MAXIMIZE; - } - - if (POINT_IN_RECT (x, y, fgeom.shade_rect.clickable)) - { - return META_FRAME_CONTROL_SHADE; - } - - if (POINT_IN_RECT (x, y, fgeom.unshade_rect.clickable)) - { - return META_FRAME_CONTROL_UNSHADE; - } - - if (POINT_IN_RECT (x, y, fgeom.above_rect.clickable)) - { - return META_FRAME_CONTROL_ABOVE; - } - - if (POINT_IN_RECT (x, y, fgeom.unabove_rect.clickable)) - { - return META_FRAME_CONTROL_UNABOVE; - } - - if (POINT_IN_RECT (x, y, fgeom.stick_rect.clickable)) - { - return META_FRAME_CONTROL_STICK; - } - - if (POINT_IN_RECT (x, y, fgeom.unstick_rect.clickable)) - { - return META_FRAME_CONTROL_UNSTICK; - } - - /* South resize always has priority over north resize, - * in case of overlap. - */ - - if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS) && - x >= (fgeom.width - fgeom.right_width - RESIZE_EXTENDS)) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_SE; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_E; - } - else if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS) && - x <= (fgeom.left_width + RESIZE_EXTENDS)) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_SW; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (y < (fgeom.top_height + RESIZE_EXTENDS) && - x < RESIZE_EXTENDS) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_NW; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_N; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (y < (fgeom.top_height + RESIZE_EXTENDS) && - x >= (fgeom.width - RESIZE_EXTENDS)) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_NE; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_N; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_E; - } - else if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS)) - { - if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - } - else if (y <= TOP_RESIZE_HEIGHT) - { - if (has_vert) - return META_FRAME_CONTROL_RESIZE_N; - else if (has_horiz) - return META_FRAME_CONTROL_TITLE; - } - else if (x <= fgeom.left_width) - { - if (has_horiz) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (x >= (fgeom.width - fgeom.right_width)) - { - if (has_horiz) - return META_FRAME_CONTROL_RESIZE_E; - } - - if (y >= fgeom.top_height) - return META_FRAME_CONTROL_NONE; - else - return META_FRAME_CONTROL_TITLE; -} - -void -meta_frames_push_delay_exposes (MetaFrames *frames) -{ - if (frames->expose_delay_count == 0) - { - /* Make sure we've repainted things */ - gdk_window_process_all_updates (); - XFlush (gdk_display); - } - - frames->expose_delay_count += 1; -} - -static void -queue_pending_exposes_func (gpointer key, gpointer value, gpointer data) -{ - MetaUIFrame *frame; - MetaFrames *frames; - - frames = META_FRAMES (data); - frame = value; - - if (frame->expose_delayed) - { - invalidate_whole_window (frames, frame); - frame->expose_delayed = FALSE; - } -} - -void -meta_frames_pop_delay_exposes (MetaFrames *frames) -{ - g_return_if_fail (frames->expose_delay_count > 0); - - frames->expose_delay_count -= 1; - - if (frames->expose_delay_count == 0) - { - g_hash_table_foreach (frames->frames, - queue_pending_exposes_func, - frames); - } -} - -static void -invalidate_whole_window (MetaFrames *frames, - MetaUIFrame *frame) -{ - gdk_window_invalidate_rect (frame->window, NULL, FALSE); - invalidate_cache (frames, frame); -} diff --git a/src/ui/frames.h b/src/ui/frames.h deleted file mode 100644 index c4ad8bfb..00000000 --- a/src/ui/frames.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window frame manager widget */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_FRAMES_H -#define META_FRAMES_H - -#include <gtk/gtk.h> -#include <gdk/gdkx.h> -#include "common.h" -#include "theme.h" - -typedef enum -{ - META_FRAME_CONTROL_NONE, - META_FRAME_CONTROL_TITLE, - META_FRAME_CONTROL_DELETE, - META_FRAME_CONTROL_MENU, - META_FRAME_CONTROL_MINIMIZE, - META_FRAME_CONTROL_MAXIMIZE, - META_FRAME_CONTROL_UNMAXIMIZE, - META_FRAME_CONTROL_SHADE, - META_FRAME_CONTROL_UNSHADE, - META_FRAME_CONTROL_ABOVE, - META_FRAME_CONTROL_UNABOVE, - META_FRAME_CONTROL_STICK, - META_FRAME_CONTROL_UNSTICK, - META_FRAME_CONTROL_RESIZE_SE, - META_FRAME_CONTROL_RESIZE_S, - META_FRAME_CONTROL_RESIZE_SW, - META_FRAME_CONTROL_RESIZE_N, - META_FRAME_CONTROL_RESIZE_NE, - META_FRAME_CONTROL_RESIZE_NW, - META_FRAME_CONTROL_RESIZE_W, - META_FRAME_CONTROL_RESIZE_E, - META_FRAME_CONTROL_CLIENT_AREA -} MetaFrameControl; - -/* This is one widget that manages all the window frames - * as subwindows. - */ - -#define META_TYPE_FRAMES (meta_frames_get_type ()) -#define META_FRAMES(obj) (GTK_CHECK_CAST ((obj), META_TYPE_FRAMES, MetaFrames)) -#define META_FRAMES_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), META_TYPE_FRAMES, MetaFramesClass)) -#define META_IS_FRAMES(obj) (GTK_CHECK_TYPE ((obj), META_TYPE_FRAMES)) -#define META_IS_FRAMES_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), META_TYPE_FRAMES)) -#define META_FRAMES_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), META_TYPE_FRAMES, MetaFramesClass)) - -typedef struct _MetaFrames MetaFrames; -typedef struct _MetaFramesClass MetaFramesClass; - -typedef struct _MetaUIFrame MetaUIFrame; - -struct _MetaUIFrame -{ - Window xwindow; - GdkWindow *window; - MetaFrameStyle *cache_style; - PangoLayout *layout; - int text_height; - char *title; /* NULL once we have a layout */ - guint expose_delayed : 1; - guint shape_applied : 1; - - /* FIXME get rid of this, it can just be in the MetaFrames struct */ - MetaFrameControl prelit_control; -}; - -struct _MetaFrames -{ - GtkWindow parent_instance; - - GHashTable *text_heights; - - GHashTable *frames; - - guint tooltip_timeout; - MetaUIFrame *last_motion_frame; - - int expose_delay_count; - - int invalidate_cache_timeout_id; - GList *invalidate_frames; - GHashTable *cache; -}; - -struct _MetaFramesClass -{ - GtkWindowClass parent_class; - -}; - -GType meta_frames_get_type (void) G_GNUC_CONST; - -MetaFrames *meta_frames_new (int screen_number); - -void meta_frames_manage_window (MetaFrames *frames, - Window xwindow, - GdkWindow *window); -void meta_frames_unmanage_window (MetaFrames *frames, - Window xwindow); -void meta_frames_set_title (MetaFrames *frames, - Window xwindow, - const char *title); - -void meta_frames_repaint_frame (MetaFrames *frames, - Window xwindow); - -void meta_frames_get_geometry (MetaFrames *frames, - Window xwindow, - int *top_height, int *bottom_height, - int *left_width, int *right_width); - -void meta_frames_reset_bg (MetaFrames *frames, - Window xwindow); -void meta_frames_unflicker_bg (MetaFrames *frames, - Window xwindow, - int target_width, - int target_height); - -void meta_frames_apply_shapes (MetaFrames *frames, - Window xwindow, - int new_window_width, - int new_window_height, - gboolean window_has_shape); -void meta_frames_move_resize_frame (MetaFrames *frames, - Window xwindow, - int x, - int y, - int width, - int height); -void meta_frames_queue_draw (MetaFrames *frames, - Window xwindow); - -void meta_frames_notify_menu_hide (MetaFrames *frames); - -Window meta_frames_get_moving_frame (MetaFrames *frames); - -void meta_frames_push_delay_exposes (MetaFrames *frames); -void meta_frames_pop_delay_exposes (MetaFrames *frames); - -#endif diff --git a/src/ui/gradient.c b/src/ui/gradient.c deleted file mode 100644 index 67906231..00000000 --- a/src/ui/gradient.c +++ /dev/null @@ -1,842 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity gradient rendering */ - -/* - * Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in - * WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. */ - -#include "gradient.h" -#include "util.h" -#include <string.h> - -/* This is all Alfredo's and Dan's usual very nice WindowMaker code, - * slightly GTK-ized - */ -static GdkPixbuf* meta_gradient_create_horizontal (int width, - int height, - const GdkColor *from, - const GdkColor *to); -static GdkPixbuf* meta_gradient_create_vertical (int width, - int height, - const GdkColor *from, - const GdkColor *to); -static GdkPixbuf* meta_gradient_create_diagonal (int width, - int height, - const GdkColor *from, - const GdkColor *to); -static GdkPixbuf* meta_gradient_create_multi_horizontal (int width, - int height, - const GdkColor *colors, - int count); -static GdkPixbuf* meta_gradient_create_multi_vertical (int width, - int height, - const GdkColor *colors, - int count); -static GdkPixbuf* meta_gradient_create_multi_diagonal (int width, - int height, - const GdkColor *colors, - int count); - - -/* Used as the destroy notification function for gdk_pixbuf_new() */ -static void -free_buffer (guchar *pixels, gpointer data) -{ - g_free (pixels); -} - -static GdkPixbuf* -blank_pixbuf (int width, int height, gboolean no_padding) -{ - guchar *buf; - int rowstride; - - g_return_val_if_fail (width > 0, NULL); - g_return_val_if_fail (height > 0, NULL); - - if (no_padding) - rowstride = width * 3; - else - /* Always align rows to 32-bit boundaries */ - rowstride = 4 * ((3 * width + 3) / 4); - - buf = g_try_malloc (height * rowstride); - if (!buf) - return NULL; - - return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, - FALSE, 8, - width, height, rowstride, - free_buffer, NULL); -} - -GdkPixbuf* -meta_gradient_create_simple (int width, - int height, - const GdkColor *from, - const GdkColor *to, - MetaGradientType style) -{ - switch (style) - { - case META_GRADIENT_HORIZONTAL: - return meta_gradient_create_horizontal (width, height, - from, to); - case META_GRADIENT_VERTICAL: - return meta_gradient_create_vertical (width, height, - from, to); - - case META_GRADIENT_DIAGONAL: - return meta_gradient_create_diagonal (width, height, - from, to); - case META_GRADIENT_LAST: - break; - } - g_assert_not_reached (); - return NULL; -} - -GdkPixbuf* -meta_gradient_create_multi (int width, - int height, - const GdkColor *colors, - int n_colors, - MetaGradientType style) -{ - - if (n_colors > 2) - { - switch (style) - { - case META_GRADIENT_HORIZONTAL: - return meta_gradient_create_multi_horizontal (width, height, colors, n_colors); - case META_GRADIENT_VERTICAL: - return meta_gradient_create_multi_vertical (width, height, colors, n_colors); - case META_GRADIENT_DIAGONAL: - return meta_gradient_create_multi_diagonal (width, height, colors, n_colors); - case META_GRADIENT_LAST: - g_assert_not_reached (); - break; - } - } - else if (n_colors > 1) - { - return meta_gradient_create_simple (width, height, &colors[0], &colors[1], - style); - } - else if (n_colors > 0) - { - return meta_gradient_create_simple (width, height, &colors[0], &colors[0], - style); - } - g_assert_not_reached (); - return NULL; -} - -/* Interwoven essentially means we have two vertical gradients, - * cut into horizontal strips of the given thickness, and then the strips - * are alternated. I'm not sure what it's good for, just copied since - * WindowMaker had it. - */ -GdkPixbuf* -meta_gradient_create_interwoven (int width, - int height, - const GdkColor colors1[2], - int thickness1, - const GdkColor colors2[2], - int thickness2) -{ - - int i, j, k, l, ll; - long r1, g1, b1, dr1, dg1, db1; - long r2, g2, b2, dr2, dg2, db2; - GdkPixbuf *pixbuf; - unsigned char *ptr; - unsigned char *pixels; - int rowstride; - - pixbuf = blank_pixbuf (width, height, FALSE); - if (pixbuf == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - r1 = colors1[0].red<<8; - g1 = colors1[0].green<<8; - b1 = colors1[0].blue<<8; - - r2 = colors2[0].red<<8; - g2 = colors2[0].green<<8; - b2 = colors2[0].blue<<8; - - dr1 = ((colors1[1].red-colors1[0].red)<<8)/(int)height; - dg1 = ((colors1[1].green-colors1[0].green)<<8)/(int)height; - db1 = ((colors1[1].blue-colors1[0].blue)<<8)/(int)height; - - dr2 = ((colors2[1].red-colors2[0].red)<<8)/(int)height; - dg2 = ((colors2[1].green-colors2[0].green)<<8)/(int)height; - db2 = ((colors2[1].blue-colors2[0].blue)<<8)/(int)height; - - for (i=0,k=0,l=0,ll=thickness1; i<height; i++) - { - ptr = pixels + i * rowstride; - - if (k == 0) - { - ptr[0] = (unsigned char) (r1>>16); - ptr[1] = (unsigned char) (g1>>16); - ptr[2] = (unsigned char) (b1>>16); - } - else - { - ptr[0] = (unsigned char) (r2>>16); - ptr[1] = (unsigned char) (g2>>16); - ptr[2] = (unsigned char) (b2>>16); - } - - for (j=1; j <= width/2; j *= 2) - memcpy (&(ptr[j*3]), ptr, j*3); - memcpy (&(ptr[j*3]), ptr, (width - j)*3); - - if (++l == ll) - { - if (k == 0) - { - k = 1; - ll = thickness2; - } - else - { - k = 0; - ll = thickness1; - } - l = 0; - } - r1+=dr1; - g1+=dg1; - b1+=db1; - - r2+=dr2; - g2+=dg2; - b2+=db2; - } - - return pixbuf; -} - -/* - *---------------------------------------------------------------------- - * meta_gradient_create_horizontal-- - * Renders a horizontal linear gradient of the specified size in the - * GdkPixbuf format with a border of the specified type. - * - * Returns: - * A 24bit GdkPixbuf with the gradient (no alpha channel). - * - * Side effects: - * None - *---------------------------------------------------------------------- - */ -static GdkPixbuf* -meta_gradient_create_horizontal (int width, int height, - const GdkColor *from, - const GdkColor *to) -{ - int i; - long r, g, b, dr, dg, db; - GdkPixbuf *pixbuf; - unsigned char *ptr; - unsigned char *pixels; - int r0, g0, b0; - int rf, gf, bf; - int rowstride; - - pixbuf = blank_pixbuf (width, height, FALSE); - if (pixbuf == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - ptr = pixels; - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - r0 = (guchar) (from->red / 256.0); - g0 = (guchar) (from->green / 256.0); - b0 = (guchar) (from->blue / 256.0); - rf = (guchar) (to->red / 256.0); - gf = (guchar) (to->green / 256.0); - bf = (guchar) (to->blue / 256.0); - - r = r0 << 16; - g = g0 << 16; - b = b0 << 16; - - dr = ((rf-r0)<<16)/(int)width; - dg = ((gf-g0)<<16)/(int)width; - db = ((bf-b0)<<16)/(int)width; - /* render the first line */ - for (i=0; i<width; i++) - { - *(ptr++) = (unsigned char)(r>>16); - *(ptr++) = (unsigned char)(g>>16); - *(ptr++) = (unsigned char)(b>>16); - r += dr; - g += dg; - b += db; - } - - /* copy the first line to the other lines */ - for (i=1; i<height; i++) - { - memcpy (&(pixels[i*rowstride]), pixels, rowstride); - } - return pixbuf; -} - -/* - *---------------------------------------------------------------------- - * meta_gradient_create_vertical-- - * Renders a vertical linear gradient of the specified size in the - * GdkPixbuf format with a border of the specified type. - * - * Returns: - * A 24bit GdkPixbuf with the gradient (no alpha channel). - * - * Side effects: - * None - *---------------------------------------------------------------------- - */ -static GdkPixbuf* -meta_gradient_create_vertical (int width, int height, - const GdkColor *from, - const GdkColor *to) -{ - int i, j; - long r, g, b, dr, dg, db; - GdkPixbuf *pixbuf; - unsigned char *ptr; - int r0, g0, b0; - int rf, gf, bf; - int rowstride; - unsigned char *pixels; - - pixbuf = blank_pixbuf (width, height, FALSE); - if (pixbuf == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - r0 = (guchar) (from->red / 256.0); - g0 = (guchar) (from->green / 256.0); - b0 = (guchar) (from->blue / 256.0); - rf = (guchar) (to->red / 256.0); - gf = (guchar) (to->green / 256.0); - bf = (guchar) (to->blue / 256.0); - - r = r0<<16; - g = g0<<16; - b = b0<<16; - - dr = ((rf-r0)<<16)/(int)height; - dg = ((gf-g0)<<16)/(int)height; - db = ((bf-b0)<<16)/(int)height; - - for (i=0; i<height; i++) - { - ptr = pixels + i * rowstride; - - ptr[0] = (unsigned char)(r>>16); - ptr[1] = (unsigned char)(g>>16); - ptr[2] = (unsigned char)(b>>16); - - for (j=1; j <= width/2; j *= 2) - memcpy (&(ptr[j*3]), ptr, j*3); - memcpy (&(ptr[j*3]), ptr, (width - j)*3); - - r+=dr; - g+=dg; - b+=db; - } - return pixbuf; -} - - -/* - *---------------------------------------------------------------------- - * meta_gradient_create_diagonal-- - * Renders a diagonal linear gradient of the specified size in the - * GdkPixbuf format with a border of the specified type. - * - * Returns: - * A 24bit GdkPixbuf with the gradient (no alpha channel). - * - * Side effects: - * None - *---------------------------------------------------------------------- - */ - - -static GdkPixbuf* -meta_gradient_create_diagonal (int width, int height, - const GdkColor *from, - const GdkColor *to) -{ - GdkPixbuf *pixbuf, *tmp; - int j; - float a, offset; - unsigned char *ptr; - unsigned char *pixels; - int rowstride; - - if (width == 1) - return meta_gradient_create_vertical (width, height, from, to); - else if (height == 1) - return meta_gradient_create_horizontal (width, height, from, to); - - pixbuf = blank_pixbuf (width, height, FALSE); - if (pixbuf == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - tmp = meta_gradient_create_horizontal (2*width-1, 1, from, to); - if (!tmp) - { - g_object_unref (G_OBJECT (pixbuf)); - return NULL; - } - - ptr = gdk_pixbuf_get_pixels (tmp); - - a = ((float)(width - 1))/((float)(height - 1)); - width = width * 3; - - /* copy the first line to the other lines with corresponding offset */ - for (j=0, offset=0.0; j<rowstride*height; j += rowstride) - { - memcpy (&(pixels[j]), &ptr[3*(int)offset], width); - offset += a; - } - - g_object_unref (G_OBJECT (tmp)); - return pixbuf; -} - - -static GdkPixbuf* -meta_gradient_create_multi_horizontal (int width, int height, - const GdkColor *colors, - int count) -{ - int i, j, k; - long r, g, b, dr, dg, db; - GdkPixbuf *pixbuf; - unsigned char *ptr; - unsigned char *pixels; - int width2; - int rowstride; - - g_return_val_if_fail (count > 2, NULL); - - pixbuf = blank_pixbuf (width, height, FALSE); - if (pixbuf == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - ptr = pixels; - - if (count > width) - count = width; - - if (count > 1) - width2 = width/(count-1); - else - width2 = width; - - k = 0; - - r = colors[0].red << 8; - g = colors[0].green << 8; - b = colors[0].blue << 8; - - /* render the first line */ - for (i=1; i<count; i++) - { - dr = ((int)(colors[i].red - colors[i-1].red) <<8)/(int)width2; - dg = ((int)(colors[i].green - colors[i-1].green)<<8)/(int)width2; - db = ((int)(colors[i].blue - colors[i-1].blue) <<8)/(int)width2; - for (j=0; j<width2; j++) - { - *ptr++ = (unsigned char)(r>>16); - *ptr++ = (unsigned char)(g>>16); - *ptr++ = (unsigned char)(b>>16); - r += dr; - g += dg; - b += db; - k++; - } - r = colors[i].red << 8; - g = colors[i].green << 8; - b = colors[i].blue << 8; - } - for (j=k; j<width; j++) - { - *ptr++ = (unsigned char)(r>>16); - *ptr++ = (unsigned char)(g>>16); - *ptr++ = (unsigned char)(b>>16); - } - - /* copy the first line to the other lines */ - for (i=1; i<height; i++) - { - memcpy (&(pixels[i*rowstride]), pixels, rowstride); - } - return pixbuf; -} - -static GdkPixbuf* -meta_gradient_create_multi_vertical (int width, int height, - const GdkColor *colors, - int count) -{ - int i, j, k; - long r, g, b, dr, dg, db; - GdkPixbuf *pixbuf; - unsigned char *ptr, *tmp, *pixels; - int height2; - int x; - int rowstride; - - g_return_val_if_fail (count > 2, NULL); - - pixbuf = blank_pixbuf (width, height, FALSE); - if (pixbuf == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - ptr = pixels; - - if (count > height) - count = height; - - if (count > 1) - height2 = height/(count-1); - else - height2 = height; - - k = 0; - - r = colors[0].red << 8; - g = colors[0].green << 8; - b = colors[0].blue << 8; - - for (i=1; i<count; i++) - { - dr = ((int)(colors[i].red - colors[i-1].red) <<8)/(int)height2; - dg = ((int)(colors[i].green - colors[i-1].green)<<8)/(int)height2; - db = ((int)(colors[i].blue - colors[i-1].blue) <<8)/(int)height2; - - for (j=0; j<height2; j++) - { - ptr[0] = (unsigned char)(r>>16); - ptr[1] = (unsigned char)(g>>16); - ptr[2] = (unsigned char)(b>>16); - - for (x=1; x <= width/2; x *= 2) - memcpy (&(ptr[x*3]), ptr, x*3); - memcpy (&(ptr[x*3]), ptr, (width - x)*3); - - ptr += rowstride; - - r += dr; - g += dg; - b += db; - k++; - } - r = colors[i].red << 8; - g = colors[i].green << 8; - b = colors[i].blue << 8; - } - - if (k<height) - { - tmp = ptr; - - ptr[0] = (unsigned char) (r>>16); - ptr[1] = (unsigned char) (g>>16); - ptr[2] = (unsigned char) (b>>16); - - for (x=1; x <= width/2; x *= 2) - memcpy (&(ptr[x*3]), ptr, x*3); - memcpy (&(ptr[x*3]), ptr, (width - x)*3); - - ptr += rowstride; - - for (j=k+1; j<height; j++) - { - memcpy (ptr, tmp, rowstride); - ptr += rowstride; - } - } - - return pixbuf; -} - - -static GdkPixbuf* -meta_gradient_create_multi_diagonal (int width, int height, - const GdkColor *colors, - int count) -{ - GdkPixbuf *pixbuf, *tmp; - float a, offset; - int j; - unsigned char *ptr; - unsigned char *pixels; - int rowstride; - - g_return_val_if_fail (count > 2, NULL); - - if (width == 1) - return meta_gradient_create_multi_vertical (width, height, colors, count); - else if (height == 1) - return meta_gradient_create_multi_horizontal (width, height, colors, count); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, - width, height); - if (pixbuf == NULL) - return NULL; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - if (count > width) - count = width; - if (count > height) - count = height; - - if (count > 2) - tmp = meta_gradient_create_multi_horizontal (2*width-1, 1, colors, count); - else - /* wrlib multiplies these colors by 256 before passing them in, but - * I think it's a bug in wrlib, so changed here. I could be wrong - * though, if we notice two-color multi diagonals not working. - */ - tmp = meta_gradient_create_horizontal (2*width-1, 1, - &colors[0], &colors[1]); - - if (!tmp) - { - g_object_unref (G_OBJECT (pixbuf)); - return NULL; - } - ptr = gdk_pixbuf_get_pixels (tmp); - - a = ((float)(width - 1))/((float)(height - 1)); - width = width * 3; - - /* copy the first line to the other lines with corresponding offset */ - for (j=0, offset=0; j<rowstride*height; j += rowstride) - { - memcpy (&(pixels[j]), &ptr[3*(int)offset], width); - offset += a; - } - - g_object_unref (G_OBJECT (tmp)); - return pixbuf; -} - -static void -simple_multiply_alpha (GdkPixbuf *pixbuf, - guchar alpha) -{ - guchar *pixels; - int rowstride; - int height; - int row; - - g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); - - if (alpha == 255) - return; - - g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); - - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - - row = 0; - while (row < height) - { - guchar *p; - guchar *end; - - p = pixels + row * rowstride; - end = p + rowstride; - - while (p != end) - { - p += 3; /* skip RGB */ - - /* multiply the two alpha channels. not sure this is right. - * but some end cases are that if the pixbuf contains 255, - * then it should be modified to contain "alpha"; if the - * pixbuf contains 0, it should remain 0. - */ - /* ((*p / 255.0) * (alpha / 255.0)) * 255; */ - *p = (guchar) (((int) *p * (int) alpha) / (int) 255); - - ++p; /* skip A */ - } - - ++row; - } -} - -static void -meta_gradient_add_alpha_horizontal (GdkPixbuf *pixbuf, - const unsigned char *alphas, - int n_alphas) -{ - int i, j; - long a, da; - unsigned char *p; - unsigned char *pixels; - int width2; - int rowstride; - int width, height; - unsigned char *gradient; - unsigned char *gradient_p; - unsigned char *gradient_end; - - g_return_if_fail (n_alphas > 0); - - if (n_alphas == 1) - { - /* Optimize this */ - simple_multiply_alpha (pixbuf, alphas[0]); - return; - } - - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - - gradient = g_new (unsigned char, width); - gradient_end = gradient + width; - - if (n_alphas > width) - n_alphas = width; - - if (n_alphas > 1) - width2 = width / (n_alphas - 1); - else - width2 = width; - - a = alphas[0] << 8; - gradient_p = gradient; - - /* render the gradient into an array */ - for (i = 1; i < n_alphas; i++) - { - da = (((int)(alphas[i] - (int) alphas[i-1])) << 8) / (int) width2; - - for (j = 0; j < width2; j++) - { - *gradient_p++ = (a >> 8); - - a += da; - } - - a = alphas[i] << 8; - } - - /* get leftover pixels */ - while (gradient_p != gradient_end) - { - *gradient_p++ = a >> 8; - } - - /* Now for each line of the pixbuf, fill in with the gradient */ - pixels = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - p = pixels; - i = 0; - while (i < height) - { - unsigned char *row_end = p + rowstride; - gradient_p = gradient; - - p += 3; - while (gradient_p != gradient_end) - { - /* multiply the two alpha channels. not sure this is right. - * but some end cases are that if the pixbuf contains 255, - * then it should be modified to contain "alpha"; if the - * pixbuf contains 0, it should remain 0. - */ - /* ((*p / 255.0) * (alpha / 255.0)) * 255; */ - *p = (guchar) (((int) *p * (int) *gradient_p) / (int) 255); - - p += 4; - ++gradient_p; - } - - p = row_end; - ++i; - } - - g_free (gradient); -} - -void -meta_gradient_add_alpha (GdkPixbuf *pixbuf, - const guchar *alphas, - int n_alphas, - MetaGradientType type) -{ - g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); - g_return_if_fail (gdk_pixbuf_get_has_alpha (pixbuf)); - g_return_if_fail (n_alphas > 0); - - switch (type) - { - case META_GRADIENT_HORIZONTAL: - meta_gradient_add_alpha_horizontal (pixbuf, alphas, n_alphas); - break; - - case META_GRADIENT_VERTICAL: - g_printerr ("metacity: vertical alpha channel gradient not implemented yet\n"); - break; - - case META_GRADIENT_DIAGONAL: - g_printerr ("metacity: diagonal alpha channel gradient not implemented yet\n"); - break; - - case META_GRADIENT_LAST: - g_assert_not_reached (); - break; - } -} diff --git a/src/ui/gradient.h b/src/ui/gradient.h deleted file mode 100644 index 16b3985d..00000000 --- a/src/ui/gradient.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity gradient rendering */ - -/* - * Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in - * WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. */ - -#ifndef META_GRADIENT_H -#define META_GRADIENT_H - -#include <gdk-pixbuf/gdk-pixbuf.h> -#include <gdk/gdk.h> - -typedef enum -{ - META_GRADIENT_VERTICAL, - META_GRADIENT_HORIZONTAL, - META_GRADIENT_DIAGONAL, - META_GRADIENT_LAST -} MetaGradientType; - -GdkPixbuf* meta_gradient_create_simple (int width, - int height, - const GdkColor *from, - const GdkColor *to, - MetaGradientType style); -GdkPixbuf* meta_gradient_create_multi (int width, - int height, - const GdkColor *colors, - int n_colors, - MetaGradientType style); -GdkPixbuf* meta_gradient_create_interwoven (int width, - int height, - const GdkColor colors1[2], - int thickness1, - const GdkColor colors2[2], - int thickness2); - - -/* Generate an alpha gradient and multiply it with the existing alpha - * channel of the given pixbuf - */ -void meta_gradient_add_alpha (GdkPixbuf *pixbuf, - const guchar *alphas, - int n_alphas, - MetaGradientType type); - - -#endif diff --git a/src/ui/menu.c b/src/ui/menu.c deleted file mode 100644 index 83198979..00000000 --- a/src/ui/menu.c +++ /dev/null @@ -1,532 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window menu */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2004 Rob Adams - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include <stdio.h> -#include <string.h> -#include "menu.h" -#include "main.h" -#include "util.h" -#include "core.h" -#include "themewidget.h" -#include "metaaccellabel.h" -#include "ui.h" - -typedef struct _MenuItem MenuItem; -typedef struct _MenuData MenuData; - -typedef enum -{ - MENU_ITEM_SEPARATOR = 0, - MENU_ITEM_NORMAL, - MENU_ITEM_IMAGE, - MENU_ITEM_CHECKBOX, - MENU_ITEM_RADIOBUTTON, - MENU_ITEM_WORKSPACE_LIST, -} MetaMenuItemType; - -struct _MenuItem -{ - MetaMenuOp op; - MetaMenuItemType type; - const char *stock_id; - const gboolean checked; - const char *label; -}; - - -struct _MenuData -{ - MetaWindowMenu *menu; - MetaMenuOp op; -}; - -static void activate_cb (GtkWidget *menuitem, gpointer data); - -static MenuItem menuitems[] = { - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_MINIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MINIMIZE, FALSE, N_("Mi_nimize") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_MAXIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MAXIMIZE, FALSE, N_("Ma_ximize") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Unma_ximize") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_SHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Roll _Up") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Unroll") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_MOVE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Move") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Resize") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move Titlebar On_screen") }, - { META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */ - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, NULL, FALSE, N_("Always on _Top") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, NULL, TRUE, N_("Always on _Top") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Always on Visible Workspace") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Only on This Workspace") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Left") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace R_ight") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Up") }, - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Down") }, - { 0, MENU_ITEM_WORKSPACE_LIST, NULL, FALSE, NULL }, - { 0, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */ - /* Translators: Translate this string the same way as you do in libwnck! */ - { META_MENU_OP_DELETE, MENU_ITEM_IMAGE, METACITY_STOCK_DELETE, FALSE, N_("_Close") } -}; - -static void -popup_position_func (GtkMenu *menu, - gint *x, - gint *y, - gboolean *push_in, - gpointer user_data) -{ - GtkRequisition req; - GdkPoint *pos; - - pos = user_data; - - gtk_widget_size_request (GTK_WIDGET (menu), &req); - - *x = pos->x; - *y = pos->y; - - if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - *x = MAX (0, *x - req.width); - - /* Ensure onscreen */ - *x = CLAMP (*x, 0, MAX (0, gdk_screen_width () - req.width)); - *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height)); -} - -static void -menu_closed (GtkMenu *widget, - gpointer data) -{ - MetaWindowMenu *menu; - - menu = data; - - meta_frames_notify_menu_hide (menu->frames); - (* menu->func) (menu, gdk_display, - menu->client_xwindow, - gtk_get_current_event_time (), - 0, 0, - menu->data); - - /* menu may now be freed */ -} - -static void -activate_cb (GtkWidget *menuitem, gpointer data) -{ - MenuData *md; - - g_return_if_fail (GTK_IS_WIDGET (menuitem)); - - md = data; - - meta_frames_notify_menu_hide (md->menu->frames); - (* md->menu->func) (md->menu, gdk_display, - md->menu->client_xwindow, - gtk_get_current_event_time (), - md->op, - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), - "workspace")), - md->menu->data); - - /* menu may now be freed */ -} - -/* - * Given a Display and an index, get the workspace name and add any - * accelerators. At the moment this means adding a _ if the name is of - * the form "Workspace n" where n is less than 10, and escaping any - * other '_'s so they do not create inadvertant accelerators. - * - * The calling code owns the string, and is reponsible to free the - * memory after use. - * - * See also http://mail.gnome.org/archives/gnome-i18n/2008-March/msg00380.html - * which discusses possible i18n concerns. - */ -static char* -get_workspace_name_with_accel (Display *display, - Window xroot, - int index) -{ - const char *name; - int number; - int charcount=0; - - name = meta_core_get_workspace_name_with_index (display, xroot, index); - - g_assert (name != NULL); - - /* - * If the name is of the form "Workspace x" where x is an unsigned - * integer, insert a '_' before the number if it is less than 10 and - * return it - */ - number = 0; - if (sscanf (name, _("Workspace %d%n"), &number, &charcount) != 0 && - *(name + charcount)=='\0') - { - char *new_name; - - /* - * Above name is a pointer into the Workspace struct. Here we make - * a copy copy so we can have our wicked way with it. - */ - if (number == 10) - new_name = g_strdup_printf (_("Workspace 1_0")); - else - new_name = g_strdup_printf (_("Workspace %s%d"), - number < 10 ? "_" : "", - number); - return new_name; - } - else - { - /* - * Otherwise this is just a normal name. Escape any _ characters so that - * the user's workspace names do not get mangled. If the number is less - * than 10 we provide an accelerator. - */ - char *new_name; - const char *source; - char *dest; - - /* - * Assume the worst case, that every character is a _. We also - * provide memory for " (_#)" - */ - new_name = g_malloc0 (strlen (name) * 2 + 6 + 1); - - /* - * Now iterate down the strings, adding '_' to escape as we go - */ - dest = new_name; - source = name; - while (*source != '\0') - { - if (*source == '_') - *dest++ = '_'; - *dest++ = *source++; - } - - /* People don't start at workspace 0, but workspace 1 */ - if (index < 9) - { - g_snprintf (dest, 6, " (_%d)", index + 1); - } - else if (index == 9) - { - g_snprintf (dest, 6, " (_0)"); - } - - return new_name; - } -} - -static GtkWidget * -menu_item_new (MenuItem *menuitem, int workspace_id) -{ - unsigned int key; - MetaVirtualModifier mods; - const char *i18n_label; - GtkWidget *mi; - GtkWidget *accel_label; - - if (menuitem->type == MENU_ITEM_NORMAL) - { - mi = gtk_menu_item_new (); - } - else if (menuitem->type == MENU_ITEM_IMAGE) - { - GtkWidget *image; - - image = gtk_image_new_from_stock (menuitem->stock_id, GTK_ICON_SIZE_MENU); - mi = gtk_image_menu_item_new (); - - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image); - gtk_widget_show (image); - } - else if (menuitem->type == MENU_ITEM_CHECKBOX) - { - mi = gtk_check_menu_item_new (); - - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), - menuitem->checked); - } - else if (menuitem->type == MENU_ITEM_RADIOBUTTON) - { - mi = gtk_check_menu_item_new (); - - gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (mi), - TRUE); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), - menuitem->checked); - } - else if (menuitem->type == MENU_ITEM_WORKSPACE_LIST) - return NULL; - else - return gtk_separator_menu_item_new (); - - i18n_label = _(menuitem->label); - meta_core_get_menu_accelerator (menuitem->op, workspace_id, &key, &mods); - - accel_label = meta_accel_label_new_with_mnemonic (i18n_label); - gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5); - - gtk_container_add (GTK_CONTAINER (mi), accel_label); - gtk_widget_show (accel_label); - - meta_accel_label_set_accelerator (META_ACCEL_LABEL (accel_label), - key, mods); - - return mi; -} - -MetaWindowMenu* -meta_window_menu_new (MetaFrames *frames, - MetaMenuOp ops, - MetaMenuOp insensitive, - Window client_xwindow, - unsigned long active_workspace, - int n_workspaces, - MetaWindowMenuFunc func, - gpointer data) -{ - int i; - MetaWindowMenu *menu; - - /* FIXME: Modifications to 'ops' should happen in meta_window_show_menu */ - if (n_workspaces < 2) - ops &= ~(META_MENU_OP_STICK | META_MENU_OP_UNSTICK | META_MENU_OP_WORKSPACES); - else if (n_workspaces == 2) - /* #151183: If we only have two workspaces, disable the menu listing them. */ - ops &= ~(META_MENU_OP_WORKSPACES); - - menu = g_new (MetaWindowMenu, 1); - menu->frames = frames; - menu->client_xwindow = client_xwindow; - menu->func = func; - menu->data = data; - menu->ops = ops; - menu->insensitive = insensitive; - - menu->menu = gtk_menu_new (); - - gtk_menu_set_screen (GTK_MENU (menu->menu), - gtk_widget_get_screen (GTK_WIDGET (frames))); - - for (i = 0; i < (int) G_N_ELEMENTS (menuitems); i++) - { - MenuItem menuitem = menuitems[i]; - if (ops & menuitem.op || menuitem.op == 0) - { - GtkWidget *mi; - MenuData *md; - unsigned int key; - MetaVirtualModifier mods; - - mi = menu_item_new (&menuitem, -1); - - /* Set the activeness of radiobuttons. */ - switch (menuitem.op) - { - case META_MENU_OP_STICK: - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), - active_workspace == 0xFFFFFFFF); - break; - case META_MENU_OP_UNSTICK: - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), - active_workspace != 0xFFFFFFFF); - break; - default: - break; - } - - if (menuitem.type == MENU_ITEM_WORKSPACE_LIST) - { - if (ops & META_MENU_OP_WORKSPACES) - { - Display *display; - Window xroot; - GdkScreen *screen; - GtkWidget *submenu; - int j; - - MenuItem to_another_workspace = { - 0, MENU_ITEM_NORMAL, - NULL, FALSE, - N_("Move to Another _Workspace") - }; - - meta_verbose ("Creating %d-workspace menu current space %lu\n", - n_workspaces, active_workspace); - - display = gdk_x11_drawable_get_xdisplay (GTK_WIDGET (frames)->window); - - screen = gdk_drawable_get_screen (GTK_WIDGET (frames)->window); - xroot = GDK_DRAWABLE_XID (gdk_screen_get_root_window (screen)); - - submenu = gtk_menu_new (); - - g_assert (mi==NULL); - mi = menu_item_new (&to_another_workspace, -1); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), submenu); - - for (j = 0; j < n_workspaces; j++) - { - char *label; - MenuData *md; - unsigned int key; - MetaVirtualModifier mods; - MenuItem moveitem; - GtkWidget *submi; - - meta_core_get_menu_accelerator (META_MENU_OP_WORKSPACES, - j + 1, - &key, &mods); - - label = get_workspace_name_with_accel (display, xroot, j); - - moveitem.type = MENU_ITEM_NORMAL; - moveitem.op = META_MENU_OP_WORKSPACES; - moveitem.label = label; - submi = menu_item_new (&moveitem, j + 1); - - g_free (label); - - if ((active_workspace == (unsigned)j) && (ops & META_MENU_OP_UNSTICK)) - gtk_widget_set_sensitive (submi, FALSE); - - md = g_new (MenuData, 1); - - md->menu = menu; - md->op = META_MENU_OP_WORKSPACES; - - g_object_set_data (G_OBJECT (submi), - "workspace", - GINT_TO_POINTER (j)); - - gtk_signal_connect_full (GTK_OBJECT (submi), - "activate", - GTK_SIGNAL_FUNC (activate_cb), - NULL, - md, - g_free, FALSE, FALSE); - - gtk_menu_shell_append (GTK_MENU_SHELL (submenu), submi); - - gtk_widget_show (submi); - } - } - else - meta_verbose ("not creating workspace menu\n"); - } - else if (menuitem.type != MENU_ITEM_SEPARATOR) - { - meta_core_get_menu_accelerator (menuitems[i].op, -1, - &key, &mods); - - if (insensitive & menuitem.op) - gtk_widget_set_sensitive (mi, FALSE); - - md = g_new (MenuData, 1); - - md->menu = menu; - md->op = menuitem.op; - - gtk_signal_connect_full (GTK_OBJECT (mi), - "activate", - GTK_SIGNAL_FUNC (activate_cb), - NULL, - md, - g_free, FALSE, FALSE); - } - - if (mi) - { - gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), mi); - - gtk_widget_show (mi); - } - } - } - - - g_signal_connect (menu->menu, "selection_done", - G_CALLBACK (menu_closed), menu); - - return menu; -} - -void -meta_window_menu_popup (MetaWindowMenu *menu, - int root_x, - int root_y, - int button, - guint32 timestamp) -{ - GdkPoint *pt; - - pt = g_new (GdkPoint, 1); - - g_object_set_data_full (G_OBJECT (menu->menu), - "destroy-point", - pt, - g_free); - - pt->x = root_x; - pt->y = root_y; - - gtk_menu_popup (GTK_MENU (menu->menu), - NULL, NULL, - popup_position_func, pt, - button, - timestamp); - - if (!GTK_MENU_SHELL (menu->menu)->have_xgrab) - meta_warning ("GtkMenu failed to grab the pointer\n"); -} - -void -meta_window_menu_free (MetaWindowMenu *menu) -{ - gtk_widget_destroy (menu->menu); - g_free (menu); -} diff --git a/src/ui/menu.h b/src/ui/menu.h deleted file mode 100644 index 39bb7fa3..00000000 --- a/src/ui/menu.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window menu */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_MENU_H -#define META_MENU_H - -#include <gtk/gtk.h> -#include "frames.h" - -/* Stock icons */ -#define METACITY_STOCK_DELETE "metacity-delete" -#define METACITY_STOCK_MINIMIZE "metacity-minimize" -#define METACITY_STOCK_MAXIMIZE "metacity-maximize" - -struct _MetaWindowMenu -{ - MetaFrames *frames; - Window client_xwindow; - GtkWidget *menu; - MetaWindowMenuFunc func; - gpointer data; - MetaMenuOp ops; - MetaMenuOp insensitive; -}; - -MetaWindowMenu* meta_window_menu_new (MetaFrames *frames, - MetaMenuOp ops, - MetaMenuOp insensitive, - Window client_xwindow, - unsigned long active_workspace, - int n_workspaces, - MetaWindowMenuFunc func, - gpointer data); -void meta_window_menu_popup (MetaWindowMenu *menu, - int root_x, - int root_y, - int button, - guint32 timestamp); -void meta_window_menu_free (MetaWindowMenu *menu); - - -#endif diff --git a/src/ui/metaaccellabel.c b/src/ui/metaaccellabel.c deleted file mode 100644 index d5233042..00000000 --- a/src/ui/metaaccellabel.c +++ /dev/null @@ -1,456 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity hacked-up GtkAccelLabel */ -/* Copyright (C) 2002 Red Hat, Inc. */ -/* GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * MetaAccelLabel: GtkLabel with accelerator monitoring facilities. - * Copyright (C) 1998 Tim Janik - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Modified by the GTK+ Team and others 1997-2001. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#include <config.h> -#include "metaaccellabel.h" -#include <gtk/gtk.h> -#include <string.h> -#include "util.h" - -static void meta_accel_label_class_init (MetaAccelLabelClass *klass); -static void meta_accel_label_init (MetaAccelLabel *accel_label); -static void meta_accel_label_destroy (GtkObject *object); -static void meta_accel_label_finalize (GObject *object); -static void meta_accel_label_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static gboolean meta_accel_label_expose_event (GtkWidget *widget, - GdkEventExpose *event); - -static void meta_accel_label_update (MetaAccelLabel *accel_label); -static int meta_accel_label_get_accel_width (MetaAccelLabel *accel_label); - - -static GtkLabelClass *parent_class = NULL; - - -GtkType -meta_accel_label_get_type (void) -{ - static GtkType accel_label_type = 0; - - if (!accel_label_type) - { - static const GtkTypeInfo accel_label_info = - { - "MetaAccelLabel", - sizeof (MetaAccelLabel), - sizeof (MetaAccelLabelClass), - (GtkClassInitFunc) meta_accel_label_class_init, - (GtkObjectInitFunc) meta_accel_label_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - accel_label_type = gtk_type_unique (GTK_TYPE_LABEL, &accel_label_info); - } - - return accel_label_type; -} - -static void -meta_accel_label_class_init (MetaAccelLabelClass *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - GtkObjectClass *object_class = GTK_OBJECT_CLASS (class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); - - parent_class = g_type_class_peek_parent (class); - - gobject_class->finalize = meta_accel_label_finalize; - - object_class->destroy = meta_accel_label_destroy; - - widget_class->size_request = meta_accel_label_size_request; - widget_class->expose_event = meta_accel_label_expose_event; - - class->signal_quote1 = g_strdup ("<:"); - class->signal_quote2 = g_strdup (":>"); - /* This is the text that should appear next to menu accelerators - * that use the shift key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_shift = g_strdup (_("Shift")); - /* This is the text that should appear next to menu accelerators - * that use the control key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_control = g_strdup (_("Ctrl")); - /* This is the text that should appear next to menu accelerators - * that use the alt key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_alt = g_strdup (_("Alt")); - /* This is the text that should appear next to menu accelerators - * that use the meta key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_meta = g_strdup (_("Meta")); - /* This is the text that should appear next to menu accelerators - * that use the super key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_super = g_strdup (_("Super")); - /* This is the text that should appear next to menu accelerators - * that use the hyper key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_hyper = g_strdup (_("Hyper")); - /* This is the text that should appear next to menu accelerators - * that use the mod2 key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_mod2 = g_strdup (_("Mod2")); - /* This is the text that should appear next to menu accelerators - * that use the mod3 key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_mod3 = g_strdup (_("Mod3")); - /* This is the text that should appear next to menu accelerators - * that use the mod4 key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_mod4 = g_strdup (_("Mod4")); - /* This is the text that should appear next to menu accelerators - * that use the mod5 key. If the text on this key isn't typically - * translated on keyboards used for your language, don't translate - * this. - */ - class->mod_name_mod5 = g_strdup (_("Mod5")); - - class->mod_separator = g_strdup ("+"); - class->accel_seperator = g_strdup (" / "); - class->latin1_to_char = TRUE; -} - -static void -meta_accel_label_init (MetaAccelLabel *accel_label) -{ - accel_label->accel_padding = 3; - accel_label->accel_string = NULL; - - meta_accel_label_update (accel_label); -} - -GtkWidget* -meta_accel_label_new_with_mnemonic (const gchar *string) -{ - MetaAccelLabel *accel_label; - - g_return_val_if_fail (string != NULL, NULL); - - accel_label = g_object_new (META_TYPE_ACCEL_LABEL, NULL); - - gtk_label_set_text_with_mnemonic (GTK_LABEL (accel_label), string); - - return GTK_WIDGET (accel_label); -} - -static void -meta_accel_label_destroy (GtkObject *object) -{ - MetaAccelLabel *accel_label = META_ACCEL_LABEL (object); - - - g_free (accel_label->accel_string); - accel_label->accel_string = NULL; - - accel_label->accel_mods = 0; - accel_label->accel_key = 0; - - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - -static void -meta_accel_label_finalize (GObject *object) -{ - MetaAccelLabel *accel_label = META_ACCEL_LABEL (object); - - g_free (accel_label->accel_string); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -void -meta_accel_label_set_accelerator (MetaAccelLabel *accel_label, - guint accelerator_key, - MetaVirtualModifier accelerator_mods) -{ - g_return_if_fail (META_IS_ACCEL_LABEL (accel_label)); - - if (accelerator_key != accel_label->accel_key || - accelerator_mods != accel_label->accel_mods) - { - accel_label->accel_mods = accelerator_mods; - accel_label->accel_key = accelerator_key; - - meta_accel_label_update (accel_label); - } -} - -static int -meta_accel_label_get_accel_width (MetaAccelLabel *accel_label) -{ - g_return_val_if_fail (META_IS_ACCEL_LABEL (accel_label), 0); - - return (accel_label->accel_string_width + - (accel_label->accel_string_width ? accel_label->accel_padding : 0)); -} - -static void -meta_accel_label_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - MetaAccelLabel *accel_label = META_ACCEL_LABEL (widget); - PangoLayout *layout; - gint width; - - if (GTK_WIDGET_CLASS (parent_class)->size_request) - GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition); - - layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string); - pango_layout_get_pixel_size (layout, &width, NULL); - accel_label->accel_string_width = width; - - g_object_unref (G_OBJECT (layout)); -} - -static gboolean -meta_accel_label_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - MetaAccelLabel *accel_label = META_ACCEL_LABEL (widget); - GtkMisc *misc = GTK_MISC (accel_label); - PangoLayout *layout; - - if (GTK_WIDGET_DRAWABLE (accel_label)) - { - int ac_width; - - ac_width = meta_accel_label_get_accel_width (accel_label); - - if (widget->allocation.width >= widget->requisition.width + ac_width) - { - GtkTextDirection direction = gtk_widget_get_direction (widget); - gint x; - gint y; - - if (direction == GTK_TEXT_DIR_RTL) - { - widget->allocation.x += ac_width; - } - widget->allocation.width -= ac_width; - - if (GTK_WIDGET_CLASS (parent_class)->expose_event) - GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); - - if (direction == GTK_TEXT_DIR_RTL) - { - widget->allocation.x -= ac_width; - } - widget->allocation.width += ac_width; - - if (direction == GTK_TEXT_DIR_RTL) - { - x = widget->allocation.x + misc->xpad; - } - else - { - x = widget->allocation.x + widget->allocation.width - misc->xpad - ac_width; - } - - y = (widget->allocation.y * (1.0 - misc->yalign) + - (widget->allocation.y + widget->allocation.height - - (widget->requisition.height - misc->ypad * 2)) * - misc->yalign) + 1.5; - - layout = gtk_widget_create_pango_layout (widget, accel_label->accel_string); - - gtk_paint_layout (widget->style, - widget->window, - GTK_WIDGET_STATE (widget), - FALSE, - &event->area, - widget, - "accellabel", - x, y, - layout); - - g_object_unref (G_OBJECT (layout)); - } - else - { - if (GTK_WIDGET_CLASS (parent_class)->expose_event) - GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); - } - } - - return FALSE; -} - -static void -meta_accel_label_update (MetaAccelLabel *accel_label) -{ - MetaAccelLabelClass *class; - GString *gstring; - gboolean seen_mod = FALSE; - gunichar ch; - - g_return_if_fail (META_IS_ACCEL_LABEL (accel_label)); - - class = META_ACCEL_LABEL_GET_CLASS (accel_label); - - g_free (accel_label->accel_string); - accel_label->accel_string = NULL; - - gstring = g_string_new (accel_label->accel_string); - g_string_append (gstring, gstring->len ? class->accel_seperator : " "); - - if (accel_label->accel_mods & META_VIRTUAL_SHIFT_MASK) - { - g_string_append (gstring, class->mod_name_shift); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_CONTROL_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_control); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_ALT_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_alt); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_META_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_meta); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_SUPER_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_super); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_HYPER_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_hyper); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_MOD2_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_mod2); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_MOD3_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_mod3); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_MOD4_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_mod4); - seen_mod = TRUE; - } - if (accel_label->accel_mods & META_VIRTUAL_MOD5_MASK) - { - if (seen_mod) - g_string_append (gstring, class->mod_separator); - g_string_append (gstring, class->mod_name_mod5); - seen_mod = TRUE; - } - - if (seen_mod) - g_string_append (gstring, class->mod_separator); - - ch = gdk_keyval_to_unicode (accel_label->accel_key); - if (ch && (g_unichar_isgraph (ch) || ch == ' ') && - (ch < 0x80 || class->latin1_to_char)) - { - switch (ch) - { - case ' ': - g_string_append (gstring, "Space"); - break; - case '\\': - g_string_append (gstring, "Backslash"); - break; - default: - g_string_append_unichar (gstring, g_unichar_toupper (ch)); - break; - } - } - else - { - gchar *tmp; - - tmp = gtk_accelerator_name (accel_label->accel_key, 0); - if (tmp[0] != 0 && tmp[1] == 0) - tmp[0] = g_ascii_toupper (tmp[0]); - g_string_append (gstring, tmp); - g_free (tmp); - } - - g_free (accel_label->accel_string); - accel_label->accel_string = gstring->str; - g_string_free (gstring, FALSE); - - g_assert (accel_label->accel_string); - /* accel_label->accel_string = g_strdup ("-/-"); */ - - gtk_widget_queue_resize (GTK_WIDGET (accel_label)); -} diff --git a/src/ui/metaaccellabel.h b/src/ui/metaaccellabel.h deleted file mode 100644 index 4fb8ed5d..00000000 --- a/src/ui/metaaccellabel.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity hacked-up GtkAccelLabel */ -/* Copyright (C) 2002 Red Hat, Inc. */ -/* GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * MetaAccelLabel: GtkLabel with accelerator monitoring facilities. - * Copyright (C) 1998 Tim Janik - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Modified by the GTK+ Team and others 1997-2001. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#ifndef __META_ACCEL_LABEL_H__ -#define __META_ACCEL_LABEL_H__ - -#include <gtk/gtk.h> -#include "common.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - -#define META_TYPE_ACCEL_LABEL (meta_accel_label_get_type ()) -#define META_ACCEL_LABEL(obj) (GTK_CHECK_CAST ((obj), META_TYPE_ACCEL_LABEL, MetaAccelLabel)) -#define META_ACCEL_LABEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), META_TYPE_ACCEL_LABEL, MetaAccelLabelClass)) -#define META_IS_ACCEL_LABEL(obj) (GTK_CHECK_TYPE ((obj), META_TYPE_ACCEL_LABEL)) -#define META_IS_ACCEL_LABEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), META_TYPE_ACCEL_LABEL)) -#define META_ACCEL_LABEL_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), META_TYPE_ACCEL_LABEL, MetaAccelLabelClass)) - - -typedef struct _MetaAccelLabel MetaAccelLabel; -typedef struct _MetaAccelLabelClass MetaAccelLabelClass; - -struct _MetaAccelLabel -{ - GtkLabel label; - - MetaVirtualModifier accel_mods; - guint accel_key; - guint accel_padding; - gchar *accel_string; - guint16 accel_string_width; -}; - -struct _MetaAccelLabelClass -{ - GtkLabelClass parent_class; - - gchar *signal_quote1; - gchar *signal_quote2; - gchar *mod_name_shift; - gchar *mod_name_control; - gchar *mod_name_alt; - gchar *mod_name_meta; - gchar *mod_name_super; - gchar *mod_name_hyper; - gchar *mod_name_mod2; - gchar *mod_name_mod3; - gchar *mod_name_mod4; - gchar *mod_name_mod5; - gchar *mod_separator; - gchar *accel_seperator; - guint latin1_to_char : 1; - - /* Padding for future expansion */ - void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); -}; - -GtkType meta_accel_label_get_type (void) G_GNUC_CONST; -GtkWidget* meta_accel_label_new_with_mnemonic (const gchar *string); -void meta_accel_label_set_accelerator (MetaAccelLabel *accel_label, - guint accelerator_key, - MetaVirtualModifier accelerator_mods); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* __META_ACCEL_LABEL_H__ */ diff --git a/src/ui/metacity-dialog.c b/src/ui/metacity-dialog.c deleted file mode 100644 index d47a9b3e..00000000 --- a/src/ui/metacity-dialog.c +++ /dev/null @@ -1,438 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity dialog process */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2004 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include <gtk/gtk.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <libintl.h> -#define _(x) dgettext (GETTEXT_PACKAGE, x) -#define N_(x) x - -#include <gdk/gdkx.h> -#include <X11/Xatom.h> - -static Window -window_from_string (const char *str) -{ - char *end; - unsigned long l; - - end = NULL; - - l = strtoul (str, &end, 16); - - if (end == NULL || end == str) - { - g_printerr (_("Could not parse \"%s\" as an integer"), - str); - return None; - } - - if (*end != '\0') - { - g_printerr (_("Did not understand trailing characters \"%s\" in string \"%s\""), - end, str); - return None; - } - - return l; -} - -static void -on_realize (GtkWidget *dialog, - void *data) -{ - const char *parent_str = data; - Window xwindow; - - xwindow = window_from_string (parent_str); - - gdk_error_trap_push (); - XSetTransientForHint (gdk_display, GDK_WINDOW_XID (dialog->window), - xwindow); - XSync (gdk_display, False); - gdk_error_trap_pop (); -} - -static int -kill_window_question (const char *window_name, - const char *parent_str, - guint32 timestamp) -{ - GtkWidget *dialog; - char *str, *tmp; - - tmp = g_markup_escape_text (window_name, -1); - str = g_strdup_printf (_("\"%s\" is not responding."), tmp); - g_free (tmp); - dialog = gtk_message_dialog_new (NULL, 0, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_NONE, - "<big><b>%s</b></big>\n\n<i>%s</i>", - str, - _("You may choose to wait a short while " - "for it to continue or force the application " - "to quit entirely.")); - g_free (str); - gtk_window_set_icon_name (GTK_WINDOW (dialog), "stock_dialog-warning"); - - gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE); - gtk_label_set_line_wrap (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE); - - gtk_dialog_add_buttons (GTK_DIALOG (dialog), - _("_Wait"), - GTK_RESPONSE_REJECT, - _("_Force Quit"), - GTK_RESPONSE_ACCEPT, - NULL); - - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT); - - g_signal_connect (G_OBJECT (dialog), "realize", - G_CALLBACK (on_realize), (char*) parent_str); - - gtk_widget_realize (dialog); - gdk_x11_window_set_user_time (dialog->window, timestamp); - - /* return our PID, then window ID that should be killed */ - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) - g_print ("%d\n%s\n", (int) getpid (), parent_str); - else - g_print ("%d\n0x0\n", (int) getpid ()); - - return 0; -} - -static char* -latin1_to_utf8 (const char *text) -{ - GString *str; - const char *p; - - str = g_string_new (""); - - p = text; - while (*p) - { - g_string_append_unichar (str, *p); - ++p; - } - - return g_string_free (str, FALSE); -} - -enum -{ - COLUMN_TITLE, - COLUMN_CLASS, - COLUMN_LAST -}; - -static GtkWidget* -create_lame_apps_list (char **lame_apps) -{ - GtkTreeSelection *selection; - GtkCellRenderer *cell; - GtkWidget *tree_view; - GtkTreeViewColumn *column; - GtkListStore *model; - GtkTreeIter iter; - int i; - - model = gtk_list_store_new (COLUMN_LAST, - G_TYPE_STRING, - G_TYPE_STRING); - - tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); - - g_object_unref (G_OBJECT (model)); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); - - gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection), - GTK_SELECTION_NONE); - - i = 0; - while (lame_apps[i]) - { - char *s; - - gtk_list_store_append (model, &iter); - - /* window class is latin-1 */ - s = latin1_to_utf8 (lame_apps[i+1]); - - gtk_list_store_set (model, - &iter, - COLUMN_TITLE, lame_apps[i], - COLUMN_CLASS, s, - -1); - - g_free (s); - - i += 2; - } - - cell = gtk_cell_renderer_text_new (); - - g_object_set (G_OBJECT (cell), - "xpad", 2, - NULL); - - column = gtk_tree_view_column_new_with_attributes (_("Title"), - cell, - "text", COLUMN_TITLE, - NULL); - - gtk_tree_view_column_set_sort_column_id (column, COLUMN_TITLE); - - gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), - GTK_TREE_VIEW_COLUMN (column)); - - cell = gtk_cell_renderer_text_new (); - - column = gtk_tree_view_column_new_with_attributes (_("Class"), - cell, - "text", COLUMN_CLASS, - NULL); - - gtk_tree_view_column_set_sort_column_id (column, COLUMN_CLASS); - - gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), - GTK_TREE_VIEW_COLUMN (column)); - - return tree_view; -} - -static int -warn_about_no_sm_support (char **lame_apps, - guint32 timestamp) -{ - GtkWidget *dialog; - GtkWidget *list; - GtkWidget *sw; - GtkWidget *button; - - dialog = gtk_message_dialog_new (NULL, - 0, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_NONE, - _("These windows do not support \"save current setup\" and will have to be restarted manually next time you log in.")); - gtk_window_set_icon_name (GTK_WINDOW (dialog), "stock_dialog-warning"); - - g_signal_connect (G_OBJECT (dialog), - "response", - G_CALLBACK (gtk_main_quit), - NULL); - - /* Wait 4 minutes then force quit, so we don't wait around all night */ - g_timeout_add (4 * 60 * 1000, (GSourceFunc) gtk_main_quit, NULL); - - button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); - list = create_lame_apps_list (lame_apps); - - sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_container_set_border_width (GTK_CONTAINER (sw), 3); - - gtk_container_add (GTK_CONTAINER (sw), list); - - /* sw as geometry widget */ - gtk_window_set_geometry_hints (GTK_WINDOW (dialog), - sw, NULL, 0); - - gtk_window_set_resizable (GTK_WINDOW(dialog), TRUE); - - /* applies to geometry widget; try to avoid scrollbars, - * but don't make the window huge - */ - gtk_window_set_default_size (GTK_WINDOW (dialog), - 400, 225); - - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - sw, - TRUE, TRUE, 0); - - gtk_window_stick (GTK_WINDOW (dialog)); - - gtk_widget_realize (dialog); - gdk_x11_window_set_user_time (dialog->window, timestamp); - - gtk_widget_grab_focus (button); - gtk_widget_show_all (dialog); - - gtk_main (); - - return 0; -} - -static int -error_about_command (const char *gconf_key, - const char *command, - const char *error, - guint32 timestamp) -{ - GtkWidget *dialog; - - /* FIXME offer to change the value of the command's gconf key */ - - if (*command != '\0') - dialog = gtk_message_dialog_new (NULL, 0, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - _("There was an error running \"%s\":\n" - "%s."), - command, error); - else - dialog = gtk_message_dialog_new (NULL, 0, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "%s", error); - gtk_window_set_icon_name (GTK_WINDOW (dialog), "stock_dialog-error"); - - gtk_widget_realize (dialog); - gdk_x11_window_set_user_time (dialog->window, timestamp); - - gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); - - return 0; -} - -static gchar *screen = NULL; -static gchar *timestamp_string = NULL; -static gboolean isset_kill_window_question = FALSE; -static gboolean isset_warn_about_no_sm_support = FALSE; -static gboolean isset_command_failed_error = FALSE; -static gchar **remaining_args; - -static const GOptionEntry options[] = { - { "screen", 0, 0, G_OPTION_ARG_STRING, &screen, NULL, NULL}, - { "timestamp", 0, 0, G_OPTION_ARG_STRING, ×tamp_string, NULL, NULL}, - { "kill-window-question", 'k', 0, G_OPTION_ARG_NONE, - &isset_kill_window_question, NULL, NULL}, - { "warn-about-no-sm-support", 'w', 0, G_OPTION_ARG_NONE, - &isset_warn_about_no_sm_support, NULL, NULL}, - { "command-failed-error", 'c', 0, G_OPTION_ARG_NONE, - &isset_command_failed_error, NULL, NULL}, - { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, - &remaining_args, NULL, NULL}, - { NULL} -}; - -int -main (int argc, char **argv) -{ - GOptionContext *ctx; - guint32 timestamp = 0; - gint num_args = 0; - - bindtextdomain (GETTEXT_PACKAGE, METACITY_LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - gtk_init (&argc, &argv); - - ctx = g_option_context_new ("- Dialogs for metacity. " - "This program is intented for use by metacity only."); - g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE); - g_option_context_parse (ctx, &argc, &argv, NULL); - g_option_context_free (ctx); - - if (timestamp_string != NULL) - { - timestamp = strtoul (timestamp_string, NULL, 10); - } - - if (remaining_args != NULL) - { - num_args = g_strv_length (remaining_args); - } - - if ((isset_kill_window_question && isset_warn_about_no_sm_support) || - (isset_kill_window_question && isset_command_failed_error) || - (isset_warn_about_no_sm_support && isset_command_failed_error) || - timestamp == 0) - { - g_printerr ("bad args to metacity-dialog\n"); - return 1; - } - - else if (isset_kill_window_question) - { - if (num_args < 2) - { - g_printerr ("bad args to metacity-dialog\n"); - return 1; - } - else - { - return kill_window_question (remaining_args[0], - remaining_args[1], timestamp); - } - } - - else if (isset_warn_about_no_sm_support) - { - /* argc must be even because we want title-class pairs */ - if (num_args == 0 || (num_args % 2) != 0) - { - g_printerr ("bad args to metacity-dialog\n"); - return 1; - } - else - { - return warn_about_no_sm_support (&remaining_args[0], timestamp); - } - } - - else if (isset_command_failed_error) - { - /* the args are the gconf key of the failed command, the text of - * the command, and the error message - */ - if (num_args != 3) - { - g_printerr ("bad args to metacity-dialog\n"); - return 1; - } - else - { - return error_about_command (remaining_args[0], - remaining_args[1], remaining_args[2], timestamp); - } - } - else - { - g_printerr ("bad args to metacity-dialog\n"); - return 1; - } -} diff --git a/src/ui/preview-widget.c b/src/ui/preview-widget.c deleted file mode 100644 index e098baac..00000000 --- a/src/ui/preview-widget.c +++ /dev/null @@ -1,593 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme preview widget */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#define _GNU_SOURCE -#define _XOPEN_SOURCE 600 /* for the maths routines over floats */ - -#include <math.h> -#include <gtk/gtk.h> -#include "preview-widget.h" - -static void meta_preview_class_init (MetaPreviewClass *klass); -static void meta_preview_init (MetaPreview *preview); -static void meta_preview_size_request (GtkWidget *widget, - GtkRequisition *req); -static void meta_preview_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gboolean meta_preview_expose (GtkWidget *widget, - GdkEventExpose *event); -static void meta_preview_finalize (GObject *object); - -static GtkWidgetClass *parent_class; - -GtkType -meta_preview_get_type (void) -{ - static GtkType preview_type = 0; - - if (!preview_type) - { - static const GtkTypeInfo preview_info = - { - "MetaPreview", - sizeof (MetaPreview), - sizeof (MetaPreviewClass), - (GtkClassInitFunc) meta_preview_class_init, - (GtkObjectInitFunc) meta_preview_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - preview_type = gtk_type_unique (GTK_TYPE_BIN, &preview_info); - } - - return preview_type; -} - -static void -meta_preview_class_init (MetaPreviewClass *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - GtkWidgetClass *widget_class; - - widget_class = (GtkWidgetClass*) class; - parent_class = gtk_type_class (GTK_TYPE_BIN); - - gobject_class->finalize = meta_preview_finalize; - - widget_class->expose_event = meta_preview_expose; - widget_class->size_request = meta_preview_size_request; - widget_class->size_allocate = meta_preview_size_allocate; -} - -static void -meta_preview_init (MetaPreview *preview) -{ - int i; - - GTK_WIDGET_SET_FLAGS (preview, GTK_NO_WINDOW); - - i = 0; - while (i < MAX_BUTTONS_PER_CORNER) - { - preview->button_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST; - preview->button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; - ++i; - } - - preview->button_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU; - - preview->button_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE; - preview->button_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE; - preview->button_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE; - - preview->type = META_FRAME_TYPE_NORMAL; - preview->flags = - META_FRAME_ALLOWS_DELETE | - META_FRAME_ALLOWS_MENU | - META_FRAME_ALLOWS_MINIMIZE | - META_FRAME_ALLOWS_MAXIMIZE | - META_FRAME_ALLOWS_VERTICAL_RESIZE | - META_FRAME_ALLOWS_HORIZONTAL_RESIZE | - META_FRAME_HAS_FOCUS | - META_FRAME_ALLOWS_SHADE | - META_FRAME_ALLOWS_MOVE; - - preview->left_width = -1; - preview->right_width = -1; - preview->top_height = -1; - preview->bottom_height = -1; -} - -GtkWidget* -meta_preview_new (void) -{ - MetaPreview *preview; - - preview = gtk_type_new (META_TYPE_PREVIEW); - - return GTK_WIDGET (preview); -} - -static void -meta_preview_finalize (GObject *object) -{ - MetaPreview *preview; - - preview = META_PREVIEW (object); - - g_free (preview->title); - preview->title = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -ensure_info (MetaPreview *preview) -{ - GtkWidget *widget; - - widget = GTK_WIDGET (preview); - - if (preview->layout == NULL) - { - PangoFontDescription *font_desc; - double scale; - PangoAttrList *attrs; - PangoAttribute *attr; - - if (preview->theme) - scale = meta_theme_get_title_scale (preview->theme, - preview->type, - preview->flags); - else - scale = 1.0; - - preview->layout = gtk_widget_create_pango_layout (widget, - preview->title); - - font_desc = meta_gtk_widget_get_font_desc (widget, scale, NULL); - - preview->text_height = - meta_pango_font_desc_get_text_height (font_desc, - gtk_widget_get_pango_context (widget)); - - attrs = pango_attr_list_new (); - - attr = pango_attr_size_new (pango_font_description_get_size (font_desc)); - attr->start_index = 0; - attr->end_index = G_MAXINT; - - pango_attr_list_insert (attrs, attr); - - pango_layout_set_attributes (preview->layout, attrs); - - pango_attr_list_unref (attrs); - - pango_font_description_free (font_desc); - } - - if (preview->top_height < 0) - { - if (preview->theme) - { - meta_theme_get_frame_borders (preview->theme, - preview->type, - preview->text_height, - preview->flags, - &preview->top_height, - &preview->bottom_height, - &preview->left_width, - &preview->right_width); - } - else - { - preview->top_height = 0; - preview->bottom_height = 0; - preview->left_width = 0; - preview->right_width = 0; - } - } -} - -static gboolean -meta_preview_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - MetaPreview *preview; - int border_width; - int client_width; - int client_height; - MetaButtonState button_states[META_BUTTON_TYPE_LAST] = - { - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL - }; - - g_return_val_if_fail (META_IS_PREVIEW (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - preview = META_PREVIEW (widget); - - ensure_info (preview); - - border_width = GTK_CONTAINER (widget)->border_width; - - client_width = widget->allocation.width - preview->left_width - preview->right_width - border_width * 2; - client_height = widget->allocation.height - preview->top_height - preview->bottom_height - border_width * 2; - - if (client_width < 0) - client_width = 1; - if (client_height < 0) - client_height = 1; - - if (preview->theme) - { - border_width = GTK_CONTAINER (widget)->border_width; - - meta_theme_draw_frame (preview->theme, - widget, - widget->window, - &event->area, - widget->allocation.x + border_width, - widget->allocation.y + border_width, - preview->type, - preview->flags, - client_width, client_height, - preview->layout, - preview->text_height, - &preview->button_layout, - button_states, - meta_preview_get_mini_icon (), - meta_preview_get_icon ()); - } - - /* draw child */ - return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); -} - -static void -meta_preview_size_request (GtkWidget *widget, - GtkRequisition *req) -{ - MetaPreview *preview; - - preview = META_PREVIEW (widget); - - ensure_info (preview); - - req->width = preview->left_width + preview->right_width; - req->height = preview->top_height + preview->bottom_height; - - if (GTK_BIN (preview)->child && - GTK_WIDGET_VISIBLE (GTK_BIN (preview)->child)) - { - GtkRequisition child_requisition; - - gtk_widget_size_request (GTK_BIN (preview)->child, &child_requisition); - - req->width += child_requisition.width; - req->height += child_requisition.height; - } - else - { -#define NO_CHILD_WIDTH 80 -#define NO_CHILD_HEIGHT 20 - req->width += NO_CHILD_WIDTH; - req->height += NO_CHILD_HEIGHT; - } - - req->width += GTK_CONTAINER (widget)->border_width * 2; - req->height += GTK_CONTAINER (widget)->border_width * 2; -} - -static void -meta_preview_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - MetaPreview *preview; - int border_width; - GtkAllocation child_allocation; - - preview = META_PREVIEW (widget); - - ensure_info (preview); - - widget->allocation = *allocation; - - border_width = GTK_CONTAINER (widget)->border_width; - - if (GTK_BIN (widget)->child && - GTK_WIDGET_VISIBLE (GTK_BIN (widget)->child)) - { - child_allocation.x = widget->allocation.x + border_width + preview->left_width; - child_allocation.y = widget->allocation.y + border_width + preview->top_height; - - child_allocation.width = MAX (1, widget->allocation.width - border_width * 2 - preview->left_width - preview->right_width); - child_allocation.height = MAX (1, widget->allocation.height - border_width * 2 - preview->top_height - preview->bottom_height); - - gtk_widget_size_allocate (GTK_BIN (widget)->child, &child_allocation); - } -} - -static void -clear_cache (MetaPreview *preview) -{ - if (preview->layout) - { - g_object_unref (G_OBJECT (preview->layout)); - preview->layout = NULL; - } - - preview->left_width = -1; - preview->right_width = -1; - preview->top_height = -1; - preview->bottom_height = -1; -} - -void -meta_preview_set_theme (MetaPreview *preview, - MetaTheme *theme) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - preview->theme = theme; - - clear_cache (preview); - - gtk_widget_queue_resize (GTK_WIDGET (preview)); -} - -void -meta_preview_set_title (MetaPreview *preview, - const char *title) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - g_free (preview->title); - preview->title = g_strdup (title); - - clear_cache (preview); - - gtk_widget_queue_resize (GTK_WIDGET (preview)); -} - -void -meta_preview_set_frame_type (MetaPreview *preview, - MetaFrameType type) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - preview->type = type; - - clear_cache (preview); - - gtk_widget_queue_resize (GTK_WIDGET (preview)); -} - -void -meta_preview_set_frame_flags (MetaPreview *preview, - MetaFrameFlags flags) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - preview->flags = flags; - - clear_cache (preview); - - gtk_widget_queue_resize (GTK_WIDGET (preview)); -} - -void -meta_preview_set_button_layout (MetaPreview *preview, - const MetaButtonLayout *button_layout) -{ - g_return_if_fail (META_IS_PREVIEW (preview)); - - preview->button_layout = *button_layout; - - gtk_widget_queue_draw (GTK_WIDGET (preview)); -} - -GdkPixbuf* -meta_preview_get_icon (void) -{ - static GdkPixbuf *default_icon = NULL; - - if (default_icon == NULL) - { - GtkIconTheme *theme; - gboolean icon_exists; - - theme = gtk_icon_theme_get_default (); - - icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME); - - if (icon_exists) - default_icon = gtk_icon_theme_load_icon (theme, - META_DEFAULT_ICON_NAME, - META_ICON_WIDTH, - 0, - NULL); - else - default_icon = gtk_icon_theme_load_icon (theme, - "gtk-missing-image", - META_ICON_WIDTH, - 0, - NULL); - - g_assert (default_icon); - } - - return default_icon; -} - -GdkPixbuf* -meta_preview_get_mini_icon (void) -{ - static GdkPixbuf *default_icon = NULL; - - if (default_icon == NULL) - { - GtkIconTheme *theme; - gboolean icon_exists; - - theme = gtk_icon_theme_get_default (); - - icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME); - - if (icon_exists) - default_icon = gtk_icon_theme_load_icon (theme, - META_DEFAULT_ICON_NAME, - META_MINI_ICON_WIDTH, - 0, - NULL); - else - default_icon = gtk_icon_theme_load_icon (theme, - "gtk-missing-image", - META_MINI_ICON_WIDTH, - 0, - NULL); - - g_assert (default_icon); - } - - return default_icon; -} - -GdkRegion * -meta_preview_get_clip_region (MetaPreview *preview, gint new_window_width, gint new_window_height) -{ - GdkRectangle xrect; - GdkRegion *corners_xregion, *window_xregion; - gint flags; - MetaFrameLayout *fgeom; - MetaFrameStyle *frame_style; - - g_return_val_if_fail (META_IS_PREVIEW (preview), NULL); - - flags = (META_PREVIEW (preview)->flags); - - window_xregion = gdk_region_new (); - - xrect.x = 0; - xrect.y = 0; - xrect.width = new_window_width; - xrect.height = new_window_height; - - gdk_region_union_with_rect (window_xregion, &xrect); - - if (preview->theme == NULL) - return window_xregion; - - /* Otherwise, we do have a theme, so calculate the corners */ - frame_style = meta_theme_get_frame_style (preview->theme, - META_FRAME_TYPE_NORMAL, flags); - - fgeom = frame_style->layout; - - corners_xregion = gdk_region_new (); - - if (fgeom->top_left_corner_rounded_radius != 0) - { - const int corner = fgeom->top_left_corner_rounded_radius; - const float radius = sqrt(corner) + corner; - int i; - - for (i=0; i<corner; i++) - { - - const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); - xrect.x = 0; - xrect.y = i; - xrect.width = width; - xrect.height = 1; - - gdk_region_union_with_rect (corners_xregion, &xrect); - } - } - - if (fgeom->top_right_corner_rounded_radius != 0) - { - const int corner = fgeom->top_right_corner_rounded_radius; - const float radius = sqrt(corner) + corner; - int i; - - for (i=0; i<corner; i++) - { - const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); - xrect.x = new_window_width - width; - xrect.y = i; - xrect.width = width; - xrect.height = 1; - - gdk_region_union_with_rect (corners_xregion, &xrect); - } - } - - if (fgeom->bottom_left_corner_rounded_radius != 0) - { - const int corner = fgeom->bottom_left_corner_rounded_radius; - const float radius = sqrt(corner) + corner; - int i; - - for (i=0; i<corner; i++) - { - const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); - xrect.x = 0; - xrect.y = new_window_height - i - 1; - xrect.width = width; - xrect.height = 1; - - gdk_region_union_with_rect (corners_xregion, &xrect); - } - } - - if (fgeom->bottom_right_corner_rounded_radius != 0) - { - const int corner = fgeom->bottom_right_corner_rounded_radius; - const float radius = sqrt(corner) + corner; - int i; - - for (i=0; i<corner; i++) - { - const int width = floor(0.5 + radius - sqrt(radius*radius - (radius-(i+0.5))*(radius-(i+0.5)))); - xrect.x = new_window_width - width; - xrect.y = new_window_height - i - 1; - xrect.width = width; - xrect.height = 1; - - gdk_region_union_with_rect (corners_xregion, &xrect); - } - } - - gdk_region_subtract (window_xregion, corners_xregion); - gdk_region_destroy (corners_xregion); - - return window_xregion; -} - - diff --git a/src/ui/preview-widget.h b/src/ui/preview-widget.h deleted file mode 100644 index ab6a8f9e..00000000 --- a/src/ui/preview-widget.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme preview widget */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "theme.h" -#include <gtk/gtk.h> - -#ifndef META_PREVIEW_WIDGET_H -#define META_PREVIEW_WIDGET_H - -#define META_TYPE_PREVIEW (meta_preview_get_type ()) -#define META_PREVIEW(obj) (GTK_CHECK_CAST ((obj), META_TYPE_PREVIEW, MetaPreview)) -#define META_PREVIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), META_TYPE_PREVIEW, MetaPreviewClass)) -#define META_IS_PREVIEW(obj) (GTK_CHECK_TYPE ((obj), META_TYPE_PREVIEW)) -#define META_IS_PREVIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), META_TYPE_PREVIEW)) -#define META_PREVIEW_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), META_TYPE_PREVIEW, MetaPreviewClass)) - -typedef struct _MetaPreview MetaPreview; -typedef struct _MetaPreviewClass MetaPreviewClass; - -struct _MetaPreview -{ - GtkBin bin; - - MetaTheme *theme; - char *title; - MetaFrameType type; - MetaFrameFlags flags; - - PangoLayout *layout; - int text_height; - - int left_width; - int right_width; - int top_height; - int bottom_height; - - MetaButtonLayout button_layout; -}; - -struct _MetaPreviewClass -{ - GtkBinClass parent_class; -}; - - -GtkType meta_preview_get_type (void) G_GNUC_CONST; -GtkWidget* meta_preview_new (void); - -void meta_preview_set_theme (MetaPreview *preview, - MetaTheme *theme); -void meta_preview_set_title (MetaPreview *preview, - const char *title); -void meta_preview_set_frame_type (MetaPreview *preview, - MetaFrameType type); -void meta_preview_set_frame_flags (MetaPreview *preview, - MetaFrameFlags flags); -void meta_preview_set_button_layout (MetaPreview *preview, - const MetaButtonLayout *button_layout); - -GdkRegion * meta_preview_get_clip_region (MetaPreview *preview, - gint new_window_width, - gint new_window_height); - -GdkPixbuf* meta_preview_get_icon (void); -GdkPixbuf* meta_preview_get_mini_icon (void); - -#endif diff --git a/src/ui/resizepopup.c b/src/ui/resizepopup.c deleted file mode 100644 index 11698e84..00000000 --- a/src/ui/resizepopup.c +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity resizing-terminal-window feedback */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "resizepopup.h" -#include "util.h" -#include <gtk/gtk.h> -#include <gdk/gdkx.h> - -struct _MetaResizePopup -{ - GtkWidget *size_window; - GtkWidget *size_label; - Display *display; - int screen_number; - - int vertical_size; - int horizontal_size; - - gboolean showing; - - MetaRectangle rect; -}; - -MetaResizePopup* -meta_ui_resize_popup_new (Display *display, - int screen_number) -{ - MetaResizePopup *popup; - - popup = g_new0 (MetaResizePopup, 1); - - popup->display = display; - popup->screen_number = screen_number; - - return popup; -} - -void -meta_ui_resize_popup_free (MetaResizePopup *popup) -{ - g_return_if_fail (popup != NULL); - - if (popup->size_window) - gtk_widget_destroy (popup->size_window); - - g_free (popup); -} - -static void -ensure_size_window (MetaResizePopup *popup) -{ - GtkWidget *frame; - - if (popup->size_window) - return; - - popup->size_window = gtk_window_new (GTK_WINDOW_POPUP); - - gtk_window_set_screen (GTK_WINDOW (popup->size_window), - gdk_display_get_screen (gdk_x11_lookup_xdisplay (popup->display), - popup->screen_number)); - - /* never shrink the size window */ - gtk_window_set_resizable (GTK_WINDOW (popup->size_window), - TRUE); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - - gtk_container_add (GTK_CONTAINER (popup->size_window), frame); - - popup->size_label = gtk_label_new (""); - gtk_misc_set_padding (GTK_MISC (popup->size_label), 3, 3); - - gtk_container_add (GTK_CONTAINER (frame), popup->size_label); - - gtk_widget_show_all (frame); -} - -static void -update_size_window (MetaResizePopup *popup) -{ - char *str; - int x, y; - int width, height; - - g_return_if_fail (popup->size_window != NULL); - - /* Translators: This represents the size of a window. The first number is - * the width of the window and the second is the height. - */ - str = g_strdup_printf (_("%d x %d"), - popup->horizontal_size, - popup->vertical_size); - - gtk_label_set_text (GTK_LABEL (popup->size_label), str); - - g_free (str); - - gtk_window_get_size (GTK_WINDOW (popup->size_window), &width, &height); - - x = popup->rect.x + (popup->rect.width - width) / 2; - y = popup->rect.y + (popup->rect.height - height) / 2; - - if (GTK_WIDGET_REALIZED (popup->size_window)) - { - /* using move_resize to avoid jumpiness */ - gdk_window_move_resize (popup->size_window->window, - x, y, - width, height); - } - else - { - gtk_window_move (GTK_WINDOW (popup->size_window), - x, y); - } -} - -static void -sync_showing (MetaResizePopup *popup) -{ - if (popup->showing) - { - if (popup->size_window) - gtk_widget_show (popup->size_window); - - if (popup->size_window && GTK_WIDGET_REALIZED (popup->size_window)) - gdk_window_raise (popup->size_window->window); - } - else - { - if (popup->size_window) - gtk_widget_hide (popup->size_window); - } -} - -void -meta_ui_resize_popup_set (MetaResizePopup *popup, - MetaRectangle rect, - int base_width, - int base_height, - int width_inc, - int height_inc) -{ - gboolean need_update_size; - int display_w, display_h; - - g_return_if_fail (popup != NULL); - - need_update_size = FALSE; - - display_w = rect.width - base_width; - if (width_inc > 0) - display_w /= width_inc; - - display_h = rect.height - base_height; - if (height_inc > 0) - display_h /= height_inc; - - if (!meta_rectangle_equal(&popup->rect, &rect) || - display_w != popup->horizontal_size || - display_h != popup->vertical_size) - need_update_size = TRUE; - - popup->rect = rect; - popup->vertical_size = display_h; - popup->horizontal_size = display_w; - - if (need_update_size) - { - ensure_size_window (popup); - update_size_window (popup); - } - - sync_showing (popup); -} - -void -meta_ui_resize_popup_set_showing (MetaResizePopup *popup, - gboolean showing) -{ - g_return_if_fail (popup != NULL); - - if (showing == popup->showing) - return; - - popup->showing = !!showing; - - if (popup->showing) - { - ensure_size_window (popup); - update_size_window (popup); - } - - sync_showing (popup); -} diff --git a/src/ui/tabpopup.c b/src/ui/tabpopup.c deleted file mode 100644 index f38bb174..00000000 --- a/src/ui/tabpopup.c +++ /dev/null @@ -1,948 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity popup window thing showing windows you can tab to */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2005 Elijah Newren - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> - -#include "util.h" -#include "core.h" -#include "tabpopup.h" -/* FIXME these two includes are 100% broken ... - */ -#include "../core/workspace.h" -#include "../core/frame-private.h" -#include "draw-workspace.h" -#include <gtk/gtk.h> -#include <math.h> - -#define OUTSIDE_SELECT_RECT 2 -#define INSIDE_SELECT_RECT 2 - -typedef struct _TabEntry TabEntry; - -struct _TabEntry -{ - MetaTabEntryKey key; - char *title; - GdkPixbuf *icon, *dimmed_icon; - GtkWidget *widget; - GdkRectangle rect; - GdkRectangle inner_rect; - guint blank : 1; -}; - -struct _MetaTabPopup -{ - GtkWidget *window; - GtkWidget *label; - GList *current; - GList *entries; - TabEntry *current_selected_entry; - GtkWidget *outline_window; - gboolean outline; -}; - -static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf); -static void select_image (GtkWidget *widget); -static void unselect_image (GtkWidget *widget); - -static GtkWidget* selectable_workspace_new (MetaWorkspace *workspace); -static void select_workspace (GtkWidget *widget); -static void unselect_workspace (GtkWidget *widget); - -static gboolean -outline_window_expose (GtkWidget *widget, - GdkEventExpose *event, - gpointer data) -{ - MetaTabPopup *popup; - TabEntry *te; - - popup = data; - - if (!popup->outline || popup->current_selected_entry == NULL) - return FALSE; - - te = popup->current_selected_entry; - - gdk_draw_rectangle (widget->window, - widget->style->white_gc, - FALSE, - 0, 0, - te->rect.width - 1, - te->rect.height - 1); - - gdk_draw_rectangle (widget->window, - widget->style->white_gc, - FALSE, - te->inner_rect.x - 1, te->inner_rect.y - 1, - te->inner_rect.width + 1, - te->inner_rect.height + 1); - - return FALSE; -} - -static GdkPixbuf* -dimm_icon (GdkPixbuf *pixbuf) -{ - int x, y, pixel_stride, row_stride; - guchar *row, *pixels; - int w, h; - GdkPixbuf *dimmed_pixbuf; - - if (gdk_pixbuf_get_has_alpha (pixbuf)) - { - dimmed_pixbuf = gdk_pixbuf_copy (pixbuf); - } - else - { - dimmed_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); - } - - w = gdk_pixbuf_get_width (dimmed_pixbuf); - h = gdk_pixbuf_get_height (dimmed_pixbuf); - - pixel_stride = 4; - - row = gdk_pixbuf_get_pixels (dimmed_pixbuf); - row_stride = gdk_pixbuf_get_rowstride (dimmed_pixbuf); - - for (y = 0; y < h; y++) - { - pixels = row; - for (x = 0; x < w; x++) - { - pixels[3] /= 2; - pixels += pixel_stride; - } - row += row_stride; - } - return dimmed_pixbuf; -} - -static TabEntry* -tab_entry_new (const MetaTabEntry *entry, - gint screen_width, - gboolean outline) -{ - TabEntry *te; - - te = g_new (TabEntry, 1); - te->key = entry->key; - te->title = NULL; - if (entry->title) - { - gchar *str; - gchar *tmp; - gchar *formatter = "%s"; - - str = meta_g_utf8_strndup (entry->title, 4096); - - if (entry->hidden) - { - formatter = "[%s]"; - } - - tmp = g_markup_printf_escaped (formatter, str); - g_free (str); - str = tmp; - - if (entry->demands_attention) - { - /* Escape the whole line of text then markup the text and - * copy it back into the original buffer. - */ - tmp = g_strdup_printf ("<b>%s</b>", str); - g_free (str); - str = tmp; - } - - te->title=g_strdup(str); - - g_free (str); - } - te->widget = NULL; - te->icon = entry->icon; - te->blank = entry->blank; - te->dimmed_icon = NULL; - if (te->icon) - { - g_object_ref (G_OBJECT (te->icon)); - if (entry->hidden) - te->dimmed_icon = dimm_icon (entry->icon); - } - - if (outline) - { - te->rect.x = entry->rect.x; - te->rect.y = entry->rect.y; - te->rect.width = entry->rect.width; - te->rect.height = entry->rect.height; - - te->inner_rect.x = entry->inner_rect.x; - te->inner_rect.y = entry->inner_rect.y; - te->inner_rect.width = entry->inner_rect.width; - te->inner_rect.height = entry->inner_rect.height; - } - return te; -} - -MetaTabPopup* -meta_ui_tab_popup_new (const MetaTabEntry *entries, - int screen_number, - int entry_count, - int width, - gboolean outline) -{ - MetaTabPopup *popup; - int i, left, right, top, bottom; - int height; - GtkWidget *table; - GtkWidget *vbox; - GtkWidget *align; - GList *tmp; - GtkWidget *frame; - int max_label_width; /* the actual max width of the labels we create */ - AtkObject *obj; - GdkScreen *screen; - int screen_width; - - popup = g_new (MetaTabPopup, 1); - - popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP); - - screen = gdk_display_get_screen (gdk_display_get_default (), - screen_number); - gtk_window_set_screen (GTK_WINDOW (popup->outline_window), - screen); - - gtk_widget_set_app_paintable (popup->outline_window, TRUE); - gtk_widget_realize (popup->outline_window); - - g_signal_connect (G_OBJECT (popup->outline_window), "expose_event", - G_CALLBACK (outline_window_expose), popup); - - popup->window = gtk_window_new (GTK_WINDOW_POPUP); - - gtk_window_set_screen (GTK_WINDOW (popup->window), - screen); - - gtk_window_set_position (GTK_WINDOW (popup->window), - GTK_WIN_POS_CENTER_ALWAYS); - /* enable resizing, to get never-shrink behavior */ - gtk_window_set_resizable (GTK_WINDOW (popup->window), - TRUE); - popup->current = NULL; - popup->entries = NULL; - popup->current_selected_entry = NULL; - popup->outline = outline; - - screen_width = gdk_screen_get_width (screen); - for (i = 0; i < entry_count; ++i) - { - TabEntry* new_entry = tab_entry_new (&entries[i], screen_width, outline); - popup->entries = g_list_prepend (popup->entries, new_entry); - } - - popup->entries = g_list_reverse (popup->entries); - - g_assert (width > 0); - height = i / width; - if (i % width) - height += 1; - - table = gtk_table_new (height, width, FALSE); - vbox = gtk_vbox_new (FALSE, 0); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - gtk_container_set_border_width (GTK_CONTAINER (table), 1); - gtk_container_add (GTK_CONTAINER (popup->window), - frame); - gtk_container_add (GTK_CONTAINER (frame), - vbox); - - align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); - - gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0); - - gtk_container_add (GTK_CONTAINER (align), - table); - - popup->label = gtk_label_new (""); - - /* Set the accessible role of the label to a status bar so it - * will emit name changed events that can be used by screen - * readers. - */ - obj = gtk_widget_get_accessible (popup->label); - atk_object_set_role (obj, ATK_ROLE_STATUSBAR); - - gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3); - - gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0); - - max_label_width = 0; - top = 0; - bottom = 1; - tmp = popup->entries; - - while (tmp && top < height) - { - left = 0; - right = 1; - - while (tmp && left < width) - { - GtkWidget *image; - GtkRequisition req; - - TabEntry *te; - - te = tmp->data; - - if (te->blank) - { - /* just stick a widget here to avoid special cases */ - image = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); - } - else if (outline) - { - if (te->dimmed_icon) - { - image = selectable_image_new (te->dimmed_icon); - } - else - { - image = selectable_image_new (te->icon); - } - - gtk_misc_set_padding (GTK_MISC (image), - INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1, - INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1); - gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5); - } - else - { - image = selectable_workspace_new ((MetaWorkspace *) te->key); - } - - te->widget = image; - - gtk_table_attach (GTK_TABLE (table), - te->widget, - left, right, top, bottom, - 0, 0, - 0, 0); - - /* Efficiency rules! */ - gtk_label_set_markup (GTK_LABEL (popup->label), - te->title); - gtk_widget_size_request (popup->label, &req); - max_label_width = MAX (max_label_width, req.width); - - tmp = tmp->next; - - ++left; - ++right; - } - - ++top; - ++bottom; - } - - /* remove all the temporary text */ - gtk_label_set_text (GTK_LABEL (popup->label), ""); - /* Make it so that we ellipsize if the text is too long */ - gtk_label_set_ellipsize (GTK_LABEL (popup->label), PANGO_ELLIPSIZE_END); - - /* Limit the window size to no bigger than screen_width/4 */ - if (max_label_width>(screen_width/4)) - { - max_label_width = screen_width/4; - } - - max_label_width += 20; /* add random padding */ - - gtk_window_set_default_size (GTK_WINDOW (popup->window), - max_label_width, - -1); - - return popup; -} - -static void -free_tab_entry (gpointer data, gpointer user_data) -{ - TabEntry *te; - - te = data; - - g_free (te->title); - if (te->icon) - g_object_unref (G_OBJECT (te->icon)); - if (te->dimmed_icon) - g_object_unref (G_OBJECT (te->dimmed_icon)); - - g_free (te); -} - -void -meta_ui_tab_popup_free (MetaTabPopup *popup) -{ - meta_verbose ("Destroying tab popup window\n"); - - gtk_widget_destroy (popup->outline_window); - gtk_widget_destroy (popup->window); - - g_list_foreach (popup->entries, free_tab_entry, NULL); - - g_list_free (popup->entries); - - g_free (popup); -} - -void -meta_ui_tab_popup_set_showing (MetaTabPopup *popup, - gboolean showing) -{ - if (showing) - { - gtk_widget_show_all (popup->window); - } - else - { - if (GTK_WIDGET_VISIBLE (popup->window)) - { - meta_verbose ("Hiding tab popup window\n"); - gtk_widget_hide (popup->window); - meta_core_increment_event_serial (gdk_display); - } - } -} - -static void -display_entry (MetaTabPopup *popup, - TabEntry *te) -{ - GdkRectangle rect; - GdkRegion *region; - GdkRegion *inner_region; - - - if (popup->current_selected_entry) - { - if (popup->outline) - unselect_image (popup->current_selected_entry->widget); - else - unselect_workspace (popup->current_selected_entry->widget); - } - - gtk_label_set_markup (GTK_LABEL (popup->label), te->title); - - if (popup->outline) - select_image (te->widget); - else - select_workspace (te->widget); - - if (popup->outline) - { - /* Do stuff behind gtk's back */ - gdk_window_hide (popup->outline_window->window); - meta_core_increment_event_serial (gdk_display); - - rect = te->rect; - rect.x = 0; - rect.y = 0; - - gdk_window_move_resize (popup->outline_window->window, - te->rect.x, te->rect.y, - te->rect.width, te->rect.height); - - gdk_window_set_background (popup->outline_window->window, - &popup->outline_window->style->black); - - region = gdk_region_rectangle (&rect); - inner_region = gdk_region_rectangle (&te->inner_rect); - gdk_region_subtract (region, inner_region); - gdk_region_destroy (inner_region); - - gdk_window_shape_combine_region (popup->outline_window->window, - region, - 0, 0); - - gdk_region_destroy (region); - - /* This should piss off gtk a bit, but we don't want to raise - * above the tab popup. So, instead of calling gtk_widget_show, - * we manually set the window as mapped and then manually map it - * with gdk functions. - */ - GTK_WIDGET_SET_FLAGS (popup->outline_window, GTK_MAPPED); - gdk_window_show_unraised (popup->outline_window->window); - } - - /* Must be before we handle an expose for the outline window */ - popup->current_selected_entry = te; -} - -void -meta_ui_tab_popup_forward (MetaTabPopup *popup) -{ - if (popup->current != NULL) - popup->current = popup->current->next; - - if (popup->current == NULL) - popup->current = popup->entries; - - if (popup->current != NULL) - { - TabEntry *te; - - te = popup->current->data; - - display_entry (popup, te); - } -} - -void -meta_ui_tab_popup_backward (MetaTabPopup *popup) -{ - if (popup->current != NULL) - popup->current = popup->current->prev; - - if (popup->current == NULL) - popup->current = g_list_last (popup->entries); - - if (popup->current != NULL) - { - TabEntry *te; - - te = popup->current->data; - - display_entry (popup, te); - } -} - -MetaTabEntryKey -meta_ui_tab_popup_get_selected (MetaTabPopup *popup) -{ - if (popup->current) - { - TabEntry *te; - - te = popup->current->data; - - return te->key; - } - else - return (MetaTabEntryKey)None; -} - -void -meta_ui_tab_popup_select (MetaTabPopup *popup, - MetaTabEntryKey key) -{ - GList *tmp; - - /* Note, "key" may not be in the list of entries; other code assumes - * it's OK to pass in a key that isn't. - */ - - tmp = popup->entries; - while (tmp != NULL) - { - TabEntry *te; - - te = tmp->data; - - if (te->key == key) - { - popup->current = tmp; - - display_entry (popup, te); - - return; - } - - tmp = tmp->next; - } -} - -#define META_TYPE_SELECT_IMAGE (meta_select_image_get_type ()) -#define META_SELECT_IMAGE(obj) (GTK_CHECK_CAST ((obj), META_TYPE_SELECT_IMAGE, MetaSelectImage)) - -typedef struct _MetaSelectImage MetaSelectImage; -typedef struct _MetaSelectImageClass MetaSelectImageClass; - -struct _MetaSelectImage -{ - GtkImage parent_instance; - guint selected : 1; -}; - -struct _MetaSelectImageClass -{ - GtkImageClass parent_class; -}; - - -static GType meta_select_image_get_type (void) G_GNUC_CONST; - -static GtkWidget* -selectable_image_new (GdkPixbuf *pixbuf) -{ - GtkWidget *w; - - w = g_object_new (meta_select_image_get_type (), NULL); - gtk_image_set_from_pixbuf (GTK_IMAGE (w), pixbuf); - - return w; -} - -static void -select_image (GtkWidget *widget) -{ - META_SELECT_IMAGE (widget)->selected = TRUE; - gtk_widget_queue_draw (widget); -} - -static void -unselect_image (GtkWidget *widget) -{ - META_SELECT_IMAGE (widget)->selected = FALSE; - gtk_widget_queue_draw (widget); -} - -static void meta_select_image_class_init (MetaSelectImageClass *klass); -static gboolean meta_select_image_expose_event (GtkWidget *widget, - GdkEventExpose *event); - -static GtkImageClass *parent_class; - -GType -meta_select_image_get_type (void) -{ - static GtkType image_type = 0; - - if (!image_type) - { - static const GTypeInfo image_info = - { - sizeof (MetaSelectImageClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) meta_select_image_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (MetaSelectImage), - 16, /* n_preallocs */ - (GInstanceInitFunc) NULL, - }; - - image_type = g_type_register_static (GTK_TYPE_IMAGE, "MetaSelectImage", &image_info, 0); - } - - return image_type; -} - -static void -meta_select_image_class_init (MetaSelectImageClass *klass) -{ - GtkWidgetClass *widget_class; - - parent_class = gtk_type_class (gtk_image_get_type ()); - - widget_class = GTK_WIDGET_CLASS (klass); - - widget_class->expose_event = meta_select_image_expose_event; -} - -static gboolean -meta_select_image_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - if (META_SELECT_IMAGE (widget)->selected) - { - int x, y, w, h; - GtkMisc *misc; - - misc = GTK_MISC (widget); - - x = (widget->allocation.x * (1.0 - misc->xalign) + - (widget->allocation.x + widget->allocation.width - - (widget->requisition.width - misc->xpad * 2)) * - misc->xalign) + 0.5; - y = (widget->allocation.y * (1.0 - misc->yalign) + - (widget->allocation.y + widget->allocation.height - - (widget->requisition.height - misc->ypad * 2)) * - misc->yalign) + 0.5; - - x -= INSIDE_SELECT_RECT + 1; - y -= INSIDE_SELECT_RECT + 1; - - w = widget->requisition.width - OUTSIDE_SELECT_RECT * 2 - 1; - h = widget->requisition.height - OUTSIDE_SELECT_RECT * 2 - 1; - - gdk_draw_rectangle (widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - FALSE, - x, y, w, h); - gdk_draw_rectangle (widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - FALSE, - x - 1, y - 1, w + 2, h + 2); - -#if 0 - gdk_draw_rectangle (widget->window, - widget->style->bg_gc[GTK_STATE_SELECTED], - TRUE, - x, y, w, h); -#endif -#if 0 - gtk_paint_focus (widget->style, widget->window, - &event->area, widget, "meta-tab-image", - x, y, w, h); -#endif - } - - return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); -} - -#define META_TYPE_SELECT_WORKSPACE (meta_select_workspace_get_type ()) -#define META_SELECT_WORKSPACE(obj) (GTK_CHECK_CAST ((obj), META_TYPE_SELECT_WORKSPACE, MetaSelectWorkspace)) - -typedef struct _MetaSelectWorkspace MetaSelectWorkspace; -typedef struct _MetaSelectWorkspaceClass MetaSelectWorkspaceClass; - -struct _MetaSelectWorkspace -{ - GtkDrawingArea parent_instance; - MetaWorkspace *workspace; - guint selected : 1; -}; - -struct _MetaSelectWorkspaceClass -{ - GtkDrawingAreaClass parent_class; -}; - - -static GType meta_select_workspace_get_type (void) G_GNUC_CONST; - -#define SELECT_OUTLINE_WIDTH 2 -#define MINI_WORKSPACE_WIDTH 48 - -static GtkWidget* -selectable_workspace_new (MetaWorkspace *workspace) -{ - GtkWidget *widget; - double screen_aspect; - - widget = g_object_new (meta_select_workspace_get_type (), NULL); - - screen_aspect = (double) workspace->screen->rect.height / - (double) workspace->screen->rect.width; - - /* account for select rect */ - gtk_widget_set_size_request (widget, - MINI_WORKSPACE_WIDTH + SELECT_OUTLINE_WIDTH * 2, - MINI_WORKSPACE_WIDTH * screen_aspect + SELECT_OUTLINE_WIDTH * 2); - - META_SELECT_WORKSPACE (widget)->workspace = workspace; - - return widget; -} - -static void -select_workspace (GtkWidget *widget) -{ - META_SELECT_WORKSPACE(widget)->selected = TRUE; - gtk_widget_queue_draw (widget); -} - -static void -unselect_workspace (GtkWidget *widget) -{ - META_SELECT_WORKSPACE (widget)->selected = FALSE; - gtk_widget_queue_draw (widget); -} - -static void meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass); - -static gboolean meta_select_workspace_expose_event (GtkWidget *widget, - GdkEventExpose *event); - -GType -meta_select_workspace_get_type (void) -{ - static GtkType workspace_type = 0; - - if (!workspace_type) - { - static const GTypeInfo workspace_info = - { - sizeof (MetaSelectWorkspaceClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) meta_select_workspace_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (MetaSelectWorkspace), - 16, /* n_preallocs */ - (GInstanceInitFunc) NULL, - }; - - workspace_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, - "MetaSelectWorkspace", - &workspace_info, - 0); - } - - return workspace_type; -} - -static void -meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass) -{ - GtkWidgetClass *widget_class; - - widget_class = GTK_WIDGET_CLASS (klass); - - widget_class->expose_event = meta_select_workspace_expose_event; -} - -/** - * meta_convert_meta_to_wnck() converts a MetaWindow to a - * WnckWindowDisplayInfo window that is used to build a thumbnail of a - * workspace. - **/ -static WnckWindowDisplayInfo -meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen) -{ - WnckWindowDisplayInfo wnck_window; - wnck_window.icon = window->icon; - wnck_window.mini_icon = window->mini_icon; - - wnck_window.is_active = FALSE; - if (window == window->display->expected_focus_window) - wnck_window.is_active = TRUE; - - if (window->frame) - { - wnck_window.x = window->frame->rect.x; - wnck_window.y = window->frame->rect.y; - wnck_window.width = window->frame->rect.width; - wnck_window.height = window->frame->rect.height; - } - else - { - wnck_window.x = window->rect.x; - wnck_window.y = window->rect.y; - wnck_window.width = window->rect.width; - wnck_window.height = window->rect.height; - } - return wnck_window; -} - - -static gboolean -meta_select_workspace_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - MetaWorkspace *workspace; - WnckWindowDisplayInfo *windows; - int i, n_windows; - GList *tmp, *list; - - workspace = META_SELECT_WORKSPACE (widget)->workspace; - - list = meta_stack_list_windows (workspace->screen->stack, workspace); - n_windows = g_list_length (list); - windows = g_new (WnckWindowDisplayInfo, n_windows); - - tmp = list; - i = 0; - while (tmp != NULL) - { - MetaWindow *window; - gboolean ignoreable_sticky; - - window = tmp->data; - - ignoreable_sticky = window->on_all_workspaces && - workspace != workspace->screen->active_workspace; - - if (window->skip_pager || - !meta_window_showing_on_its_workspace (window) || - window->unmaps_pending || - ignoreable_sticky) - { - --n_windows; - } - else - { - windows[i] = meta_convert_meta_to_wnck (window, workspace->screen); - i++; - } - tmp = tmp->next; - } - - g_list_free (list); - - wnck_draw_workspace (widget, - widget->window, - SELECT_OUTLINE_WIDTH, - SELECT_OUTLINE_WIDTH, - widget->allocation.width - SELECT_OUTLINE_WIDTH * 2, - widget->allocation.height - SELECT_OUTLINE_WIDTH * 2, - workspace->screen->rect.width, - workspace->screen->rect.height, - NULL, - (workspace->screen->active_workspace == workspace), - windows, - n_windows); - - g_free (windows); - - if (META_SELECT_WORKSPACE (widget)->selected) - { - i = SELECT_OUTLINE_WIDTH - 1; - while (i >= 0) - { - gdk_draw_rectangle (widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - FALSE, - i, - i, - widget->allocation.width - i * 2 - 1, - widget->allocation.height - i * 2 - 1); - - --i; - } - } - - return TRUE; -} - diff --git a/src/ui/testgradient.c b/src/ui/testgradient.c deleted file mode 100644 index 28de317d..00000000 --- a/src/ui/testgradient.c +++ /dev/null @@ -1,348 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity gradient test program */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. */ - -#include "gradient.h" -#include <gtk/gtk.h> - -typedef void (* RenderGradientFunc) (GdkDrawable *drawable, - GdkGC *gc, - int width, - int height); - -static void -draw_checkerboard (GdkDrawable *drawable, - int width, - int height) -{ - gint i, j, xcount, ycount; - GdkGC *gc1, *gc2; - GdkColor color; - -#define CHECK_SIZE 10 -#define SPACING 2 - - /* It would be a bit more efficient to keep these - * GC's around instead of recreating on each expose, but - * this is the lazy/slow way. - */ - gc1 = gdk_gc_new (drawable); - color.red = 30000; - color.green = 30000; - color.blue = 30000; - gdk_gc_set_rgb_fg_color (gc1, &color); - - gc2 = gdk_gc_new (drawable); - color.red = 50000; - color.green = 50000; - color.blue = 50000; - gdk_gc_set_rgb_fg_color (gc2, &color); - - xcount = 0; - i = SPACING; - while (i < width) - { - j = SPACING; - ycount = xcount % 2; /* start with even/odd depending on row */ - while (j < height) - { - GdkGC *gc; - - if (ycount % 2) - gc = gc1; - else - gc = gc2; - - /* If we're outside event->area, this will do nothing. - * It might be mildly more efficient if we handled - * the clipping ourselves, but again we're feeling lazy. - */ - gdk_draw_rectangle (drawable, - gc, - TRUE, - i, j, - CHECK_SIZE, - CHECK_SIZE); - - j += CHECK_SIZE + SPACING; - ++ycount; - } - - i += CHECK_SIZE + SPACING; - ++xcount; - } - - g_object_unref (G_OBJECT (gc1)); - g_object_unref (G_OBJECT (gc2)); -} - -static void -render_simple (GdkDrawable *drawable, - GdkGC *gc, - int width, int height, - MetaGradientType type, - gboolean with_alpha) -{ - GdkPixbuf *pixbuf; - GdkColor from, to; - - gdk_color_parse ("blue", &from); - gdk_color_parse ("green", &to); - - pixbuf = meta_gradient_create_simple (width, height, - &from, &to, - type); - - if (with_alpha) - { - const unsigned char alphas[] = { 0xff, 0xaa, 0x2f, 0x0, 0xcc, 0xff, 0xff }; - - if (!gdk_pixbuf_get_has_alpha (pixbuf)) - { - GdkPixbuf *new_pixbuf; - - new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = new_pixbuf; - } - - meta_gradient_add_alpha (pixbuf, - alphas, G_N_ELEMENTS (alphas), - META_GRADIENT_HORIZONTAL); - - draw_checkerboard (drawable, width, height); - } - - gdk_draw_pixbuf (drawable, - gc, - pixbuf, - 0, 0, - 0, 0, width, height, - GDK_RGB_DITHER_MAX, - 0, 0); - - g_object_unref (G_OBJECT (pixbuf)); -} - -static void -render_vertical_func (GdkDrawable *drawable, - GdkGC *gc, - int width, int height) -{ - render_simple (drawable, gc, width, height, META_GRADIENT_VERTICAL, FALSE); -} - -static void -render_horizontal_func (GdkDrawable *drawable, - GdkGC *gc, - int width, int height) -{ - render_simple (drawable, gc, width, height, META_GRADIENT_HORIZONTAL, FALSE); -} - -static void -render_diagonal_func (GdkDrawable *drawable, - GdkGC *gc, - int width, int height) -{ - render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL, FALSE); -} - -static void -render_diagonal_alpha_func (GdkDrawable *drawable, - GdkGC *gc, - int width, int height) -{ - render_simple (drawable, gc, width, height, META_GRADIENT_DIAGONAL, TRUE); -} - -static void -render_multi (GdkDrawable *drawable, - GdkGC *gc, - int width, int height, - MetaGradientType type) -{ - GdkPixbuf *pixbuf; -#define N_COLORS 5 - GdkColor colors[N_COLORS]; - - gdk_color_parse ("red", &colors[0]); - gdk_color_parse ("blue", &colors[1]); - gdk_color_parse ("orange", &colors[2]); - gdk_color_parse ("pink", &colors[3]); - gdk_color_parse ("green", &colors[4]); - - pixbuf = meta_gradient_create_multi (width, height, - colors, N_COLORS, - type); - - gdk_pixbuf_render_to_drawable (pixbuf, - drawable, - gc, - 0, 0, - 0, 0, width, height, - GDK_RGB_DITHER_NORMAL, - 0, 0); - - g_object_unref (G_OBJECT (pixbuf)); -#undef N_COLORS -} - -static void -render_vertical_multi_func (GdkDrawable *drawable, - GdkGC *gc, - int width, int height) -{ - render_multi (drawable, gc, width, height, META_GRADIENT_VERTICAL); -} - -static void -render_horizontal_multi_func (GdkDrawable *drawable, - GdkGC *gc, - int width, int height) -{ - render_multi (drawable, gc, width, height, META_GRADIENT_HORIZONTAL); -} - -static void -render_diagonal_multi_func (GdkDrawable *drawable, - GdkGC *gc, - int width, int height) -{ - render_multi (drawable, gc, width, height, META_GRADIENT_DIAGONAL); -} - -static void -render_interwoven_func (GdkDrawable *drawable, - GdkGC *gc, - int width, int height) -{ - GdkPixbuf *pixbuf; -#define N_COLORS 4 - GdkColor colors[N_COLORS]; - - gdk_color_parse ("red", &colors[0]); - gdk_color_parse ("blue", &colors[1]); - gdk_color_parse ("pink", &colors[2]); - gdk_color_parse ("green", &colors[3]); - - pixbuf = meta_gradient_create_interwoven (width, height, - colors, height / 10, - colors + 2, height / 14); - - gdk_pixbuf_render_to_drawable (pixbuf, - drawable, - gc, - 0, 0, - 0, 0, width, height, - GDK_RGB_DITHER_NORMAL, - 0, 0); - - g_object_unref (G_OBJECT (pixbuf)); -} - -static gboolean -expose_callback (GtkWidget *widget, - GdkEventExpose *event, - gpointer data) -{ - RenderGradientFunc func = data; - - (* func) (widget->window, - widget->style->fg_gc[widget->state], - widget->allocation.width, - widget->allocation.height); - - return TRUE; -} - -static GtkWidget* -create_gradient_window (const char *title, - RenderGradientFunc func) -{ - GtkWidget *window; - GtkWidget *drawing_area; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_window_set_title (GTK_WINDOW (window), title); - - drawing_area = gtk_drawing_area_new (); - - gtk_widget_set_size_request (drawing_area, 1, 1); - - gtk_window_set_default_size (GTK_WINDOW (window), 175, 175); - - g_signal_connect (G_OBJECT (drawing_area), - "expose_event", - G_CALLBACK (expose_callback), - func); - - gtk_container_add (GTK_CONTAINER (window), drawing_area); - - gtk_widget_show_all (window); - - return window; -} - -static void -meta_gradient_test (void) -{ - GtkWidget *window; - - window = create_gradient_window ("Simple vertical", - render_vertical_func); - - window = create_gradient_window ("Simple horizontal", - render_horizontal_func); - - window = create_gradient_window ("Simple diagonal", - render_diagonal_func); - - window = create_gradient_window ("Multi vertical", - render_vertical_multi_func); - - window = create_gradient_window ("Multi horizontal", - render_horizontal_multi_func); - - window = create_gradient_window ("Multi diagonal", - render_diagonal_multi_func); - - window = create_gradient_window ("Interwoven", - render_interwoven_func); - - window = create_gradient_window ("Simple diagonal with horizontal multi alpha", - render_diagonal_alpha_func); - -} - -int -main (int argc, char **argv) -{ - gtk_init (&argc, &argv); - - meta_gradient_test (); - - gtk_main (); - - return 0; -} - diff --git a/src/ui/theme-parser.c b/src/ui/theme-parser.c deleted file mode 100644 index 98dc1662..00000000 --- a/src/ui/theme-parser.c +++ /dev/null @@ -1,4090 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme parsing */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "theme-parser.h" -#include "util.h" -#include <string.h> -#include <stdlib.h> - -typedef enum -{ - STATE_START, - STATE_THEME, - /* info section */ - STATE_INFO, - STATE_NAME, - STATE_AUTHOR, - STATE_COPYRIGHT, - STATE_DATE, - STATE_DESCRIPTION, - /* constants */ - STATE_CONSTANT, - /* geometry */ - STATE_FRAME_GEOMETRY, - STATE_DISTANCE, - STATE_BORDER, - STATE_ASPECT_RATIO, - /* draw ops */ - STATE_DRAW_OPS, - STATE_LINE, - STATE_RECTANGLE, - STATE_ARC, - STATE_CLIP, - STATE_TINT, - STATE_GRADIENT, - STATE_IMAGE, - STATE_GTK_ARROW, - STATE_GTK_BOX, - STATE_GTK_VLINE, - STATE_ICON, - STATE_TITLE, - STATE_INCLUDE, /* include another draw op list */ - STATE_TILE, /* tile another draw op list */ - /* sub-parts of gradient */ - STATE_COLOR, - /* frame style */ - STATE_FRAME_STYLE, - STATE_PIECE, - STATE_BUTTON, - /* style set */ - STATE_FRAME_STYLE_SET, - STATE_FRAME, - /* assigning style sets to windows */ - STATE_WINDOW, - /* things we don't use any more but we can still parse: */ - STATE_MENU_ICON, - STATE_FALLBACK -} ParseState; - -typedef struct -{ - GSList *states; - - const char *theme_name; /* name of theme (directory it's in) */ - char *theme_file; /* theme filename */ - char *theme_dir; /* dir the theme is inside */ - MetaTheme *theme; /* theme being parsed */ - guint format_version; /* version of format of theme file */ - char *name; /* name of named thing being parsed */ - MetaFrameLayout *layout; /* layout being parsed if any */ - MetaDrawOpList *op_list; /* op list being parsed if any */ - MetaDrawOp *op; /* op being parsed if any */ - MetaFrameStyle *style; /* frame style being parsed if any */ - MetaFrameStyleSet *style_set; /* frame style set being parsed if any */ - MetaFramePiece piece; /* position of piece being parsed */ - MetaButtonType button_type; /* type of button/menuitem being parsed */ - MetaButtonState button_state; /* state of button being parsed */ -} ParseInfo; - -static void set_error (GError **err, - GMarkupParseContext *context, - int error_domain, - int error_code, - const char *format, - ...) G_GNUC_PRINTF (5, 6); - -static void add_context_to_error (GError **err, - GMarkupParseContext *context); - -static void parse_info_init (ParseInfo *info); -static void parse_info_free (ParseInfo *info); - -static void push_state (ParseInfo *info, - ParseState state); -static void pop_state (ParseInfo *info); -static ParseState peek_state (ParseInfo *info); - - -static void parse_toplevel_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_info_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_geometry_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_draw_op_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_gradient_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_style_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); -static void parse_style_set_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); - -static void parse_piece_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); - -static void parse_button_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); - -static void parse_menu_icon_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error); - -static void start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); - -/* Translators: This means that an attribute which should have been found - * on an XML element was not in fact found. - */ -#define ATTRIBUTE_NOT_FOUND _("No \"%s\" attribute on element <%s>") - -static GMarkupParser metacity_theme_parser = { - start_element_handler, - end_element_handler, - text_handler, - NULL, - NULL -}; - -static void -set_error (GError **err, - GMarkupParseContext *context, - int error_domain, - int error_code, - const char *format, - ...) -{ - int line, ch; - va_list args; - char *str; - - g_markup_parse_context_get_position (context, &line, &ch); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - - g_set_error (err, error_domain, error_code, - _("Line %d character %d: %s"), - line, ch, str); - - g_free (str); -} - -static void -add_context_to_error (GError **err, - GMarkupParseContext *context) -{ - int line, ch; - char *str; - - if (err == NULL || *err == NULL) - return; - - g_markup_parse_context_get_position (context, &line, &ch); - - str = g_strdup_printf (_("Line %d character %d: %s"), - line, ch, (*err)->message); - g_free ((*err)->message); - (*err)->message = str; -} - -static void -parse_info_init (ParseInfo *info) -{ - info->theme_file = NULL; - info->states = g_slist_prepend (NULL, GINT_TO_POINTER (STATE_START)); - info->theme = NULL; - info->name = NULL; - info->layout = NULL; - info->op_list = NULL; - info->op = NULL; - info->style = NULL; - info->style_set = NULL; - info->piece = META_FRAME_PIECE_LAST; - info->button_type = META_BUTTON_TYPE_LAST; - info->button_state = META_BUTTON_STATE_LAST; -} - -static void -parse_info_free (ParseInfo *info) -{ - g_free (info->theme_file); - g_free (info->theme_dir); - - g_slist_free (info->states); - - if (info->theme) - meta_theme_free (info->theme); - - if (info->layout) - meta_frame_layout_unref (info->layout); - - if (info->op_list) - meta_draw_op_list_unref (info->op_list); - - if (info->op) - meta_draw_op_free (info->op); - - if (info->style) - meta_frame_style_unref (info->style); - - if (info->style_set) - meta_frame_style_set_unref (info->style_set); -} - -static void -push_state (ParseInfo *info, - ParseState state) -{ - info->states = g_slist_prepend (info->states, GINT_TO_POINTER (state)); -} - -static void -pop_state (ParseInfo *info) -{ - g_return_if_fail (info->states != NULL); - - info->states = g_slist_remove (info->states, info->states->data); -} - -static ParseState -peek_state (ParseInfo *info) -{ - g_return_val_if_fail (info->states != NULL, STATE_START); - - return GPOINTER_TO_INT (info->states->data); -} - -#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0) - -typedef struct -{ - const char *name; - const char **retloc; - gboolean required; -} LocateAttr; - -/* Attribute names can have a leading '!' to indicate that they are - * required. - */ -static gboolean -locate_attributes (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error, - const char *first_attribute_name, - const char **first_attribute_retloc, - ...) -{ - va_list args; - const char *name; - const char **retloc; - int n_attrs; -#define MAX_ATTRS 24 - LocateAttr attrs[MAX_ATTRS]; - gboolean retval; - int i; - - g_return_val_if_fail (first_attribute_name != NULL, FALSE); - g_return_val_if_fail (first_attribute_retloc != NULL, FALSE); - - retval = TRUE; - - /* FIXME: duplicated code; refactor loop */ - n_attrs = 1; - attrs[0].name = first_attribute_name; - attrs[0].retloc = first_attribute_retloc; - attrs[0].required = attrs[0].name[0]=='!'; - if (attrs[0].required) - attrs[0].name++; /* skip past it */ - *first_attribute_retloc = NULL; - - va_start (args, first_attribute_retloc); - - name = va_arg (args, const char*); - retloc = va_arg (args, const char**); - - while (name != NULL) - { - g_return_val_if_fail (retloc != NULL, FALSE); - - g_assert (n_attrs < MAX_ATTRS); - - attrs[n_attrs].name = name; - attrs[n_attrs].retloc = retloc; - attrs[n_attrs].required = attrs[n_attrs].name[0]=='!'; - if (attrs[n_attrs].required) - attrs[n_attrs].name++; /* skip past it */ - - n_attrs += 1; - *retloc = NULL; - - name = va_arg (args, const char*); - retloc = va_arg (args, const char**); - } - - va_end (args); - - i = 0; - while (attribute_names[i]) - { - int j; - gboolean found; - - found = FALSE; - j = 0; - while (j < n_attrs) - { - if (strcmp (attrs[j].name, attribute_names[i]) == 0) - { - retloc = attrs[j].retloc; - - if (*retloc != NULL) - { - - set_error (error, context, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Attribute \"%s\" repeated twice on the same <%s> element"), - attrs[j].name, element_name); - retval = FALSE; - goto out; - } - - *retloc = attribute_values[i]; - found = TRUE; - } - - ++j; - } - - if (!found) - { - j = 0; - while (j < n_attrs) - { - g_warning ("It could have been %s.\n", attrs[j++].name); - } - - set_error (error, context, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Attribute \"%s\" is invalid on <%s> element in this context"), - attribute_names[i], element_name); - retval = FALSE; - goto out; - } - - ++i; - } - - /* Did we catch them all? */ - i = 0; - while (i < n_attrs) - { - if (attrs[i].required && *(attrs[i].retloc)==NULL) - { - set_error (error, context, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, - attrs[i].name, element_name); - retval = FALSE; - goto out; - } - - ++i; - } - - out: - return retval; -} - -static gboolean -check_no_attributes (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - GError **error) -{ - if (attribute_names[0] != NULL) - { - set_error (error, context, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Attribute \"%s\" is invalid on <%s> element in this context"), - attribute_names[0], element_name); - return FALSE; - } - - return TRUE; -} - -#define MAX_REASONABLE 4096 -static gboolean -parse_positive_integer (const char *str, - int *val, - GMarkupParseContext *context, - MetaTheme *theme, - GError **error) -{ - char *end; - long l; - int j; - - *val = 0; - - end = NULL; - - /* Is str a constant? */ - - if (META_THEME_ALLOWS (theme, META_THEME_UBIQUITOUS_CONSTANTS) && - meta_theme_lookup_int_constant (theme, str, &j)) - { - /* Yes. */ - l = j; - } - else - { - /* No. Let's try parsing it instead. */ - - l = strtol (str, &end, 10); - - if (end == NULL || end == str) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Could not parse \"%s\" as an integer"), - str); - return FALSE; - } - - if (*end != '\0') - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand trailing characters \"%s\" in string \"%s\""), - end, str); - return FALSE; - } - } - - if (l < 0) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Integer %ld must be positive"), l); - return FALSE; - } - - if (l > MAX_REASONABLE) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Integer %ld is too large, current max is %d"), - l, MAX_REASONABLE); - return FALSE; - } - - *val = (int) l; - - return TRUE; -} - -static gboolean -parse_double (const char *str, - double *val, - GMarkupParseContext *context, - GError **error) -{ - char *end; - - *val = 0; - - end = NULL; - - *val = g_ascii_strtod (str, &end); - - if (end == NULL || end == str) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Could not parse \"%s\" as a floating point number"), - str); - return FALSE; - } - - if (*end != '\0') - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand trailing characters \"%s\" in string \"%s\""), - end, str); - return FALSE; - } - - return TRUE; -} - -static gboolean -parse_boolean (const char *str, - gboolean *val, - GMarkupParseContext *context, - GError **error) -{ - if (strcmp ("true", str) == 0) - *val = TRUE; - else if (strcmp ("false", str) == 0) - *val = FALSE; - else - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Boolean values must be \"true\" or \"false\" not \"%s\""), - str); - return FALSE; - } - - return TRUE; -} - -static gboolean -parse_rounding (const char *str, - guint *val, - GMarkupParseContext *context, - MetaTheme *theme, - GError **error) -{ - if (strcmp ("true", str) == 0) - *val = 5; /* historical "true" value */ - else if (strcmp ("false", str) == 0) - *val = 0; - else - { - int tmp; - gboolean result; - if (!META_THEME_ALLOWS (theme, META_THEME_VARIED_ROUND_CORNERS)) - { - /* Not known in this version, so bail. */ - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Boolean values must be \"true\" or \"false\" not \"%s\""), - str); - return FALSE; - } - - result = parse_positive_integer (str, &tmp, context, theme, error); - - *val = tmp; - - return result; - } - - return TRUE; -} - -static gboolean -parse_angle (const char *str, - double *val, - GMarkupParseContext *context, - GError **error) -{ - if (!parse_double (str, val, context, error)) - return FALSE; - - if (*val < (0.0 - 1e6) || *val > (360.0 + 1e6)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Angle must be between 0.0 and 360.0, was %g\n"), - *val); - return FALSE; - } - - return TRUE; -} - -static gboolean -parse_alpha (const char *str, - MetaAlphaGradientSpec **spec_ret, - GMarkupParseContext *context, - GError **error) -{ - char **split; - int i; - int n_alphas; - MetaAlphaGradientSpec *spec; - - *spec_ret = NULL; - - split = g_strsplit (str, ":", -1); - - i = 0; - while (split[i]) - ++i; - - if (i == 0) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Could not parse \"%s\" as a floating point number"), - str); - - g_strfreev (split); - - return FALSE; - } - - n_alphas = i; - - /* FIXME allow specifying horizontal/vertical/diagonal in theme format, - * once we implement vertical/diagonal in gradient.c - */ - spec = meta_alpha_gradient_spec_new (META_GRADIENT_HORIZONTAL, - n_alphas); - - i = 0; - while (i < n_alphas) - { - double v; - - if (!parse_double (split[i], &v, context, error)) - { - /* clear up, but don't set error: it was set by parse_double */ - g_strfreev (split); - meta_alpha_gradient_spec_free (spec); - - return FALSE; - } - - if (v < (0.0 - 1e-6) || v > (1.0 + 1e-6)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"), - v); - - g_strfreev (split); - meta_alpha_gradient_spec_free (spec); - - return FALSE; - } - - spec->alphas[i] = (unsigned char) (v * 255); - - ++i; - } - - g_strfreev (split); - - *spec_ret = spec; - - return TRUE; -} - -static MetaColorSpec* -parse_color (MetaTheme *theme, - const char *str, - GError **err) -{ - char* referent; - - if (META_THEME_ALLOWS (theme, META_THEME_COLOR_CONSTANTS) && - meta_theme_lookup_color_constant (theme, str, &referent)) - { - if (referent) - return meta_color_spec_new_from_string (referent, err); - - /* no need to free referent: it's a pointer into the actual hash table */ - } - - return meta_color_spec_new_from_string (str, err); -} - -static gboolean -parse_title_scale (const char *str, - double *val, - GMarkupParseContext *context, - GError **error) -{ - double factor; - - if (strcmp (str, "xx-small") == 0) - factor = PANGO_SCALE_XX_SMALL; - else if (strcmp (str, "x-small") == 0) - factor = PANGO_SCALE_X_SMALL; - else if (strcmp (str, "small") == 0) - factor = PANGO_SCALE_SMALL; - else if (strcmp (str, "medium") == 0) - factor = PANGO_SCALE_MEDIUM; - else if (strcmp (str, "large") == 0) - factor = PANGO_SCALE_LARGE; - else if (strcmp (str, "x-large") == 0) - factor = PANGO_SCALE_X_LARGE; - else if (strcmp (str, "xx-large") == 0) - factor = PANGO_SCALE_XX_LARGE; - else - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,large,x-large,xx-large)\n"), - str); - return FALSE; - } - - *val = factor; - - return TRUE; -} - -static void -parse_toplevel_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_THEME); - - if (ELEMENT_IS ("info")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_INFO); - } - else if (ELEMENT_IS ("constant")) - { - const char *name; - const char *value; - int ival = 0; - double dval = 0.0; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "!value", &value, - NULL)) - return; - - if (strchr (value, '.') && parse_double (value, &dval, context, error)) - { - g_clear_error (error); - - if (!meta_theme_define_float_constant (info->theme, - name, - dval, - error)) - { - add_context_to_error (error, context); - return; - } - } - else if (parse_positive_integer (value, &ival, context, info->theme, error)) - { - g_clear_error (error); - - if (!meta_theme_define_int_constant (info->theme, - name, - ival, - error)) - { - add_context_to_error (error, context); - return; - } - } - else - { - g_clear_error (error); - - if (!meta_theme_define_color_constant (info->theme, - name, - value, - error)) - { - add_context_to_error (error, context); - return; - } - } - - push_state (info, STATE_CONSTANT); - } - else if (ELEMENT_IS ("frame_geometry")) - { - const char *name = NULL; - const char *parent = NULL; - const char *has_title = NULL; - const char *title_scale = NULL; - const char *rounded_top_left = NULL; - const char *rounded_top_right = NULL; - const char *rounded_bottom_left = NULL; - const char *rounded_bottom_right = NULL; - const char *hide_buttons = NULL; - gboolean has_title_val; - guint rounded_top_left_val; - guint rounded_top_right_val; - guint rounded_bottom_left_val; - guint rounded_bottom_right_val; - gboolean hide_buttons_val; - double title_scale_val; - MetaFrameLayout *parent_layout; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "parent", &parent, - "has_title", &has_title, "title_scale", &title_scale, - "rounded_top_left", &rounded_top_left, - "rounded_top_right", &rounded_top_right, - "rounded_bottom_left", &rounded_bottom_left, - "rounded_bottom_right", &rounded_bottom_right, - "hide_buttons", &hide_buttons, - NULL)) - return; - - has_title_val = TRUE; - if (has_title && !parse_boolean (has_title, &has_title_val, context, error)) - return; - - hide_buttons_val = FALSE; - if (hide_buttons && !parse_boolean (hide_buttons, &hide_buttons_val, context, error)) - return; - - rounded_top_left_val = 0; - rounded_top_right_val = 0; - rounded_bottom_left_val = 0; - rounded_bottom_right_val = 0; - - if (rounded_top_left && !parse_rounding (rounded_top_left, &rounded_top_left_val, context, info->theme, error)) - return; - if (rounded_top_right && !parse_rounding (rounded_top_right, &rounded_top_right_val, context, info->theme, error)) - return; - if (rounded_bottom_left && !parse_rounding (rounded_bottom_left, &rounded_bottom_left_val, context, info->theme, error)) - return; - if (rounded_bottom_right && !parse_rounding (rounded_bottom_right, &rounded_bottom_right_val, context, info->theme, error)) - return; - - title_scale_val = 1.0; - if (title_scale && !parse_title_scale (title_scale, &title_scale_val, context, error)) - return; - - if (meta_theme_lookup_layout (info->theme, name)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> name \"%s\" used a second time"), - element_name, name); - return; - } - - parent_layout = NULL; - if (parent) - { - parent_layout = meta_theme_lookup_layout (info->theme, parent); - if (parent_layout == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> parent \"%s\" has not been defined"), - element_name, parent); - return; - } - } - - g_assert (info->layout == NULL); - - if (parent_layout) - info->layout = meta_frame_layout_copy (parent_layout); - else - info->layout = meta_frame_layout_new (); - - if (has_title) /* only if explicit, otherwise inherit */ - info->layout->has_title = has_title_val; - - if (META_THEME_ALLOWS (info->theme, META_THEME_HIDDEN_BUTTONS) && hide_buttons_val) - info->layout->hide_buttons = hide_buttons_val; - - if (title_scale) - info->layout->title_scale = title_scale_val; - - if (rounded_top_left) - info->layout->top_left_corner_rounded_radius = rounded_top_left_val; - - if (rounded_top_right) - info->layout->top_right_corner_rounded_radius = rounded_top_right_val; - - if (rounded_bottom_left) - info->layout->bottom_left_corner_rounded_radius = rounded_bottom_left_val; - - if (rounded_bottom_right) - info->layout->bottom_right_corner_rounded_radius = rounded_bottom_right_val; - - meta_theme_insert_layout (info->theme, name, info->layout); - - push_state (info, STATE_FRAME_GEOMETRY); - } - else if (ELEMENT_IS ("draw_ops")) - { - const char *name = NULL; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, - NULL)) - return; - - if (meta_theme_lookup_draw_op_list (info->theme, name)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> name \"%s\" used a second time"), - element_name, name); - return; - } - - g_assert (info->op_list == NULL); - info->op_list = meta_draw_op_list_new (2); - - meta_theme_insert_draw_op_list (info->theme, name, info->op_list); - - push_state (info, STATE_DRAW_OPS); - } - else if (ELEMENT_IS ("frame_style")) - { - const char *name = NULL; - const char *parent = NULL; - const char *geometry = NULL; - const char *background = NULL; - const char *alpha = NULL; - MetaFrameStyle *parent_style; - MetaFrameLayout *layout; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "parent", &parent, - "geometry", &geometry, - "background", &background, - "alpha", &alpha, - NULL)) - return; - - if (meta_theme_lookup_style (info->theme, name)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> name \"%s\" used a second time"), - element_name, name); - return; - } - - parent_style = NULL; - if (parent) - { - parent_style = meta_theme_lookup_style (info->theme, parent); - if (parent_style == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> parent \"%s\" has not been defined"), - element_name, parent); - return; - } - } - - layout = NULL; - if (geometry) - { - layout = meta_theme_lookup_layout (info->theme, geometry); - if (layout == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> geometry \"%s\" has not been defined"), - element_name, geometry); - return; - } - } - else if (parent_style) - { - layout = parent_style->layout; - } - - if (layout == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> must specify either a geometry or a parent that has a geometry"), - element_name); - return; - } - - g_assert (info->style == NULL); - - info->style = meta_frame_style_new (parent_style); - g_assert (info->style->layout == NULL); - meta_frame_layout_ref (layout); - info->style->layout = layout; - - if (background != NULL && META_THEME_ALLOWS (info->theme, META_THEME_FRAME_BACKGROUNDS)) - { - info->style->window_background_color = meta_color_spec_new_from_string (background, error); - if (!info->style->window_background_color) - return; - - if (alpha != NULL) - { - - gboolean success; - MetaAlphaGradientSpec *alpha_vector; - - g_clear_error (error); - /* fortunately, we already have a routine to parse alpha values, - * though it produces a vector of them, which is a superset of - * what we want. - */ - success = parse_alpha (alpha, &alpha_vector, context, error); - if (!success) - return; - - /* alpha_vector->alphas must contain at least one element */ - info->style->window_background_alpha = alpha_vector->alphas[0]; - - meta_alpha_gradient_spec_free (alpha_vector); - } - } - else if (alpha != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("You must specify a background for an alpha value to be meaningful")); - return; - } - - meta_theme_insert_style (info->theme, name, info->style); - - push_state (info, STATE_FRAME_STYLE); - } - else if (ELEMENT_IS ("frame_style_set")) - { - const char *name = NULL; - const char *parent = NULL; - MetaFrameStyleSet *parent_set; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "parent", &parent, - NULL)) - return; - - if (meta_theme_lookup_style_set (info->theme, name)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> name \"%s\" used a second time"), - element_name, name); - return; - } - - parent_set = NULL; - if (parent) - { - parent_set = meta_theme_lookup_style_set (info->theme, parent); - if (parent_set == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("<%s> parent \"%s\" has not been defined"), - element_name, parent); - return; - } - } - - g_assert (info->style_set == NULL); - - info->style_set = meta_frame_style_set_new (parent_set); - - meta_theme_insert_style_set (info->theme, name, info->style_set); - - push_state (info, STATE_FRAME_STYLE_SET); - } - else if (ELEMENT_IS ("window")) - { - const char *type_name = NULL; - const char *style_set_name = NULL; - MetaFrameStyleSet *style_set; - MetaFrameType type; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!type", &type_name, "!style_set", &style_set_name, - NULL)) - return; - - type = meta_frame_type_from_string (type_name); - - if (type == META_FRAME_TYPE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown type \"%s\" on <%s> element"), - type_name, element_name); - return; - } - - style_set = meta_theme_lookup_style_set (info->theme, - style_set_name); - - if (style_set == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown style_set \"%s\" on <%s> element"), - style_set_name, element_name); - return; - } - - if (info->theme->style_sets_by_type[type] != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Window type \"%s\" has already been assigned a style set"), - type_name); - return; - } - - meta_frame_style_set_ref (style_set); - info->theme->style_sets_by_type[type] = style_set; - - push_state (info, STATE_WINDOW); - } - else if (ELEMENT_IS ("menu_icon")) - { - /* Not supported any more, but we have to parse it if they include it, - * for backwards compatibility. - */ - g_assert (info->op_list == NULL); - - push_state (info, STATE_MENU_ICON); - } - else if (ELEMENT_IS ("fallback")) - { - /* Not supported any more, but we have to parse it if they include it, - * for backwards compatibility. - */ - push_state (info, STATE_FALLBACK); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "metacity_theme"); - } -} - -static void -parse_info_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_INFO); - - if (ELEMENT_IS ("name")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_NAME); - } - else if (ELEMENT_IS ("author")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_AUTHOR); - } - else if (ELEMENT_IS ("copyright")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_COPYRIGHT); - } - else if (ELEMENT_IS ("description")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_DESCRIPTION); - } - else if (ELEMENT_IS ("date")) - { - if (!check_no_attributes (context, element_name, - attribute_names, attribute_values, - error)) - return; - - push_state (info, STATE_DATE); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "info"); - } -} - -static void -parse_distance (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - const char *name; - const char *value; - int val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "!value", &value, - NULL)) - return; - - val = 0; - if (!parse_positive_integer (value, &val, context, info->theme, error)) - return; - - g_assert (val >= 0); /* yeah, "non-negative" not "positive" get over it */ - g_assert (info->layout); - - if (strcmp (name, "left_width") == 0) - info->layout->left_width = val; - else if (strcmp (name, "right_width") == 0) - info->layout->right_width = val; - else if (strcmp (name, "bottom_height") == 0) - info->layout->bottom_height = val; - else if (strcmp (name, "title_vertical_pad") == 0) - info->layout->title_vertical_pad = val; - else if (strcmp (name, "right_titlebar_edge") == 0) - info->layout->right_titlebar_edge = val; - else if (strcmp (name, "left_titlebar_edge") == 0) - info->layout->left_titlebar_edge = val; - else if (strcmp (name, "button_width") == 0) - { - info->layout->button_width = val; - - if (!(info->layout->button_sizing == META_BUTTON_SIZING_LAST || - info->layout->button_sizing == META_BUTTON_SIZING_FIXED)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" for buttons")); - return; - } - - info->layout->button_sizing = META_BUTTON_SIZING_FIXED; - } - else if (strcmp (name, "button_height") == 0) - { - info->layout->button_height = val; - - if (!(info->layout->button_sizing == META_BUTTON_SIZING_LAST || - info->layout->button_sizing == META_BUTTON_SIZING_FIXED)) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" for buttons")); - return; - } - - info->layout->button_sizing = META_BUTTON_SIZING_FIXED; - } - else - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Distance \"%s\" is unknown"), name); - return; - } -} - -static void -parse_aspect_ratio (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - const char *name; - const char *value; - double val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, "!value", &value, - NULL)) - return; - - val = 0; - if (!parse_double (value, &val, context, error)) - return; - - g_assert (info->layout); - - if (strcmp (name, "button") == 0) - { - info->layout->button_aspect = val; - - if (info->layout->button_sizing != META_BUTTON_SIZING_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" for buttons")); - return; - } - - info->layout->button_sizing = META_BUTTON_SIZING_ASPECT; - } - else - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Aspect ratio \"%s\" is unknown"), name); - return; - } -} - -static void -parse_border (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - const char *name; - const char *top; - const char *bottom; - const char *left; - const char *right; - int top_val; - int bottom_val; - int left_val; - int right_val; - GtkBorder *border; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!name", &name, - "!top", &top, - "!bottom", &bottom, - "!left", &left, - "!right", &right, - NULL)) - return; - - top_val = 0; - if (!parse_positive_integer (top, &top_val, context, info->theme, error)) - return; - - bottom_val = 0; - if (!parse_positive_integer (bottom, &bottom_val, context, info->theme, error)) - return; - - left_val = 0; - if (!parse_positive_integer (left, &left_val, context, info->theme, error)) - return; - - right_val = 0; - if (!parse_positive_integer (right, &right_val, context, info->theme, error)) - return; - - g_assert (info->layout); - - border = NULL; - - if (strcmp (name, "title_border") == 0) - border = &info->layout->title_border; - else if (strcmp (name, "button_border") == 0) - border = &info->layout->button_border; - - if (border == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Border \"%s\" is unknown"), name); - return; - } - - border->top = top_val; - border->bottom = bottom_val; - border->left = left_val; - border->right = right_val; -} - -static void -parse_geometry_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_FRAME_GEOMETRY); - - if (ELEMENT_IS ("distance")) - { - parse_distance (context, element_name, - attribute_names, attribute_values, - info, error); - push_state (info, STATE_DISTANCE); - } - else if (ELEMENT_IS ("border")) - { - parse_border (context, element_name, - attribute_names, attribute_values, - info, error); - push_state (info, STATE_BORDER); - } - else if (ELEMENT_IS ("aspect_ratio")) - { - parse_aspect_ratio (context, element_name, - attribute_names, attribute_values, - info, error); - - push_state (info, STATE_ASPECT_RATIO); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "frame_geometry"); - } -} - -#if 0 -static gboolean -check_expression (PosToken *tokens, - int n_tokens, - gboolean has_object, - MetaTheme *theme, - GMarkupParseContext *context, - GError **error) -{ - MetaPositionExprEnv env; - int x, y; - - /* We set it all to 0 to try and catch divide-by-zero screwups. - * it's possible we should instead guarantee that widths and heights - * are at least 1. - */ - - env.rect = meta_rect (0, 0, 0, 0); - if (has_object) - { - env.object_width = 0; - env.object_height = 0; - } - else - { - env.object_width = -1; - env.object_height = -1; - } - - env.left_width = 0; - env.right_width = 0; - env.top_height = 0; - env.bottom_height = 0; - env.title_width = 0; - env.title_height = 0; - - env.icon_width = 0; - env.icon_height = 0; - env.mini_icon_width = 0; - env.mini_icon_height = 0; - env.theme = theme; - - if (!meta_parse_position_expression (tokens, n_tokens, - &env, - &x, &y, - error)) - { - add_context_to_error (error, context); - return FALSE; - } - - return TRUE; -} -#endif - -static void -parse_draw_op_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_DRAW_OPS); - - if (ELEMENT_IS ("line")) - { - MetaDrawOp *op; - const char *color; - const char *x1; - const char *y1; - const char *x2; - const char *y2; - const char *dash_on_length; - const char *dash_off_length; - const char *width; - MetaColorSpec *color_spec; - int dash_on_val; - int dash_off_val; - int width_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x1", &x1, "!y1", &y1, - "!x2", &x2, "!y2", &y2, - "dash_on_length", &dash_on_length, - "dash_off_length", &dash_off_length, - "width", &width, - NULL)) - return; - -#if 0 - if (!check_expression (x1, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y1, FALSE, info->theme, context, error)) - return; - - if (!check_expression (x2, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y2, FALSE, info->theme, context, error)) - return; -#endif - - dash_on_val = 0; - if (dash_on_length && - !parse_positive_integer (dash_on_length, &dash_on_val, context, info->theme, error)) - return; - - dash_off_val = 0; - if (dash_off_length && - !parse_positive_integer (dash_off_length, &dash_off_val, context, info->theme, error)) - return; - - width_val = 0; - if (width && - !parse_positive_integer (width, &width_val, context, info->theme, error)) - return; - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_LINE); - - op->data.line.color_spec = color_spec; - - op->data.line.x1 = meta_draw_spec_new (info->theme, x1, NULL); - op->data.line.y1 = meta_draw_spec_new (info->theme, y1, NULL); - op->data.line.x2 = meta_draw_spec_new (info->theme, x2, NULL); - op->data.line.y2 = meta_draw_spec_new (info->theme, y2, NULL); - - op->data.line.width = width_val; - op->data.line.dash_on_length = dash_on_val; - op->data.line.dash_off_length = dash_off_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_LINE); - } - else if (ELEMENT_IS ("rectangle")) - { - MetaDrawOp *op; - const char *color; - const char *x; - const char *y; - const char *width; - const char *height; - const char *filled; - gboolean filled_val; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "filled", &filled, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - - filled_val = FALSE; - if (filled && !parse_boolean (filled, &filled_val, context, error)) - return; - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_RECTANGLE); - - op->data.rectangle.color_spec = color_spec; - op->data.rectangle.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.rectangle.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.rectangle.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.rectangle.height = meta_draw_spec_new (info->theme, - height, NULL); - - op->data.rectangle.filled = filled_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_RECTANGLE); - } - else if (ELEMENT_IS ("arc")) - { - MetaDrawOp *op; - const char *color; - const char *x; - const char *y; - const char *width; - const char *height; - const char *filled; - const char *start_angle; - const char *extent_angle; - const char *from; - const char *to; - gboolean filled_val; - double start_angle_val; - double extent_angle_val; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "filled", &filled, - "start_angle", &start_angle, - "extent_angle", &extent_angle, - "from", &from, - "to", &to, - NULL)) - return; - - if (META_THEME_ALLOWS (info->theme, META_THEME_DEGREES_IN_ARCS) ) - { - if (start_angle == NULL && from == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No \"start_angle\" or \"from\" attribute on element <%s>"), element_name); - return; - } - - if (extent_angle == NULL && to == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No \"extent_angle\" or \"to\" attribute on element <%s>"), element_name); - return; - } - } - else - { - if (start_angle == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, "start_angle", element_name); - return; - } - - if (extent_angle == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, "extent_angle", element_name); - return; - } - } - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - - if (start_angle == NULL) - { - if (!parse_angle (from, &start_angle_val, context, error)) - return; - - start_angle_val = (180-start_angle_val)/360.0; - } - else - { - if (!parse_angle (start_angle, &start_angle_val, context, error)) - return; - } - - if (extent_angle == NULL) - { - if (!parse_angle (to, &extent_angle_val, context, error)) - return; - - extent_angle_val = ((180-extent_angle_val)/360.0) - start_angle_val; - } - else - { - if (!parse_angle (extent_angle, &extent_angle_val, context, error)) - return; - } - - filled_val = FALSE; - if (filled && !parse_boolean (filled, &filled_val, context, error)) - return; - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_ARC); - - op->data.arc.color_spec = color_spec; - - op->data.arc.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.arc.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.arc.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.arc.height = meta_draw_spec_new (info->theme, height, NULL); - - op->data.arc.filled = filled_val; - op->data.arc.start_angle = start_angle_val; - op->data.arc.extent_angle = extent_angle_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_ARC); - } - else if (ELEMENT_IS ("clip")) - { - MetaDrawOp *op; - const char *x; - const char *y; - const char *width; - const char *height; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - op = meta_draw_op_new (META_DRAW_CLIP); - - op->data.clip.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.clip.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.clip.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.clip.height = meta_draw_spec_new (info->theme, height, NULL); - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_CLIP); - } - else if (ELEMENT_IS ("tint")) - { - MetaDrawOp *op; - const char *color; - const char *x; - const char *y; - const char *width; - const char *height; - const char *alpha; - MetaAlphaGradientSpec *alpha_spec; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "!alpha", &alpha, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - alpha_spec = NULL; - if (!parse_alpha (alpha, &alpha_spec, context, error)) - return; - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - if (alpha_spec) - meta_alpha_gradient_spec_free (alpha_spec); - - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_TINT); - - op->data.tint.color_spec = color_spec; - op->data.tint.alpha_spec = alpha_spec; - - op->data.tint.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.tint.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.tint.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.tint.height = meta_draw_spec_new (info->theme, height, NULL); - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_TINT); - } - else if (ELEMENT_IS ("gradient")) - { - const char *x; - const char *y; - const char *width; - const char *height; - const char *type; - const char *alpha; - MetaAlphaGradientSpec *alpha_spec; - MetaGradientType type_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!type", &type, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "alpha", &alpha, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - - type_val = meta_gradient_type_from_string (type); - if (type_val == META_GRADIENT_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Did not understand value \"%s\" for type of gradient"), - type); - return; - } - - alpha_spec = NULL; - if (alpha && !parse_alpha (alpha, &alpha_spec, context, error)) - return; - - g_assert (info->op == NULL); - info->op = meta_draw_op_new (META_DRAW_GRADIENT); - - info->op->data.gradient.x = meta_draw_spec_new (info->theme, x, NULL); - info->op->data.gradient.y = meta_draw_spec_new (info->theme, y, NULL); - info->op->data.gradient.width = meta_draw_spec_new (info->theme, - width, NULL); - info->op->data.gradient.height = meta_draw_spec_new (info->theme, - height, NULL); - - info->op->data.gradient.gradient_spec = meta_gradient_spec_new (type_val); - - info->op->data.gradient.alpha_spec = alpha_spec; - - push_state (info, STATE_GRADIENT); - - /* op gets appended on close tag */ - } - else if (ELEMENT_IS ("image")) - { - MetaDrawOp *op; - const char *filename; - const char *x; - const char *y; - const char *width; - const char *height; - const char *alpha; - const char *colorize; - const char *fill_type; - MetaAlphaGradientSpec *alpha_spec; - GdkPixbuf *pixbuf; - MetaColorSpec *colorize_spec = NULL; - MetaImageFillType fill_type_val; - int h, w, c; - int pixbuf_width, pixbuf_height, pixbuf_n_channels, pixbuf_rowstride; - guchar *pixbuf_pixels; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "alpha", &alpha, "!filename", &filename, - "colorize", &colorize, - "fill_type", &fill_type, - NULL)) - return; - -#if 0 - if (!check_expression (x, TRUE, info->theme, context, error)) - return; - - if (!check_expression (y, TRUE, info->theme, context, error)) - return; - - if (!check_expression (width, TRUE, info->theme, context, error)) - return; - - if (!check_expression (height, TRUE, info->theme, context, error)) - return; -#endif - fill_type_val = META_IMAGE_FILL_SCALE; - if (fill_type) - { - fill_type_val = meta_image_fill_type_from_string (fill_type); - - if (((int) fill_type_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand fill type \"%s\" for <%s> element"), - fill_type, element_name); - } - } - - /* Check last so we don't have to free it when other - * stuff fails. - * - * If it's a theme image, ask for it at 64px, which is - * the largest possible. We scale it anyway. - */ - pixbuf = meta_theme_load_image (info->theme, filename, 64, error); - - if (pixbuf == NULL) - { - add_context_to_error (error, context); - return; - } - - if (colorize) - { - colorize_spec = parse_color (info->theme, colorize, error); - - if (colorize_spec == NULL) - { - add_context_to_error (error, context); - g_object_unref (G_OBJECT (pixbuf)); - return; - } - } - - alpha_spec = NULL; - if (alpha && !parse_alpha (alpha, &alpha_spec, context, error)) - { - g_object_unref (G_OBJECT (pixbuf)); - return; - } - - op = meta_draw_op_new (META_DRAW_IMAGE); - - op->data.image.pixbuf = pixbuf; - op->data.image.colorize_spec = colorize_spec; - - op->data.image.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.image.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.image.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.image.height = meta_draw_spec_new (info->theme, height, NULL); - - op->data.image.alpha_spec = alpha_spec; - op->data.image.fill_type = fill_type_val; - - /* Check for vertical & horizontal stripes */ - pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf); - pixbuf_width = gdk_pixbuf_get_width(pixbuf); - pixbuf_height = gdk_pixbuf_get_height(pixbuf); - pixbuf_rowstride = gdk_pixbuf_get_rowstride(pixbuf); - pixbuf_pixels = gdk_pixbuf_get_pixels(pixbuf); - - /* Check for horizontal stripes */ - for (h = 0; h < pixbuf_height; h++) - { - for (w = 1; w < pixbuf_width; w++) - { - for (c = 0; c < pixbuf_n_channels; c++) - { - if (pixbuf_pixels[(h * pixbuf_rowstride) + c] != - pixbuf_pixels[(h * pixbuf_rowstride) + w + c]) - break; - } - if (c < pixbuf_n_channels) - break; - } - if (w < pixbuf_width) - break; - } - - if (h >= pixbuf_height) - { - op->data.image.horizontal_stripes = TRUE; - } - else - { - op->data.image.horizontal_stripes = FALSE; - } - - /* Check for vertical stripes */ - for (w = 0; w < pixbuf_width; w++) - { - for (h = 1; h < pixbuf_height; h++) - { - for (c = 0; c < pixbuf_n_channels; c++) - { - if (pixbuf_pixels[w + c] != - pixbuf_pixels[(h * pixbuf_rowstride) + w + c]) - break; - } - if (c < pixbuf_n_channels) - break; - } - if (h < pixbuf_height) - break; - } - - if (w >= pixbuf_width) - { - op->data.image.vertical_stripes = TRUE; - } - else - { - op->data.image.vertical_stripes = FALSE; - } - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_IMAGE); - } - else if (ELEMENT_IS ("gtk_arrow")) - { - MetaDrawOp *op; - const char *state; - const char *shadow; - const char *arrow; - const char *x; - const char *y; - const char *width; - const char *height; - const char *filled; - gboolean filled_val; - GtkStateType state_val; - GtkShadowType shadow_val; - GtkArrowType arrow_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!state", &state, - "!shadow", &shadow, - "!arrow", &arrow, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "filled", &filled, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - filled_val = TRUE; - if (filled && !parse_boolean (filled, &filled_val, context, error)) - return; - - state_val = meta_gtk_state_from_string (state); - if (((int) state_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand state \"%s\" for <%s> element"), - state, element_name); - return; - } - - shadow_val = meta_gtk_shadow_from_string (shadow); - if (((int) shadow_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand shadow \"%s\" for <%s> element"), - shadow, element_name); - return; - } - - arrow_val = meta_gtk_arrow_from_string (arrow); - if (((int) arrow_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand arrow \"%s\" for <%s> element"), - arrow, element_name); - return; - } - - op = meta_draw_op_new (META_DRAW_GTK_ARROW); - - op->data.gtk_arrow.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_arrow.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.gtk_arrow.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.gtk_arrow.height = meta_draw_spec_new (info->theme, - height, NULL); - - op->data.gtk_arrow.filled = filled_val; - op->data.gtk_arrow.state = state_val; - op->data.gtk_arrow.shadow = shadow_val; - op->data.gtk_arrow.arrow = arrow_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_GTK_ARROW); - } - else if (ELEMENT_IS ("gtk_box")) - { - MetaDrawOp *op; - const char *state; - const char *shadow; - const char *x; - const char *y; - const char *width; - const char *height; - GtkStateType state_val; - GtkShadowType shadow_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!state", &state, - "!shadow", &shadow, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - state_val = meta_gtk_state_from_string (state); - if (((int) state_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand state \"%s\" for <%s> element"), - state, element_name); - return; - } - - shadow_val = meta_gtk_shadow_from_string (shadow); - if (((int) shadow_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand shadow \"%s\" for <%s> element"), - shadow, element_name); - return; - } - - op = meta_draw_op_new (META_DRAW_GTK_BOX); - - op->data.gtk_box.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_box.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.gtk_box.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.gtk_box.height = meta_draw_spec_new (info->theme, height, NULL); - - op->data.gtk_box.state = state_val; - op->data.gtk_box.shadow = shadow_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_GTK_BOX); - } - else if (ELEMENT_IS ("gtk_vline")) - { - MetaDrawOp *op; - const char *state; - const char *x; - const char *y1; - const char *y2; - GtkStateType state_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!state", &state, - "!x", &x, "!y1", &y1, "!y2", &y2, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y1, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y2, FALSE, info->theme, context, error)) - return; -#endif - - state_val = meta_gtk_state_from_string (state); - if (((int) state_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand state \"%s\" for <%s> element"), - state, element_name); - return; - } - - op = meta_draw_op_new (META_DRAW_GTK_VLINE); - - op->data.gtk_vline.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_vline.y1 = meta_draw_spec_new (info->theme, y1, NULL); - op->data.gtk_vline.y2 = meta_draw_spec_new (info->theme, y2, NULL); - - op->data.gtk_vline.state = state_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_GTK_VLINE); - } - else if (ELEMENT_IS ("icon")) - { - MetaDrawOp *op; - const char *x; - const char *y; - const char *width; - const char *height; - const char *alpha; - const char *fill_type; - MetaAlphaGradientSpec *alpha_spec; - MetaImageFillType fill_type_val; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!x", &x, "!y", &y, - "!width", &width, "!height", &height, - "alpha", &alpha, - "fill_type", &fill_type, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; - - if (!check_expression (width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - fill_type_val = META_IMAGE_FILL_SCALE; - if (fill_type) - { - fill_type_val = meta_image_fill_type_from_string (fill_type); - - if (((int) fill_type_val) == -1) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Did not understand fill type \"%s\" for <%s> element"), - fill_type, element_name); - } - } - - alpha_spec = NULL; - if (alpha && !parse_alpha (alpha, &alpha_spec, context, error)) - return; - - op = meta_draw_op_new (META_DRAW_ICON); - - op->data.icon.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.icon.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.icon.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.icon.height = meta_draw_spec_new (info->theme, height, NULL); - - op->data.icon.alpha_spec = alpha_spec; - op->data.icon.fill_type = fill_type_val; - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_ICON); - } - else if (ELEMENT_IS ("title")) - { - MetaDrawOp *op; - const char *color; - const char *x; - const char *y; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!color", &color, - "!x", &x, "!y", &y, - NULL)) - return; - -#if 0 - if (!check_expression (x, FALSE, info->theme, context, error)) - return; - - if (!check_expression (y, FALSE, info->theme, context, error)) - return; -#endif - - /* Check last so we don't have to free it when other - * stuff fails - */ - color_spec = parse_color (info->theme, color, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - op = meta_draw_op_new (META_DRAW_TITLE); - - op->data.title.color_spec = color_spec; - - op->data.title.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.title.y = meta_draw_spec_new (info->theme, y, NULL); - - g_assert (info->op_list); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_TITLE); - } - else if (ELEMENT_IS ("include")) - { - MetaDrawOp *op; - const char *name; - const char *x; - const char *y; - const char *width; - const char *height; - MetaDrawOpList *op_list; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "x", &x, "y", &y, - "width", &width, "height", &height, - "!name", &name, - NULL)) - return; - - /* x/y/width/height default to 0,0,width,height - should - * probably do this for all the draw ops - */ -#if 0 - if (x && !check_expression (x, FALSE, info->theme, context, error)) - return; - - if (y && !check_expression (y, FALSE, info->theme, context, error)) - return; - - if (width && !check_expression (width, FALSE, info->theme, context, error)) - return; - - if (height && !check_expression (height, FALSE, info->theme, context, error)) - return; -#endif - - op_list = meta_theme_lookup_draw_op_list (info->theme, - name); - if (op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("No <draw_ops> called \"%s\" has been defined"), - name); - return; - } - - g_assert (info->op_list); - - if (op_list == info->op_list || - meta_draw_op_list_contains (op_list, info->op_list)) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Including draw_ops \"%s\" here would create a circular reference"), - name); - return; - } - - op = meta_draw_op_new (META_DRAW_OP_LIST); - - meta_draw_op_list_ref (op_list); - op->data.op_list.op_list = op_list; - - op->data.op_list.x = meta_draw_spec_new (info->theme, x ? x : "0", NULL); - op->data.op_list.y = meta_draw_spec_new (info->theme, y ? y : "0", NULL); - op->data.op_list.width = meta_draw_spec_new (info->theme, - width ? width : "width", - NULL); - op->data.op_list.height = meta_draw_spec_new (info->theme, - height ? height : "height", - NULL); - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_INCLUDE); - } - else if (ELEMENT_IS ("tile")) - { - MetaDrawOp *op; - const char *name; - const char *x; - const char *y; - const char *width; - const char *height; - const char *tile_xoffset; - const char *tile_yoffset; - const char *tile_width; - const char *tile_height; - MetaDrawOpList *op_list; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "x", &x, "y", &y, - "width", &width, "height", &height, - "!name", &name, - "tile_xoffset", &tile_xoffset, - "tile_yoffset", &tile_yoffset, - "!tile_width", &tile_width, - "!tile_height", &tile_height, - NULL)) - return; - - /* These default to 0 */ -#if 0 - if (tile_xoffset && !check_expression (tile_xoffset, FALSE, info->theme, context, error)) - return; - - if (tile_yoffset && !check_expression (tile_yoffset, FALSE, info->theme, context, error)) - return; - - /* x/y/width/height default to 0,0,width,height - should - * probably do this for all the draw ops - */ - if (x && !check_expression (x, FALSE, info->theme, context, error)) - return; - - if (y && !check_expression (y, FALSE, info->theme, context, error)) - return; - - if (width && !check_expression (width, FALSE, info->theme, context, error)) - return; - - if (height && !check_expression (height, FALSE, info->theme, context, error)) - return; - - if (!check_expression (tile_width, FALSE, info->theme, context, error)) - return; - - if (!check_expression (tile_height, FALSE, info->theme, context, error)) - return; -#endif - op_list = meta_theme_lookup_draw_op_list (info->theme, - name); - if (op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("No <draw_ops> called \"%s\" has been defined"), - name); - return; - } - - g_assert (info->op_list); - - if (op_list == info->op_list || - meta_draw_op_list_contains (op_list, info->op_list)) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("Including draw_ops \"%s\" here would create a circular reference"), - name); - return; - } - - op = meta_draw_op_new (META_DRAW_TILE); - - meta_draw_op_list_ref (op_list); - - op->data.tile.x = meta_draw_spec_new (info->theme, x ? x : "0", NULL); - op->data.tile.y = meta_draw_spec_new (info->theme, y ? y : "0", NULL); - op->data.tile.width = meta_draw_spec_new (info->theme, - width ? width : "width", - NULL); - op->data.tile.height = meta_draw_spec_new (info->theme, - height ? height : "height", - NULL); - op->data.tile.tile_xoffset = meta_draw_spec_new (info->theme, - tile_xoffset ? tile_xoffset : "0", - NULL); - op->data.tile.tile_yoffset = meta_draw_spec_new (info->theme, - tile_yoffset ? tile_yoffset : "0", - NULL); - op->data.tile.tile_width = meta_draw_spec_new (info->theme, tile_width, NULL); - op->data.tile.tile_height = meta_draw_spec_new (info->theme, tile_height, NULL); - - op->data.tile.op_list = op_list; - - meta_draw_op_list_append (info->op_list, op); - - push_state (info, STATE_TILE); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "draw_ops"); - } -} - -static void -parse_gradient_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_GRADIENT); - - if (ELEMENT_IS ("color")) - { - const char *value = NULL; - MetaColorSpec *color_spec; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!value", &value, - NULL)) - return; - - color_spec = parse_color (info->theme, value, error); - if (color_spec == NULL) - { - add_context_to_error (error, context); - return; - } - - g_assert (info->op); - g_assert (info->op->type == META_DRAW_GRADIENT); - g_assert (info->op->data.gradient.gradient_spec != NULL); - info->op->data.gradient.gradient_spec->color_specs = - g_slist_append (info->op->data.gradient.gradient_spec->color_specs, - color_spec); - - push_state (info, STATE_COLOR); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "gradient"); - } -} - -static void -parse_style_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_FRAME_STYLE); - - g_assert (info->style); - - if (ELEMENT_IS ("piece")) - { - const char *position = NULL; - const char *draw_ops = NULL; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!position", &position, - "draw_ops", &draw_ops, - NULL)) - return; - - info->piece = meta_frame_piece_from_string (position); - if (info->piece == META_FRAME_PIECE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown position \"%s\" for frame piece"), - position); - return; - } - - if (info->style->pieces[info->piece] != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Frame style already has a piece at position %s"), - position); - return; - } - - g_assert (info->op_list == NULL); - - if (draw_ops) - { - MetaDrawOpList *op_list; - - op_list = meta_theme_lookup_draw_op_list (info->theme, - draw_ops); - - if (op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No <draw_ops> with the name \"%s\" has been defined"), - draw_ops); - return; - } - - meta_draw_op_list_ref (op_list); - info->op_list = op_list; - } - - push_state (info, STATE_PIECE); - } - else if (ELEMENT_IS ("button")) - { - const char *function = NULL; - const char *state = NULL; - const char *draw_ops = NULL; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!function", &function, - "!state", &state, - "draw_ops", &draw_ops, - NULL)) - return; - - info->button_type = meta_button_type_from_string (function, info->theme); - if (info->button_type == META_BUTTON_TYPE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown function \"%s\" for button"), - function); - return; - } - - if (meta_theme_earliest_version_with_button (info->button_type) > - info->theme->format_version) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Button function \"%s\" does not exist in this version (%d, need %d)"), - function, - info->theme->format_version, - meta_theme_earliest_version_with_button (info->button_type) - ); - return; - } - - info->button_state = meta_button_state_from_string (state); - if (info->button_state == META_BUTTON_STATE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Unknown state \"%s\" for button"), - state); - return; - } - - if (info->style->buttons[info->button_type][info->button_state] != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Frame style already has a button for function %s state %s"), - function, state); - return; - } - - g_assert (info->op_list == NULL); - - if (draw_ops) - { - MetaDrawOpList *op_list; - - op_list = meta_theme_lookup_draw_op_list (info->theme, - draw_ops); - - if (op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No <draw_ops> with the name \"%s\" has been defined"), - draw_ops); - return; - } - - meta_draw_op_list_ref (op_list); - info->op_list = op_list; - } - - push_state (info, STATE_BUTTON); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "frame_style"); - } -} - -static void -parse_style_set_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_FRAME_STYLE_SET); - - if (ELEMENT_IS ("frame")) - { - const char *focus = NULL; - const char *state = NULL; - const char *resize = NULL; - const char *style = NULL; - MetaFrameFocus frame_focus; - MetaFrameState frame_state; - MetaFrameResize frame_resize; - MetaFrameStyle *frame_style; - - if (!locate_attributes (context, element_name, attribute_names, attribute_values, - error, - "!focus", &focus, - "!state", &state, - "resize", &resize, - "!style", &style, - NULL)) - return; - - frame_focus = meta_frame_focus_from_string (focus); - if (frame_focus == META_FRAME_FOCUS_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("\"%s\" is not a valid value for focus attribute"), - focus); - return; - } - - frame_state = meta_frame_state_from_string (state); - if (frame_state == META_FRAME_STATE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("\"%s\" is not a valid value for state attribute"), - focus); - return; - } - - frame_style = meta_theme_lookup_style (info->theme, style); - - if (frame_style == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("A style called \"%s\" has not been defined"), - style); - return; - } - - switch (frame_state) - { - case META_FRAME_STATE_NORMAL: - if (resize == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - ATTRIBUTE_NOT_FOUND, - "resize", element_name); - return; - } - - - frame_resize = meta_frame_resize_from_string (resize); - if (frame_resize == META_FRAME_RESIZE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("\"%s\" is not a valid value for resize attribute"), - focus); - return; - } - - break; - - case META_FRAME_STATE_SHADED: - if (META_THEME_ALLOWS (info->theme, META_THEME_UNRESIZABLE_SHADED_STYLES)) - { - if (resize == NULL) - /* In state="normal" we would complain here. But instead we accept - * not having a resize attribute and default to resize="both", since - * that most closely mimics what we did in v1, and thus people can - * upgrade a theme to v2 without as much hassle. - */ - frame_resize = META_FRAME_RESIZE_BOTH; - else - { - frame_resize = meta_frame_resize_from_string (resize); - if (frame_resize == META_FRAME_RESIZE_LAST) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("\"%s\" is not a valid value for resize attribute"), - focus); - return; - } - } - } - else /* v1 theme */ - { - if (resize != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Should not have \"resize\" attribute on <%s> element for maximized/shaded states"), - element_name); - return; - } - - /* resize="both" is equivalent to the old behaviour */ - frame_resize = META_FRAME_RESIZE_BOTH; - } - break; - - default: - if (resize != NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Should not have \"resize\" attribute on <%s> element for maximized states"), - element_name); - return; - } - - frame_resize = META_FRAME_RESIZE_LAST; - } - - switch (frame_state) - { - case META_FRAME_STATE_NORMAL: - if (info->style_set->normal_styles[frame_resize][frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s resize %s focus %s"), - state, resize, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->normal_styles[frame_resize][frame_focus] = frame_style; - break; - case META_FRAME_STATE_MAXIMIZED: - if (info->style_set->maximized_styles[frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s focus %s"), - state, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->maximized_styles[frame_focus] = frame_style; - break; - case META_FRAME_STATE_SHADED: - if (info->style_set->shaded_styles[frame_resize][frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s resize %s focus %s"), - state, resize, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->shaded_styles[frame_resize][frame_focus] = frame_style; - break; - case META_FRAME_STATE_MAXIMIZED_AND_SHADED: - if (info->style_set->maximized_and_shaded_styles[frame_focus]) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Style has already been specified for state %s focus %s"), - state, focus); - return; - } - meta_frame_style_ref (frame_style); - info->style_set->maximized_and_shaded_styles[frame_focus] = frame_style; - break; - case META_FRAME_STATE_LAST: - g_assert_not_reached (); - break; - } - - push_state (info, STATE_FRAME); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "frame_style_set"); - } -} - -static void -parse_piece_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_PIECE); - - if (ELEMENT_IS ("draw_ops")) - { - if (info->op_list) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Can't have a two draw_ops for a <piece> element (theme specified a draw_ops attribute and also a <draw_ops> element, or specified two elements)")); - return; - } - - if (!check_no_attributes (context, element_name, attribute_names, attribute_values, - error)) - return; - - g_assert (info->op_list == NULL); - info->op_list = meta_draw_op_list_new (2); - - push_state (info, STATE_DRAW_OPS); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "piece"); - } -} - -static void -parse_button_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_BUTTON); - - if (ELEMENT_IS ("draw_ops")) - { - if (info->op_list) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Can't have a two draw_ops for a <button> element (theme specified a draw_ops attribute and also a <draw_ops> element, or specified two elements)")); - return; - } - - if (!check_no_attributes (context, element_name, attribute_names, attribute_values, - error)) - return; - - g_assert (info->op_list == NULL); - info->op_list = meta_draw_op_list_new (2); - - push_state (info, STATE_DRAW_OPS); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "button"); - } -} - -static void -parse_menu_icon_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - ParseInfo *info, - GError **error) -{ - g_return_if_fail (peek_state (info) == STATE_MENU_ICON); - - if (ELEMENT_IS ("draw_ops")) - { - if (info->op_list) - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Can't have a two draw_ops for a <menu_icon> element (theme specified a draw_ops attribute and also a <draw_ops> element, or specified two elements)")); - return; - } - - if (!check_no_attributes (context, element_name, attribute_names, attribute_values, - error)) - return; - - g_assert (info->op_list == NULL); - info->op_list = meta_draw_op_list_new (2); - - push_state (info, STATE_DRAW_OPS); - } - else - { - set_error (error, context, - G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed below <%s>"), - element_name, "menu_icon"); - } -} - - -static void -start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ParseInfo *info = user_data; - - switch (peek_state (info)) - { - case STATE_START: - if (strcmp (element_name, "metacity_theme") == 0) - { - info->theme = meta_theme_new (); - info->theme->name = g_strdup (info->theme_name); - info->theme->filename = g_strdup (info->theme_file); - info->theme->dirname = g_strdup (info->theme_dir); - info->theme->format_version = info->format_version; - - push_state (info, STATE_THEME); - } - else - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Outermost element in theme must be <metacity_theme> not <%s>"), - element_name); - break; - - case STATE_THEME: - parse_toplevel_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_INFO: - parse_info_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_NAME: - case STATE_AUTHOR: - case STATE_COPYRIGHT: - case STATE_DATE: - case STATE_DESCRIPTION: - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed inside a name/author/date/description element"), - element_name); - break; - case STATE_CONSTANT: - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed inside a <constant> element"), - element_name); - break; - case STATE_FRAME_GEOMETRY: - parse_geometry_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_DISTANCE: - case STATE_BORDER: - case STATE_ASPECT_RATIO: - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed inside a distance/border/aspect_ratio element"), - element_name); - break; - case STATE_DRAW_OPS: - parse_draw_op_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_LINE: - case STATE_RECTANGLE: - case STATE_ARC: - case STATE_CLIP: - case STATE_TINT: - case STATE_IMAGE: - case STATE_GTK_ARROW: - case STATE_GTK_BOX: - case STATE_GTK_VLINE: - case STATE_ICON: - case STATE_TITLE: - case STATE_INCLUDE: - case STATE_TILE: - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed inside a draw operation element"), - element_name); - break; - case STATE_GRADIENT: - parse_gradient_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_COLOR: - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed inside a <%s> element"), - element_name, "color"); - break; - case STATE_FRAME_STYLE: - parse_style_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_PIECE: - parse_piece_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_BUTTON: - parse_button_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_MENU_ICON: - parse_menu_icon_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_FRAME_STYLE_SET: - parse_style_set_element (context, element_name, - attribute_names, attribute_values, - info, error); - break; - case STATE_FRAME: - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed inside a <%s> element"), - element_name, "frame"); - break; - case STATE_WINDOW: - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed inside a <%s> element"), - element_name, "window"); - break; - case STATE_FALLBACK: - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Element <%s> is not allowed inside a <%s> element"), - element_name, "fallback"); - break; - } -} - -static void -end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ParseInfo *info = user_data; - - switch (peek_state (info)) - { - case STATE_START: - break; - case STATE_THEME: - g_assert (info->theme); - - if (!meta_theme_validate (info->theme, error)) - { - add_context_to_error (error, context); - meta_theme_free (info->theme); - info->theme = NULL; - } - - pop_state (info); - g_assert (peek_state (info) == STATE_START); - break; - case STATE_INFO: - pop_state (info); - g_assert (peek_state (info) == STATE_THEME); - break; - case STATE_NAME: - pop_state (info); - g_assert (peek_state (info) == STATE_INFO); - break; - case STATE_AUTHOR: - pop_state (info); - g_assert (peek_state (info) == STATE_INFO); - break; - case STATE_COPYRIGHT: - pop_state (info); - g_assert (peek_state (info) == STATE_INFO); - break; - case STATE_DATE: - pop_state (info); - g_assert (peek_state (info) == STATE_INFO); - break; - case STATE_DESCRIPTION: - pop_state (info); - g_assert (peek_state (info) == STATE_INFO); - break; - case STATE_CONSTANT: - pop_state (info); - g_assert (peek_state (info) == STATE_THEME); - break; - case STATE_FRAME_GEOMETRY: - g_assert (info->layout); - - if (!meta_frame_layout_validate (info->layout, - error)) - { - add_context_to_error (error, context); - } - - /* layout will already be stored in the theme under - * its name - */ - meta_frame_layout_unref (info->layout); - info->layout = NULL; - pop_state (info); - g_assert (peek_state (info) == STATE_THEME); - break; - case STATE_DISTANCE: - pop_state (info); - g_assert (peek_state (info) == STATE_FRAME_GEOMETRY); - break; - case STATE_BORDER: - pop_state (info); - g_assert (peek_state (info) == STATE_FRAME_GEOMETRY); - break; - case STATE_ASPECT_RATIO: - pop_state (info); - g_assert (peek_state (info) == STATE_FRAME_GEOMETRY); - break; - case STATE_DRAW_OPS: - { - g_assert (info->op_list); - - if (!meta_draw_op_list_validate (info->op_list, - error)) - { - add_context_to_error (error, context); - meta_draw_op_list_unref (info->op_list); - info->op_list = NULL; - } - - pop_state (info); - - switch (peek_state (info)) - { - case STATE_BUTTON: - case STATE_PIECE: - case STATE_MENU_ICON: - /* Leave info->op_list to be picked up - * when these elements are closed - */ - g_assert (info->op_list); - break; - case STATE_THEME: - g_assert (info->op_list); - meta_draw_op_list_unref (info->op_list); - info->op_list = NULL; - break; - default: - /* Op list can't occur in other contexts */ - g_assert_not_reached (); - break; - } - } - break; - case STATE_LINE: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_RECTANGLE: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_ARC: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_CLIP: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_TINT: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_GRADIENT: - g_assert (info->op); - g_assert (info->op->type == META_DRAW_GRADIENT); - if (!meta_gradient_spec_validate (info->op->data.gradient.gradient_spec, - error)) - { - add_context_to_error (error, context); - meta_draw_op_free (info->op); - info->op = NULL; - } - else - { - g_assert (info->op_list); - meta_draw_op_list_append (info->op_list, info->op); - info->op = NULL; - } - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_IMAGE: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_GTK_ARROW: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_GTK_BOX: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_GTK_VLINE: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_ICON: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_TITLE: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_INCLUDE: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_TILE: - pop_state (info); - g_assert (peek_state (info) == STATE_DRAW_OPS); - break; - case STATE_COLOR: - pop_state (info); - g_assert (peek_state (info) == STATE_GRADIENT); - break; - case STATE_FRAME_STYLE: - g_assert (info->style); - - if (!meta_frame_style_validate (info->style, - info->theme->format_version, - error)) - { - add_context_to_error (error, context); - } - - /* Frame style is in the theme hash table and a ref - * is held there - */ - meta_frame_style_unref (info->style); - info->style = NULL; - pop_state (info); - g_assert (peek_state (info) == STATE_THEME); - break; - case STATE_PIECE: - g_assert (info->style); - if (info->op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No draw_ops provided for frame piece")); - } - else - { - info->style->pieces[info->piece] = info->op_list; - info->op_list = NULL; - } - pop_state (info); - g_assert (peek_state (info) == STATE_FRAME_STYLE); - break; - case STATE_BUTTON: - g_assert (info->style); - if (info->op_list == NULL) - { - set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("No draw_ops provided for button")); - } - else - { - info->style->buttons[info->button_type][info->button_state] = - info->op_list; - info->op_list = NULL; - } - pop_state (info); - break; - case STATE_MENU_ICON: - g_assert (info->theme); - if (info->op_list != NULL) - { - meta_draw_op_list_unref (info->op_list); - info->op_list = NULL; - } - pop_state (info); - g_assert (peek_state (info) == STATE_THEME); - break; - case STATE_FRAME_STYLE_SET: - g_assert (info->style_set); - - if (!meta_frame_style_set_validate (info->style_set, - error)) - { - add_context_to_error (error, context); - } - - /* Style set is in the theme hash table and a reference - * is held there. - */ - meta_frame_style_set_unref (info->style_set); - info->style_set = NULL; - pop_state (info); - g_assert (peek_state (info) == STATE_THEME); - break; - case STATE_FRAME: - pop_state (info); - g_assert (peek_state (info) == STATE_FRAME_STYLE_SET); - break; - case STATE_WINDOW: - pop_state (info); - g_assert (peek_state (info) == STATE_THEME); - break; - case STATE_FALLBACK: - pop_state (info); - g_assert (peek_state (info) == STATE_THEME); - break; - } -} - -#define NO_TEXT(element_name) set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, _("No text is allowed inside element <%s>"), element_name) - -static gboolean -all_whitespace (const char *text, - int text_len) -{ - const char *p; - const char *end; - - p = text; - end = text + text_len; - - while (p != end) - { - if (!g_ascii_isspace (*p)) - return FALSE; - - p = g_utf8_next_char (p); - } - - return TRUE; -} - -static void -text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ParseInfo *info = user_data; - - if (all_whitespace (text, text_len)) - return; - - /* FIXME http://bugzilla.gnome.org/show_bug.cgi?id=70448 would - * allow a nice cleanup here. - */ - - switch (peek_state (info)) - { - case STATE_START: - g_assert_not_reached (); /* gmarkup shouldn't do this */ - break; - case STATE_THEME: - NO_TEXT ("metacity_theme"); - break; - case STATE_INFO: - NO_TEXT ("info"); - break; - case STATE_NAME: - if (info->theme->readable_name != NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("<name> specified twice for this theme")); - return; - } - - info->theme->readable_name = g_strndup (text, text_len); - break; - case STATE_AUTHOR: - if (info->theme->author != NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("<author> specified twice for this theme")); - return; - } - - info->theme->author = g_strndup (text, text_len); - break; - case STATE_COPYRIGHT: - if (info->theme->copyright != NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("<copyright> specified twice for this theme")); - return; - } - - info->theme->copyright = g_strndup (text, text_len); - break; - case STATE_DATE: - if (info->theme->date != NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("<date> specified twice for this theme")); - return; - } - - info->theme->date = g_strndup (text, text_len); - break; - case STATE_DESCRIPTION: - if (info->theme->description != NULL) - { - set_error (error, context, G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - _("<description> specified twice for this theme")); - return; - } - - info->theme->description = g_strndup (text, text_len); - break; - case STATE_CONSTANT: - NO_TEXT ("constant"); - break; - case STATE_FRAME_GEOMETRY: - NO_TEXT ("frame_geometry"); - break; - case STATE_DISTANCE: - NO_TEXT ("distance"); - break; - case STATE_BORDER: - NO_TEXT ("border"); - break; - case STATE_ASPECT_RATIO: - NO_TEXT ("aspect_ratio"); - break; - case STATE_DRAW_OPS: - NO_TEXT ("draw_ops"); - break; - case STATE_LINE: - NO_TEXT ("line"); - break; - case STATE_RECTANGLE: - NO_TEXT ("rectangle"); - break; - case STATE_ARC: - NO_TEXT ("arc"); - break; - case STATE_CLIP: - NO_TEXT ("clip"); - break; - case STATE_TINT: - NO_TEXT ("tint"); - break; - case STATE_GRADIENT: - NO_TEXT ("gradient"); - break; - case STATE_IMAGE: - NO_TEXT ("image"); - break; - case STATE_GTK_ARROW: - NO_TEXT ("gtk_arrow"); - break; - case STATE_GTK_BOX: - NO_TEXT ("gtk_box"); - break; - case STATE_GTK_VLINE: - NO_TEXT ("gtk_vline"); - break; - case STATE_ICON: - NO_TEXT ("icon"); - break; - case STATE_TITLE: - NO_TEXT ("title"); - break; - case STATE_INCLUDE: - NO_TEXT ("include"); - break; - case STATE_TILE: - NO_TEXT ("tile"); - break; - case STATE_COLOR: - NO_TEXT ("color"); - break; - case STATE_FRAME_STYLE: - NO_TEXT ("frame_style"); - break; - case STATE_PIECE: - NO_TEXT ("piece"); - break; - case STATE_BUTTON: - NO_TEXT ("button"); - break; - case STATE_MENU_ICON: - NO_TEXT ("menu_icon"); - break; - case STATE_FRAME_STYLE_SET: - NO_TEXT ("frame_style_set"); - break; - case STATE_FRAME: - NO_TEXT ("frame"); - break; - case STATE_WINDOW: - NO_TEXT ("window"); - break; - case STATE_FALLBACK: - NO_TEXT ("fallback"); - break; - } -} - -/* We were intending to put the version number - * in the subdirectory name, but we ended up - * using the filename instead. The "-1" survives - * as a fossil. - */ -#define THEME_SUBDIR "metacity-1" - -/* Highest version of the theme format to - * look out for. - */ -#define THEME_VERSION 2 - -#define METACITY_THEME_FILENAME_FORMAT "metacity-theme-%d.xml" - -MetaTheme* -meta_theme_load (const char *theme_name, - GError **err) -{ - GMarkupParseContext *context; - GError *error; - ParseInfo info; - char *text; - gsize length; - char *theme_file; - char *theme_dir; - MetaTheme *retval; - guint version; - const gchar* const* xdg_data_dirs; - int i; - - text = NULL; - length = 0; - retval = NULL; - context = NULL; - - theme_dir = NULL; - theme_file = NULL; - - if (meta_is_debugging ()) - { - gchar *theme_filename = g_strdup_printf (METACITY_THEME_FILENAME_FORMAT, - THEME_VERSION); - - /* Try in themes in our source tree */ - theme_dir = g_build_filename ("./themes", theme_name, NULL); - - theme_file = g_build_filename (theme_dir, - theme_filename, - NULL); - - error = NULL; - if (!g_file_get_contents (theme_file, - &text, - &length, - &error)) - { - meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n", - theme_file, error->message); - g_error_free (error); - g_free (theme_dir); - g_free (theme_file); - theme_file = NULL; - } - version = THEME_VERSION; - - g_free (theme_filename); - } - - /* We try all supported versions from current to oldest */ - for (version = THEME_VERSION; (version > 0) && (text == NULL); version--) - { - gchar *theme_filename = g_strdup_printf (METACITY_THEME_FILENAME_FORMAT, - version); - - /* We try first in home dir, XDG_DATA_DIRS, then system dir for themes */ - - /* Try home dir for themes */ - theme_dir = g_build_filename (g_get_home_dir (), - ".themes", - theme_name, - THEME_SUBDIR, - NULL); - - theme_file = g_build_filename (theme_dir, - theme_filename, - NULL); - - error = NULL; - if (!g_file_get_contents (theme_file, - &text, - &length, - &error)) - { - meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n", - theme_file, error->message); - g_error_free (error); - g_free (theme_dir); - g_free (theme_file); - theme_file = NULL; - } - - /* Try each XDG_DATA_DIRS for theme */ - xdg_data_dirs = g_get_system_data_dirs(); - for(i = 0; xdg_data_dirs[i] != NULL; i++) - { - if (text == NULL) - { - theme_dir = g_build_filename (xdg_data_dirs[i], - "themes", - theme_name, - THEME_SUBDIR, - NULL); - - theme_file = g_build_filename (theme_dir, - theme_filename, - NULL); - - error = NULL; - if (!g_file_get_contents (theme_file, - &text, - &length, - &error)) - { - meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n", - theme_file, error->message); - g_error_free (error); - g_free (theme_dir); - g_free (theme_file); - theme_file = NULL; - } - else - { - break; - } - } - } - - /* Look for themes in METACITY_DATADIR */ - if (text == NULL) - { - theme_dir = g_build_filename (METACITY_DATADIR, - "themes", - theme_name, - THEME_SUBDIR, - NULL); - - theme_file = g_build_filename (theme_dir, - theme_filename, - NULL); - - error = NULL; - if (!g_file_get_contents (theme_file, - &text, - &length, - &error)) - { - meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n", - theme_file, error->message); - g_error_free (error); - g_free (theme_dir); - g_free (theme_file); - theme_file = NULL; - } - } - - g_free (theme_filename); - } - - if (text == NULL) - { - g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("Failed to find a valid file for theme %s\n"), - theme_name); - - return NULL; /* all fallbacks failed */ - } - - meta_topic (META_DEBUG_THEMES, "Parsing theme file %s\n", theme_file); - - - parse_info_init (&info); - info.theme_name = theme_name; - - /* pass ownership to info so we free it with the info */ - info.theme_file = theme_file; - info.theme_dir = theme_dir; - - info.format_version = version + 1; - - context = g_markup_parse_context_new (&metacity_theme_parser, - 0, &info, NULL); - - error = NULL; - if (!g_markup_parse_context_parse (context, - text, - length, - &error)) - goto out; - - error = NULL; - if (!g_markup_parse_context_end_parse (context, &error)) - goto out; - - goto out; - - out: - - if (context) - g_markup_parse_context_free (context); - g_free (text); - - if (info.theme) - info.theme->format_version = info.format_version; - - if (error) - { - g_propagate_error (err, error); - } - else if (info.theme) - { - /* Steal theme from info */ - retval = info.theme; - info.theme = NULL; - } - else - { - g_set_error (err, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, - _("Theme file %s did not contain a root <metacity_theme> element"), - info.theme_file); - } - - parse_info_free (&info); - - return retval; -} diff --git a/src/ui/theme-parser.h b/src/ui/theme-parser.h deleted file mode 100644 index 035d7005..00000000 --- a/src/ui/theme-parser.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme parsing */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "theme.h" - -#ifndef META_THEME_PARSER_H -#define META_THEME_PARSER_H - -MetaTheme* meta_theme_load (const char *theme_name, - GError **err); - -#endif diff --git a/src/ui/theme-viewer.c b/src/ui/theme-viewer.c deleted file mode 100644 index 5787ad4b..00000000 --- a/src/ui/theme-viewer.c +++ /dev/null @@ -1,1336 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme viewer and test app main() */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <config.h> -#include "util.h" -#include "theme.h" -#include "theme-parser.h" -#include "preview-widget.h" -#include <gtk/gtk.h> -#include <time.h> -#include <stdlib.h> -#include <string.h> - -#include <libintl.h> -#define _(x) dgettext (GETTEXT_PACKAGE, x) -#define N_(x) x - -/* We need to compute all different button arrangements - * in terms of button location. We don't care about - * different arrangements in terms of button function. - * - * So if dups are allowed, from 0-4 buttons on the left, from 0-4 on - * the right, 5x5=25 combinations. - * - * If no dups, 0-4 on left determines the number on the right plus - * we have a special case for the "no buttons on either side" case. - */ -#ifndef ALLOW_DUPLICATE_BUTTONS -#define BUTTON_LAYOUT_COMBINATIONS (MAX_BUTTONS_PER_CORNER + 1 + 1) -#else -#define BUTTON_LAYOUT_COMBINATIONS ((MAX_BUTTONS_PER_CORNER+1)*(MAX_BUTTONS_PER_CORNER+1)) -#endif - -enum -{ - FONT_SIZE_SMALL, - FONT_SIZE_NORMAL, - FONT_SIZE_LARGE, - FONT_SIZE_LAST -}; - -static MetaTheme *global_theme = NULL; -static GtkWidget *previews[META_FRAME_TYPE_LAST*FONT_SIZE_LAST + BUTTON_LAYOUT_COMBINATIONS] = { NULL, }; -static double milliseconds_to_draw_frame = 0.0; - -static void run_position_expression_tests (void); -#if 0 -static void run_position_expression_timings (void); -#endif -static void run_theme_benchmark (void); - - -static GtkItemFactoryEntry menu_items[] = -{ - { N_("/_Windows"), NULL, NULL, 0, "<Branch>" }, - { N_("/Windows/tearoff"), NULL, NULL, 0, "<Tearoff>" }, - { N_("/Windows/_Dialog"), "<control>d", NULL, 0, NULL }, - { N_("/Windows/_Modal dialog"), NULL, NULL, 0, NULL }, - { N_("/Windows/_Utility"), "<control>u", NULL, 0, NULL }, - { N_("/Windows/_Splashscreen"), "<control>s", NULL, 0, NULL }, - { N_("/Windows/_Top dock"), NULL, NULL, 0, NULL }, - { N_("/Windows/_Bottom dock"), NULL, NULL, 0, NULL }, - { N_("/Windows/_Left dock"), NULL, NULL, 0, NULL }, - { N_("/Windows/_Right dock"), NULL, NULL, 0, NULL }, - { N_("/Windows/_All docks"), NULL, NULL, 0, NULL }, - { N_("/Windows/Des_ktop"), NULL, NULL, 0, NULL } -}; - -static GtkWidget * -normal_contents (void) -{ - GtkWidget *table; - GtkWidget *toolbar; - GtkWidget *handlebox; - GtkWidget *statusbar; - GtkWidget *contents; - GtkWidget *sw; - GtkItemFactory *item_factory; - - table = gtk_table_new (1, 4, FALSE); - - /* Create the menubar - */ - - item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", NULL); - - gtk_item_factory_set_translate_func(item_factory, - (GtkTranslateFunc)gettext, NULL, NULL); - - /* Set up item factory to go away */ - g_object_ref (item_factory); - gtk_object_sink (GTK_OBJECT (item_factory)); - g_object_set_data_full (G_OBJECT (table), - "<main>", - item_factory, - (GDestroyNotify) g_object_unref); - - /* create menu items */ - gtk_item_factory_create_items (item_factory, G_N_ELEMENTS (menu_items), - menu_items, NULL); - - gtk_table_attach (GTK_TABLE (table), - gtk_item_factory_get_widget (item_factory, "<main>"), - /* X direction */ /* Y direction */ - 0, 1, 0, 1, - GTK_EXPAND | GTK_FILL, 0, - 0, 0); - - /* Create the toolbar - */ - toolbar = gtk_toolbar_new (); - - gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), - GTK_STOCK_NEW, - _("Open another one of these windows"), - NULL, - NULL, NULL, - -1); /* -1 means "append" */ - - gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), - GTK_STOCK_OPEN, - _("This is a demo button with an 'open' icon"), - NULL, - NULL, NULL, - -1); /* -1 means "append" */ - - gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), - GTK_STOCK_QUIT, - _("This is a demo button with a 'quit' icon"), - NULL, - NULL, NULL, - -1); /* -1 means "append" */ - - handlebox = gtk_handle_box_new (); - - gtk_container_add (GTK_CONTAINER (handlebox), toolbar); - - gtk_table_attach (GTK_TABLE (table), - handlebox, - /* X direction */ /* Y direction */ - 0, 1, 1, 2, - GTK_EXPAND | GTK_FILL, 0, - 0, 0); - - /* Create document - */ - - sw = gtk_scrolled_window_new (NULL, NULL); - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), - GTK_SHADOW_IN); - - gtk_table_attach (GTK_TABLE (table), - sw, - /* X direction */ /* Y direction */ - 0, 1, 2, 3, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 0, 0); - - contents = gtk_text_view_new (); - gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (contents), - PANGO_WRAP_WORD); - - gtk_container_add (GTK_CONTAINER (sw), - contents); - - /* Create statusbar */ - - statusbar = gtk_statusbar_new (); - gtk_table_attach (GTK_TABLE (table), - statusbar, - /* X direction */ /* Y direction */ - 0, 1, 3, 4, - GTK_EXPAND | GTK_FILL, 0, - 0, 0); - - gtk_widget_show_all (table); - - return table; -} - -static void -update_spacings (GtkWidget *vbox, - GtkWidget *action_area) -{ - gtk_container_set_border_width (GTK_CONTAINER (vbox), 2); - gtk_box_set_spacing (GTK_BOX (action_area), 10); - gtk_container_set_border_width (GTK_CONTAINER (action_area), 5); -} - -static GtkWidget* -dialog_contents (void) -{ - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *action_area; - GtkWidget *label; - GtkWidget *image; - GtkWidget *button; - - vbox = gtk_vbox_new (FALSE, 0); - - action_area = gtk_hbutton_box_new (); - - gtk_button_box_set_layout (GTK_BUTTON_BOX (action_area), - GTK_BUTTONBOX_END); - - button = gtk_button_new_from_stock (GTK_STOCK_OK); - gtk_box_pack_end (GTK_BOX (action_area), - button, - FALSE, TRUE, 0); - - gtk_box_pack_end (GTK_BOX (vbox), action_area, - FALSE, TRUE, 0); - - update_spacings (vbox, action_area); - - label = gtk_label_new (_("This is a sample message in a sample dialog")); - image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, - GTK_ICON_SIZE_DIALOG); - gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0); - - gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); - gtk_label_set_selectable (GTK_LABEL (label), TRUE); - - hbox = gtk_hbox_new (FALSE, 6); - - gtk_box_pack_start (GTK_BOX (hbox), image, - FALSE, FALSE, 0); - - gtk_box_pack_start (GTK_BOX (hbox), label, - TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (vbox), - hbox, - FALSE, FALSE, 0); - - gtk_widget_show_all (vbox); - - return vbox; -} - -static GtkWidget* -utility_contents (void) -{ - GtkWidget *table; - GtkWidget *button; - int i, j; - - table = gtk_table_new (3, 4, FALSE); - - i = 0; - while (i < 3) - { - j = 0; - while (j < 4) - { - char *str; - - str = g_strdup_printf ("_%c", (char) ('A' + 4*i + j)); - - button = gtk_button_new_with_mnemonic (str); - - g_free (str); - - gtk_table_attach (GTK_TABLE (table), - button, - /* X direction */ /* Y direction */ - i, i+1, j, j+1, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, - 0, 0); - - ++j; - } - - ++i; - } - - gtk_widget_show_all (table); - - return table; -} - -static GtkWidget* -menu_contents (void) -{ - GtkWidget *vbox; - GtkWidget *mi; - int i; - GtkWidget *frame; - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), - GTK_SHADOW_OUT); - - vbox = gtk_vbox_new (FALSE, 0); - - i = 0; - while (i < 10) - { - char *str = g_strdup_printf (_("Fake menu item %d\n"), i + 1); - mi = gtk_label_new (str); - gtk_misc_set_alignment (GTK_MISC (mi), 0.0, 0.5); - g_free (str); - gtk_box_pack_start (GTK_BOX (vbox), mi, FALSE, FALSE, 0); - - ++i; - } - - gtk_container_add (GTK_CONTAINER (frame), vbox); - - gtk_widget_show_all (frame); - - return frame; -} - -static GtkWidget* -border_only_contents (void) -{ - GtkWidget *event_box; - GtkWidget *vbox; - GtkWidget *w; - GdkColor color; - - event_box = gtk_event_box_new (); - - color.red = 40000; - color.green = 0; - color.blue = 40000; - gtk_widget_modify_bg (event_box, GTK_STATE_NORMAL, &color); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 3); - - w = gtk_label_new (_("Border-only window")); - gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); - w = gtk_button_new_with_label (_("Bar")); - gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); - - gtk_container_add (GTK_CONTAINER (event_box), vbox); - - gtk_widget_show_all (event_box); - - return event_box; -} - -static GtkWidget* -get_window_contents (MetaFrameType type, - const char **title) -{ - switch (type) - { - case META_FRAME_TYPE_NORMAL: - *title = _("Normal Application Window"); - return normal_contents (); - - case META_FRAME_TYPE_DIALOG: - *title = _("Dialog Box"); - return dialog_contents (); - - case META_FRAME_TYPE_MODAL_DIALOG: - *title = _("Modal Dialog Box"); - return dialog_contents (); - - case META_FRAME_TYPE_UTILITY: - *title = _("Utility Palette"); - return utility_contents (); - - case META_FRAME_TYPE_MENU: - *title = _("Torn-off Menu"); - return menu_contents (); - - case META_FRAME_TYPE_BORDER: - *title = _("Border"); - return border_only_contents (); - - case META_FRAME_TYPE_LAST: - g_assert_not_reached (); - break; - } - - return NULL; -} - -static MetaFrameFlags -get_window_flags (MetaFrameType type) -{ - MetaFrameFlags flags; - - flags = META_FRAME_ALLOWS_DELETE | - META_FRAME_ALLOWS_MENU | - META_FRAME_ALLOWS_MINIMIZE | - META_FRAME_ALLOWS_MAXIMIZE | - META_FRAME_ALLOWS_VERTICAL_RESIZE | - META_FRAME_ALLOWS_HORIZONTAL_RESIZE | - META_FRAME_HAS_FOCUS | - META_FRAME_ALLOWS_SHADE | - META_FRAME_ALLOWS_MOVE; - - switch (type) - { - case META_FRAME_TYPE_NORMAL: - break; - - case META_FRAME_TYPE_DIALOG: - case META_FRAME_TYPE_MODAL_DIALOG: - flags &= ~(META_FRAME_ALLOWS_MINIMIZE | - META_FRAME_ALLOWS_MAXIMIZE); - break; - - case META_FRAME_TYPE_UTILITY: - flags &= ~(META_FRAME_ALLOWS_MINIMIZE | - META_FRAME_ALLOWS_MAXIMIZE); - break; - - case META_FRAME_TYPE_MENU: - flags &= ~(META_FRAME_ALLOWS_MINIMIZE | - META_FRAME_ALLOWS_MAXIMIZE); - break; - - case META_FRAME_TYPE_BORDER: - break; - - case META_FRAME_TYPE_LAST: - g_assert_not_reached (); - break; - } - - return flags; -} - -static GtkWidget* -preview_collection (int font_size, - PangoFontDescription *base_desc) -{ - GtkWidget *box; - GtkWidget *sw; - GdkColor desktop_color; - int i; - GtkWidget *eventbox; - - sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - box = gtk_vbox_new (FALSE, 0); - gtk_box_set_spacing (GTK_BOX (box), 20); - gtk_container_set_border_width (GTK_CONTAINER (box), 20); - - eventbox = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER (eventbox), box); - - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), eventbox); - - desktop_color.red = 0x5144; - desktop_color.green = 0x75D6; - desktop_color.blue = 0xA699; - - gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &desktop_color); - - i = 0; - while (i < META_FRAME_TYPE_LAST) - { - const char *title = NULL; - GtkWidget *contents; - GtkWidget *align; - double xalign, yalign; - GtkWidget *eventbox2; - GtkWidget *preview; - PangoFontDescription *font_desc; - double scale; - - eventbox2 = gtk_event_box_new (); - - preview = meta_preview_new (); - - gtk_container_add (GTK_CONTAINER (eventbox2), preview); - - meta_preview_set_frame_type (META_PREVIEW (preview), i); - meta_preview_set_frame_flags (META_PREVIEW (preview), - get_window_flags (i)); - - meta_preview_set_theme (META_PREVIEW (preview), global_theme); - - contents = get_window_contents (i, &title); - - meta_preview_set_title (META_PREVIEW (preview), title); - - gtk_container_add (GTK_CONTAINER (preview), contents); - - if (i == META_FRAME_TYPE_MENU) - { - xalign = 0.0; - yalign = 0.0; - } - else - { - xalign = 0.5; - yalign = 0.5; - } - - align = gtk_alignment_new (0.0, 0.0, xalign, yalign); - gtk_container_add (GTK_CONTAINER (align), eventbox2); - - gtk_box_pack_start (GTK_BOX (box), align, TRUE, TRUE, 0); - - switch (font_size) - { - case FONT_SIZE_SMALL: - scale = PANGO_SCALE_XX_SMALL; - break; - case FONT_SIZE_LARGE: - scale = PANGO_SCALE_XX_LARGE; - break; - default: - scale = 1.0; - break; - } - - if (scale != 1.0) - { - font_desc = pango_font_description_new (); - - pango_font_description_set_size (font_desc, - MAX (pango_font_description_get_size (base_desc) * scale, 1)); - - gtk_widget_modify_font (preview, font_desc); - - pango_font_description_free (font_desc); - } - - previews[font_size*META_FRAME_TYPE_LAST + i] = preview; - - ++i; - } - - return sw; -} - -static MetaButtonLayout different_layouts[BUTTON_LAYOUT_COMBINATIONS]; - -static void -init_layouts (void) -{ - int i; - - /* Blank out all the layouts */ - i = 0; - while (i < (int) G_N_ELEMENTS (different_layouts)) - { - int j; - - j = 0; - while (j < MAX_BUTTONS_PER_CORNER) - { - different_layouts[i].left_buttons[j] = META_BUTTON_FUNCTION_LAST; - different_layouts[i].right_buttons[j] = META_BUTTON_FUNCTION_LAST; - ++j; - } - ++i; - } - -#ifndef ALLOW_DUPLICATE_BUTTONS - i = 0; - while (i <= MAX_BUTTONS_PER_CORNER) - { - int j; - - j = 0; - while (j < i) - { - different_layouts[i].right_buttons[j] = (MetaButtonFunction) j; - ++j; - } - while (j < MAX_BUTTONS_PER_CORNER) - { - different_layouts[i].left_buttons[j-i] = (MetaButtonFunction) j; - ++j; - } - - ++i; - } - - /* Special extra case for no buttons on either side */ - different_layouts[i].left_buttons[0] = META_BUTTON_FUNCTION_LAST; - different_layouts[i].right_buttons[0] = META_BUTTON_FUNCTION_LAST; - -#else - /* FIXME this code is if we allow duplicate buttons, - * which we currently do not - */ - int left; - int i; - - left = 0; - i = 0; - - while (left < MAX_BUTTONS_PER_CORNER) - { - int right; - - right = 0; - - while (right < MAX_BUTTONS_PER_CORNER) - { - int j; - - static MetaButtonFunction left_functions[MAX_BUTTONS_PER_CORNER] = { - META_BUTTON_FUNCTION_MENU, - META_BUTTON_FUNCTION_MINIMIZE, - META_BUTTON_FUNCTION_MAXIMIZE, - META_BUTTON_FUNCTION_CLOSE - }; - static MetaButtonFunction right_functions[MAX_BUTTONS_PER_CORNER] = { - META_BUTTON_FUNCTION_MINIMIZE, - META_BUTTON_FUNCTION_MAXIMIZE, - META_BUTTON_FUNCTION_CLOSE, - META_BUTTON_FUNCTION_MENU - }; - - g_assert (i < BUTTON_LAYOUT_COMBINATIONS); - - j = 0; - while (j <= left) - { - different_layouts[i].left_buttons[j] = left_functions[j]; - ++j; - } - - j = 0; - while (j <= right) - { - different_layouts[i].right_buttons[j] = right_functions[j]; - ++j; - } - - ++i; - - ++right; - } - - ++left; - } -#endif -} - - -static GtkWidget* -previews_of_button_layouts (void) -{ - static gboolean initted = FALSE; - GtkWidget *box; - GtkWidget *sw; - GdkColor desktop_color; - int i; - GtkWidget *eventbox; - - if (!initted) - { - init_layouts (); - initted = TRUE; - } - - sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - box = gtk_vbox_new (FALSE, 0); - gtk_box_set_spacing (GTK_BOX (box), 20); - gtk_container_set_border_width (GTK_CONTAINER (box), 20); - - eventbox = gtk_event_box_new (); - gtk_container_add (GTK_CONTAINER (eventbox), box); - - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), eventbox); - - desktop_color.red = 0x5144; - desktop_color.green = 0x75D6; - desktop_color.blue = 0xA699; - - gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &desktop_color); - - i = 0; - while (i < BUTTON_LAYOUT_COMBINATIONS) - { - GtkWidget *align; - double xalign, yalign; - GtkWidget *eventbox2; - GtkWidget *preview; - char *title; - - eventbox2 = gtk_event_box_new (); - - preview = meta_preview_new (); - - gtk_container_add (GTK_CONTAINER (eventbox2), preview); - - meta_preview_set_theme (META_PREVIEW (preview), global_theme); - - title = g_strdup_printf (_("Button layout test %d"), i+1); - meta_preview_set_title (META_PREVIEW (preview), title); - g_free (title); - - meta_preview_set_button_layout (META_PREVIEW (preview), - &different_layouts[i]); - - xalign = 0.5; - yalign = 0.5; - - align = gtk_alignment_new (0.0, 0.0, xalign, yalign); - gtk_container_add (GTK_CONTAINER (align), eventbox2); - - gtk_box_pack_start (GTK_BOX (box), align, TRUE, TRUE, 0); - - previews[META_FRAME_TYPE_LAST*FONT_SIZE_LAST + i] = preview; - - ++i; - } - - return sw; -} - -static GtkWidget* -benchmark_summary (void) -{ - char *msg; - GtkWidget *label; - - msg = g_strdup_printf (_("%g milliseconds to draw one window frame"), - milliseconds_to_draw_frame); - label = gtk_label_new (msg); - g_free (msg); - - return label; -} - -int -main (int argc, char **argv) -{ - GtkWidget *window; - GtkWidget *collection; - GError *err; - clock_t start, end; - GtkWidget *notebook; - int i; - - bindtextdomain (GETTEXT_PACKAGE, METACITY_LOCALEDIR); - textdomain(GETTEXT_PACKAGE); - bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); - - run_position_expression_tests (); -#if 0 - run_position_expression_timings (); -#endif - - gtk_init (&argc, &argv); - - if (g_getenv ("METACITY_DEBUG") != NULL) - { - meta_set_debugging (TRUE); - meta_set_verbose (TRUE); - } - - start = clock (); - err = NULL; - if (argc == 1) - global_theme = meta_theme_load ("Atlanta", &err); - else if (argc == 2) - global_theme = meta_theme_load (argv[1], &err); - else - { - g_printerr (_("Usage: metacity-theme-viewer [THEMENAME]\n")); - exit (1); - } - end = clock (); - - if (global_theme == NULL) - { - g_printerr (_("Error loading theme: %s\n"), - err->message); - g_error_free (err); - exit (1); - } - - g_print (_("Loaded theme \"%s\" in %g seconds\n"), - global_theme->name, - (end - start) / (double) CLOCKS_PER_SEC); - - run_theme_benchmark (); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size (GTK_WINDOW (window), 350, 350); - - if (strcmp (global_theme->name, global_theme->readable_name)==0) - gtk_window_set_title (GTK_WINDOW (window), - global_theme->readable_name); - else - { - /* The theme directory name is different from the name the theme - * gives itself within its file. Display both, directory name first. - */ - gchar *title = g_strconcat (global_theme->name, " - ", - global_theme->readable_name, - NULL); - - gtk_window_set_title (GTK_WINDOW (window), - title); - - g_free (title); - } - - g_signal_connect (G_OBJECT (window), "destroy", - G_CALLBACK (gtk_main_quit), NULL); - - gtk_widget_realize (window); - g_assert (window->style); - g_assert (window->style->font_desc); - - notebook = gtk_notebook_new (); - gtk_container_add (GTK_CONTAINER (window), notebook); - - collection = preview_collection (FONT_SIZE_NORMAL, - window->style->font_desc); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - collection, - gtk_label_new (_("Normal Title Font"))); - - collection = preview_collection (FONT_SIZE_SMALL, - window->style->font_desc); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - collection, - gtk_label_new (_("Small Title Font"))); - - collection = preview_collection (FONT_SIZE_LARGE, - window->style->font_desc); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - collection, - gtk_label_new (_("Large Title Font"))); - - collection = previews_of_button_layouts (); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - collection, - gtk_label_new (_("Button Layouts"))); - - collection = benchmark_summary (); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - collection, - gtk_label_new (_("Benchmark"))); - - i = 0; - while (i < (int) G_N_ELEMENTS (previews)) - { - /* preview widget likes to be realized before its size request. - * it's lame that way. - */ - gtk_widget_realize (previews[i]); - - ++i; - } - - gtk_widget_show_all (window); - - gtk_main (); - - return 0; -} - - -static MetaFrameFlags -get_flags (GtkWidget *widget) -{ - return META_FRAME_ALLOWS_DELETE | - META_FRAME_ALLOWS_MENU | - META_FRAME_ALLOWS_MINIMIZE | - META_FRAME_ALLOWS_MAXIMIZE | - META_FRAME_ALLOWS_VERTICAL_RESIZE | - META_FRAME_ALLOWS_HORIZONTAL_RESIZE | - META_FRAME_HAS_FOCUS | - META_FRAME_ALLOWS_SHADE | - META_FRAME_ALLOWS_MOVE; -} - -static int -get_text_height (GtkWidget *widget) -{ - return meta_pango_font_desc_get_text_height (widget->style->font_desc, - gtk_widget_get_pango_context (widget)); -} - -static PangoLayout* -create_title_layout (GtkWidget *widget) -{ - PangoLayout *layout; - - layout = gtk_widget_create_pango_layout (widget, _("Window Title Goes Here")); - - return layout; -} - -static void -run_theme_benchmark (void) -{ - GtkWidget* widget; - GdkPixmap *pixmap; - int top_height, bottom_height, left_width, right_width; - MetaButtonState button_states[META_BUTTON_TYPE_LAST] = - { - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_NORMAL - }; - PangoLayout *layout; - clock_t start; - clock_t end; - GTimer *timer; - int i; - MetaButtonLayout button_layout; -#define ITERATIONS 100 - int client_width; - int client_height; - int inc; - - widget = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_widget_realize (widget); - - meta_theme_get_frame_borders (global_theme, - META_FRAME_TYPE_NORMAL, - get_text_height (widget), - get_flags (widget), - &top_height, - &bottom_height, - &left_width, - &right_width); - - layout = create_title_layout (widget); - - i = 0; - while (i < MAX_BUTTONS_PER_CORNER) - { - button_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST; - button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; - ++i; - } - - button_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU; - - button_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE; - button_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE; - button_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE; - - timer = g_timer_new (); - start = clock (); - - client_width = 50; - client_height = 50; - inc = 1000 / ITERATIONS; /* Increment to grow width/height, - * eliminates caching effects. - */ - - i = 0; - while (i < ITERATIONS) - { - /* Creating the pixmap in the loop is right, since - * GDK does the same with its double buffering. - */ - pixmap = gdk_pixmap_new (widget->window, - client_width + left_width + right_width, - client_height + top_height + bottom_height, - -1); - - meta_theme_draw_frame (global_theme, - widget, - pixmap, - NULL, - 0, 0, - META_FRAME_TYPE_NORMAL, - get_flags (widget), - client_width, client_height, - layout, - get_text_height (widget), - &button_layout, - button_states, - meta_preview_get_mini_icon (), - meta_preview_get_icon ()); - - g_object_unref (G_OBJECT (pixmap)); - - ++i; - client_width += inc; - client_height += inc; - } - - end = clock (); - g_timer_stop (timer); - - milliseconds_to_draw_frame = (g_timer_elapsed (timer, NULL) / (double) ITERATIONS) * 1000; - - g_print (_("Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g seconds wall clock time including X server resources (%g milliseconds per frame)\n"), - ITERATIONS, - ((double)end - (double)start) / CLOCKS_PER_SEC, - (((double)end - (double)start) / CLOCKS_PER_SEC / (double) ITERATIONS) * 1000, - g_timer_elapsed (timer, NULL), - milliseconds_to_draw_frame); - - g_timer_destroy (timer); - g_object_unref (G_OBJECT (layout)); - gtk_widget_destroy (widget); - -#undef ITERATIONS -} - -typedef struct -{ - GdkRectangle rect; - const char *expr; - int expected_x; - int expected_y; - MetaThemeError expected_error; -} PositionExpressionTest; - -#define NO_ERROR -1 - -static const PositionExpressionTest position_expression_tests[] = { - /* Just numbers */ - { { 10, 20, 40, 50 }, - "10", 20, 30, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14.37", 24, 34, NO_ERROR }, - /* Binary expressions with 2 ints */ - { { 10, 20, 40, 50 }, - "14 * 10", 150, 160, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14 + 10", 34, 44, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14 - 10", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8 / 2", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8 % 3", 12, 22, NO_ERROR }, - /* Binary expressions with floats and mixed float/ints */ - { { 10, 20, 40, 50 }, - "7.0 / 3.5", 12, 22, NO_ERROR }, - { { 10, 20, 40, 50 }, - "12.1 / 3", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "12 / 2.95", 14, 24, NO_ERROR }, - /* Binary expressions without whitespace after first number */ - { { 10, 20, 40, 50 }, - "14* 10", 150, 160, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14+ 10", 34, 44, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14- 10", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8/ 2", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "7.0/ 3.5", 12, 22, NO_ERROR }, - { { 10, 20, 40, 50 }, - "12.1/ 3", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "12/ 2.95", 14, 24, NO_ERROR }, - /* Binary expressions without whitespace before second number */ - { { 10, 20, 40, 50 }, - "14 *10", 150, 160, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14 +10", 34, 44, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14 -10", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8 /2", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "7.0 /3.5", 12, 22, NO_ERROR }, - { { 10, 20, 40, 50 }, - "12.1 /3", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "12 /2.95", 14, 24, NO_ERROR }, - /* Binary expressions without any whitespace */ - { { 10, 20, 40, 50 }, - "14*10", 150, 160, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14+10", 34, 44, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14-10", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8/2", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "7.0/3.5", 12, 22, NO_ERROR }, - { { 10, 20, 40, 50 }, - "12.1/3", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "12/2.95", 14, 24, NO_ERROR }, - /* Binary expressions with parentheses */ - { { 10, 20, 40, 50 }, - "(14) * (10)", 150, 160, NO_ERROR }, - { { 10, 20, 40, 50 }, - "(14) + (10)", 34, 44, NO_ERROR }, - { { 10, 20, 40, 50 }, - "(14) - (10)", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "(8) / (2)", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "(7.0) / (3.5)", 12, 22, NO_ERROR }, - { { 10, 20, 40, 50 }, - "(12.1) / (3)", 14, 24, NO_ERROR }, - { { 10, 20, 40, 50 }, - "(12) / (2.95)", 14, 24, NO_ERROR }, - /* Lots of extra parentheses */ - { { 10, 20, 40, 50 }, - "(((14)) * ((10)))", 150, 160, NO_ERROR }, - { { 10, 20, 40, 50 }, - "((((14)))) + ((((((((10))))))))", 34, 44, NO_ERROR }, - { { 10, 20, 40, 50 }, - "((((((((((14 - 10))))))))))", 14, 24, NO_ERROR }, - /* Binary expressions with variables */ - { { 10, 20, 40, 50 }, - "2 * width", 90, 100, NO_ERROR }, - { { 10, 20, 40, 50 }, - "2 * height", 110, 120, NO_ERROR }, - { { 10, 20, 40, 50 }, - "width - 10", 40, 50, NO_ERROR }, - { { 10, 20, 40, 50 }, - "height / 2", 35, 45, NO_ERROR }, - /* More than two operands */ - { { 10, 20, 40, 50 }, - "8 / 2 + 5", 19, 29, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8 * 2 + 5", 31, 41, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8 + 2 * 5", 28, 38, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8 + 8 / 2", 22, 32, NO_ERROR }, - { { 10, 20, 40, 50 }, - "14 / (2 + 5)", 12, 22, NO_ERROR }, - { { 10, 20, 40, 50 }, - "8 * (2 + 5)", 66, 76, NO_ERROR }, - { { 10, 20, 40, 50 }, - "(8 + 2) * 5", 60, 70, NO_ERROR }, - { { 10, 20, 40, 50 }, - "(8 + 8) / 2", 18, 28, NO_ERROR }, - /* Errors */ - { { 10, 20, 40, 50 }, - "2 * foo", 0, 0, META_THEME_ERROR_UNKNOWN_VARIABLE }, - { { 10, 20, 40, 50 }, - "2 *", 0, 0, META_THEME_ERROR_FAILED }, - { { 10, 20, 40, 50 }, - "- width", 0, 0, META_THEME_ERROR_FAILED }, - { { 10, 20, 40, 50 }, - "5 % 1.0", 0, 0, META_THEME_ERROR_MOD_ON_FLOAT }, - { { 10, 20, 40, 50 }, - "1.0 % 5", 0, 0, META_THEME_ERROR_MOD_ON_FLOAT }, - { { 10, 20, 40, 50 }, - "! * 2", 0, 0, META_THEME_ERROR_BAD_CHARACTER }, - { { 10, 20, 40, 50 }, - " ", 0, 0, META_THEME_ERROR_FAILED }, - { { 10, 20, 40, 50 }, - "() () (( ) ()) ((()))", 0, 0, META_THEME_ERROR_FAILED }, - { { 10, 20, 40, 50 }, - "(*) () ((/) ()) ((()))", 0, 0, META_THEME_ERROR_FAILED }, - { { 10, 20, 40, 50 }, - "2 * 5 /", 0, 0, META_THEME_ERROR_FAILED }, - { { 10, 20, 40, 50 }, - "+ 2 * 5", 0, 0, META_THEME_ERROR_FAILED }, - { { 10, 20, 40, 50 }, - "+ 2 * 5", 0, 0, META_THEME_ERROR_FAILED } -}; - -static void -run_position_expression_tests (void) -{ -#if 0 - int i; - MetaPositionExprEnv env; - - i = 0; - while (i < (int) G_N_ELEMENTS (position_expression_tests)) - { - GError *err; - gboolean retval; - const PositionExpressionTest *test; - PosToken *tokens; - int n_tokens; - int x, y; - - test = &position_expression_tests[i]; - - if (g_getenv ("META_PRINT_TESTS") != NULL) - g_print ("Test expression: \"%s\" expecting x = %d y = %d", - test->expr, test->expected_x, test->expected_y); - - err = NULL; - - env.rect = meta_rect (test->rect.x, test->rect.y, - test->rect.width, test->rect.height); - env.object_width = -1; - env.object_height = -1; - env.left_width = 0; - env.right_width = 0; - env.top_height = 0; - env.bottom_height = 0; - env.title_width = 5; - env.title_height = 5; - env.icon_width = 32; - env.icon_height = 32; - env.mini_icon_width = 16; - env.mini_icon_height = 16; - env.theme = NULL; - - if (err == NULL) - { - retval = meta_parse_position_expression (tokens, n_tokens, - &env, - &x, &y, - &err); - } - - if (retval && err) - g_error (_("position expression test returned TRUE but set error")); - if (!retval && err == NULL) - g_error (_("position expression test returned FALSE but didn't set error")); - if (((int) test->expected_error) != NO_ERROR) - { - if (err == NULL) - g_error (_("Error was expected but none given")); - if (err->code != (int) test->expected_error) - g_error (_("Error %d was expected but %d given"), - test->expected_error, err->code); - } - else - { - if (err) - g_error (_("Error not expected but one was returned: %s"), - err->message); - - if (x != test->expected_x) - g_error (_("x value was %d, %d was expected"), x, test->expected_x); - - if (y != test->expected_y) - g_error (_("y value was %d, %d was expected"), y, test->expected_y); - } - - if (err) - g_error_free (err); - - meta_pos_tokens_free (tokens, n_tokens); - ++i; - } -#endif -} - -#if 0 -static void -run_position_expression_timings (void) -{ - int i; - int iters; - clock_t start; - clock_t end; - MetaPositionExprEnv env; - -#define ITERATIONS 100000 - - start = clock (); - - iters = 0; - i = 0; - while (iters < ITERATIONS) - { - const PositionExpressionTest *test; - int x, y; - - test = &position_expression_tests[i]; - - env.x = test->rect.x; - env.y = test->rect.y; - env.width = test->rect.width; - env.height = test->rect.height; - env.object_width = -1; - env.object_height = -1; - env.left_width = 0; - env.right_width = 0; - env.top_height = 0; - env.bottom_height = 0; - env.title_width = 5; - env.title_height = 5; - env.icon_width = 32; - env.icon_height = 32; - env.mini_icon_width = 16; - env.mini_icon_height = 16; - env.theme = NULL; - - meta_parse_position_expression (test->expr, - &env, - &x, &y, NULL); - - ++iters; - ++i; - if (i == G_N_ELEMENTS (position_expression_tests)) - i = 0; - } - - end = clock (); - - g_print (_("%d coordinate expressions parsed in %g seconds (%g seconds average)\n"), - ITERATIONS, - ((double)end - (double)start) / CLOCKS_PER_SEC, - ((double)end - (double)start) / CLOCKS_PER_SEC / (double) ITERATIONS); - -} -#endif diff --git a/src/ui/theme.c b/src/ui/theme.c deleted file mode 100644 index 1d822c82..00000000 --- a/src/ui/theme.c +++ /dev/null @@ -1,6480 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity Theme Rendering */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** - * \file theme.c Making Metacity look pretty - * - * The window decorations drawn by Metacity are described by files on disk - * known internally as "themes" (externally as "window border themes" on - * http://art.gnome.org/themes/metacity/ or "Metacity themes"). This file - * contains most of the code necessary to support themes; it does not - * contain the XML parser, which is in theme-parser.c. - * - * \bug This is a big file with lots of different subsystems, which might - * be better split out into separate files. - */ - -/** - * \defgroup tokenizer The theme expression tokenizer - * - * Themes can use a simple expression language to represent the values of - * things. This is the tokeniser used for that language. - * - * \bug We could remove almost all this code by using GScanner instead, - * but we would also have to find every expression in every existing theme - * we could and make sure the parse trees were the same. - */ - -/** - * \defgroup parser The theme expression parser - * - * Themes can use a simple expression language to represent the values of - * things. This is the parser used for that language. - */ - -#include <config.h> -#include "theme.h" -#include "theme-parser.h" -#include "util.h" -#include "gradient.h" -#include <gtk/gtk.h> -#include <string.h> -#include <stdlib.h> -#include <math.h> - -#define GDK_COLOR_RGBA(color) \ - ((guint32) (0xff | \ - (((color).red / 256) << 24) | \ - (((color).green / 256) << 16) | \ - (((color).blue / 256) << 8))) - -#define GDK_COLOR_RGB(color) \ - ((guint32) ((((color).red / 256) << 16) | \ - (((color).green / 256) << 8) | \ - (((color).blue / 256)))) - -#define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255)) - -#define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s))) -#define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255))) -#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) - -static void gtk_style_shade (GdkColor *a, - GdkColor *b, - gdouble k); -static void rgb_to_hls (gdouble *r, - gdouble *g, - gdouble *b); -static void hls_to_rgb (gdouble *h, - gdouble *l, - gdouble *s); - -/** - * The current theme. (Themes are singleton.) - */ -static MetaTheme *meta_current_theme = NULL; - -static GdkPixbuf * -colorize_pixbuf (GdkPixbuf *orig, - GdkColor *new_color) -{ - GdkPixbuf *pixbuf; - double intensity; - int x, y; - const guchar *src; - guchar *dest; - int orig_rowstride; - int dest_rowstride; - int width, height; - gboolean has_alpha; - const guchar *src_pixels; - guchar *dest_pixels; - - pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig), - gdk_pixbuf_get_bits_per_sample (orig), - gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig)); - - if (pixbuf == NULL) - return NULL; - - orig_rowstride = gdk_pixbuf_get_rowstride (orig); - dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf); - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - has_alpha = gdk_pixbuf_get_has_alpha (orig); - src_pixels = gdk_pixbuf_get_pixels (orig); - dest_pixels = gdk_pixbuf_get_pixels (pixbuf); - - for (y = 0; y < height; y++) - { - src = src_pixels + y * orig_rowstride; - dest = dest_pixels + y * dest_rowstride; - - for (x = 0; x < width; x++) - { - double dr, dg, db; - - intensity = INTENSITY (src[0], src[1], src[2]) / 255.0; - - if (intensity <= 0.5) - { - /* Go from black at intensity = 0.0 to new_color at intensity = 0.5 */ - dr = (new_color->red * intensity * 2.0) / 65535.0; - dg = (new_color->green * intensity * 2.0) / 65535.0; - db = (new_color->blue * intensity * 2.0) / 65535.0; - } - else - { - /* Go from new_color at intensity = 0.5 to white at intensity = 1.0 */ - dr = (new_color->red + (65535 - new_color->red) * (intensity - 0.5) * 2.0) / 65535.0; - dg = (new_color->green + (65535 - new_color->green) * (intensity - 0.5) * 2.0) / 65535.0; - db = (new_color->blue + (65535 - new_color->blue) * (intensity - 0.5) * 2.0) / 65535.0; - } - - dest[0] = CLAMP_UCHAR (255 * dr); - dest[1] = CLAMP_UCHAR (255 * dg); - dest[2] = CLAMP_UCHAR (255 * db); - - if (has_alpha) - { - dest[3] = src[3]; - src += 4; - dest += 4; - } - else - { - src += 3; - dest += 3; - } - } - } - - return pixbuf; -} - -static void -color_composite (const GdkColor *bg, - const GdkColor *fg, - double alpha_d, - GdkColor *color) -{ - guint16 alpha; - - *color = *bg; - alpha = alpha_d * 0xffff; - color->red = color->red + (((fg->red - color->red) * alpha + 0x8000) >> 16); - color->green = color->green + (((fg->green - color->green) * alpha + 0x8000) >> 16); - color->blue = color->blue + (((fg->blue - color->blue) * alpha + 0x8000) >> 16); -} - -/** - * Sets all the fields of a border to dummy values. - * - * \param border The border whose fields should be reset. - */ -static void -init_border (GtkBorder *border) -{ - border->top = -1; - border->bottom = -1; - border->left = -1; - border->right = -1; -} - -/** - * Creates a new, empty MetaFrameLayout. The fields will be set to dummy - * values. - * - * \return The newly created MetaFrameLayout. - */ -MetaFrameLayout* -meta_frame_layout_new (void) -{ - MetaFrameLayout *layout; - - layout = g_new0 (MetaFrameLayout, 1); - - layout->refcount = 1; - - /* Fill with -1 values to detect invalid themes */ - layout->left_width = -1; - layout->right_width = -1; - layout->bottom_height = -1; - - init_border (&layout->title_border); - - layout->title_vertical_pad = -1; - - layout->right_titlebar_edge = -1; - layout->left_titlebar_edge = -1; - - layout->button_sizing = META_BUTTON_SIZING_LAST; - layout->button_aspect = 1.0; - layout->button_width = -1; - layout->button_height = -1; - - layout->has_title = TRUE; - layout->title_scale = 1.0; - - init_border (&layout->button_border); - - return layout; -} - -/** - * - */ -static gboolean -validate_border (const GtkBorder *border, - const char **bad) -{ - *bad = NULL; - - if (border->top < 0) - *bad = _("top"); - else if (border->bottom < 0) - *bad = _("bottom"); - else if (border->left < 0) - *bad = _("left"); - else if (border->right < 0) - *bad = _("right"); - - return *bad == NULL; -} - -/** - * Ensures that the theme supplied a particular dimension. When a - * MetaFrameLayout is created, all its integer fields are set to -1 - * by meta_frame_layout_new(). After an instance of this type - * should have been initialised, this function checks that - * a given field is not still at -1. It is never called directly, but - * rather via the CHECK_GEOMETRY_VALUE and CHECK_GEOMETRY_BORDER - * macros. - * - * \param val The value to check - * \param name The name to use in the error message - * \param[out] error Set to an error if val was not initialised - */ -static gboolean -validate_geometry_value (int val, - const char *name, - GError **error) -{ - if (val < 0) - { - g_set_error (error, META_THEME_ERROR, - META_THEME_ERROR_FRAME_GEOMETRY, - _("frame geometry does not specify \"%s\" dimension"), - name); - return FALSE; - } - else - return TRUE; -} - -static gboolean -validate_geometry_border (const GtkBorder *border, - const char *name, - GError **error) -{ - const char *bad; - - if (!validate_border (border, &bad)) - { - g_set_error (error, META_THEME_ERROR, - META_THEME_ERROR_FRAME_GEOMETRY, - _("frame geometry does not specify dimension \"%s\" for border \"%s\""), - bad, name); - return FALSE; - } - else - return TRUE; -} - -gboolean -meta_frame_layout_validate (const MetaFrameLayout *layout, - GError **error) -{ - g_return_val_if_fail (layout != NULL, FALSE); - -#define CHECK_GEOMETRY_VALUE(vname) if (!validate_geometry_value (layout->vname, #vname, error)) return FALSE - -#define CHECK_GEOMETRY_BORDER(bname) if (!validate_geometry_border (&layout->bname, #bname, error)) return FALSE - - CHECK_GEOMETRY_VALUE (left_width); - CHECK_GEOMETRY_VALUE (right_width); - CHECK_GEOMETRY_VALUE (bottom_height); - - CHECK_GEOMETRY_BORDER (title_border); - - CHECK_GEOMETRY_VALUE (title_vertical_pad); - - CHECK_GEOMETRY_VALUE (right_titlebar_edge); - CHECK_GEOMETRY_VALUE (left_titlebar_edge); - - switch (layout->button_sizing) - { - case META_BUTTON_SIZING_ASPECT: - if (layout->button_aspect < (0.1) || - layout->button_aspect > (15.0)) - { - g_set_error (error, META_THEME_ERROR, - META_THEME_ERROR_FRAME_GEOMETRY, - _("Button aspect ratio %g is not reasonable"), - layout->button_aspect); - return FALSE; - } - break; - case META_BUTTON_SIZING_FIXED: - CHECK_GEOMETRY_VALUE (button_width); - CHECK_GEOMETRY_VALUE (button_height); - break; - case META_BUTTON_SIZING_LAST: - g_set_error (error, META_THEME_ERROR, - META_THEME_ERROR_FRAME_GEOMETRY, - _("Frame geometry does not specify size of buttons")); - return FALSE; - } - - CHECK_GEOMETRY_BORDER (button_border); - - return TRUE; -} - -MetaFrameLayout* -meta_frame_layout_copy (const MetaFrameLayout *src) -{ - MetaFrameLayout *layout; - - layout = g_new0 (MetaFrameLayout, 1); - - *layout = *src; - - layout->refcount = 1; - - return layout; -} - -void -meta_frame_layout_ref (MetaFrameLayout *layout) -{ - g_return_if_fail (layout != NULL); - - layout->refcount += 1; -} - -void -meta_frame_layout_unref (MetaFrameLayout *layout) -{ - g_return_if_fail (layout != NULL); - g_return_if_fail (layout->refcount > 0); - - layout->refcount -= 1; - - if (layout->refcount == 0) - { - DEBUG_FILL_STRUCT (layout); - g_free (layout); - } -} - -void -meta_frame_layout_get_borders (const MetaFrameLayout *layout, - int text_height, - MetaFrameFlags flags, - int *top_height, - int *bottom_height, - int *left_width, - int *right_width) -{ - int buttons_height, title_height; - - g_return_if_fail (top_height != NULL); - g_return_if_fail (bottom_height != NULL); - g_return_if_fail (left_width != NULL); - g_return_if_fail (right_width != NULL); - - if (!layout->has_title) - text_height = 0; - - buttons_height = layout->button_height + - layout->button_border.top + layout->button_border.bottom; - title_height = text_height + - layout->title_vertical_pad + - layout->title_border.top + layout->title_border.bottom; - - if (top_height) - { - *top_height = MAX (buttons_height, title_height); - } - - if (left_width) - *left_width = layout->left_width; - if (right_width) - *right_width = layout->right_width; - - if (bottom_height) - { - if (flags & META_FRAME_SHADED) - *bottom_height = 0; - else - *bottom_height = layout->bottom_height; - } - - if (flags & META_FRAME_FULLSCREEN) - { - if (top_height) - *top_height = 0; - if (bottom_height) - *bottom_height = 0; - if (left_width) - *left_width = 0; - if (right_width) - *right_width = 0; - } -} - -static MetaButtonSpace* -rect_for_function (MetaFrameGeometry *fgeom, - MetaFrameFlags flags, - MetaButtonFunction function, - MetaTheme *theme) -{ - - /* Firstly, check version-specific things. */ - - if (META_THEME_ALLOWS(theme, META_THEME_SHADE_STICK_ABOVE_BUTTONS)) - { - switch (function) - { - case META_BUTTON_FUNCTION_SHADE: - if ((flags & META_FRAME_ALLOWS_SHADE) && !(flags & META_FRAME_SHADED)) - return &fgeom->shade_rect; - else - return NULL; - case META_BUTTON_FUNCTION_ABOVE: - if (!(flags & META_FRAME_ABOVE)) - return &fgeom->above_rect; - else - return NULL; - case META_BUTTON_FUNCTION_STICK: - if (!(flags & META_FRAME_STUCK)) - return &fgeom->stick_rect; - else - return NULL; - case META_BUTTON_FUNCTION_UNSHADE: - if ((flags & META_FRAME_ALLOWS_SHADE) && (flags & META_FRAME_SHADED)) - return &fgeom->unshade_rect; - else - return NULL; - case META_BUTTON_FUNCTION_UNABOVE: - if (flags & META_FRAME_ABOVE) - return &fgeom->unabove_rect; - else - return NULL; - case META_BUTTON_FUNCTION_UNSTICK: - if (flags & META_FRAME_STUCK) - return &fgeom->unstick_rect; - default: - /* just go on to the next switch block */; - } - } - - /* now consider the buttons which exist in all versions */ - - switch (function) - { - case META_BUTTON_FUNCTION_MENU: - if (flags & META_FRAME_ALLOWS_MENU) - return &fgeom->menu_rect; - else - return NULL; - case META_BUTTON_FUNCTION_MINIMIZE: - if (flags & META_FRAME_ALLOWS_MINIMIZE) - return &fgeom->min_rect; - else - return NULL; - case META_BUTTON_FUNCTION_MAXIMIZE: - if (flags & META_FRAME_ALLOWS_MAXIMIZE) - return &fgeom->max_rect; - else - return NULL; - case META_BUTTON_FUNCTION_CLOSE: - if (flags & META_FRAME_ALLOWS_DELETE) - return &fgeom->close_rect; - else - return NULL; - case META_BUTTON_FUNCTION_STICK: - case META_BUTTON_FUNCTION_SHADE: - case META_BUTTON_FUNCTION_ABOVE: - case META_BUTTON_FUNCTION_UNSTICK: - case META_BUTTON_FUNCTION_UNSHADE: - case META_BUTTON_FUNCTION_UNABOVE: - /* we are being asked for a >v1 button which hasn't been handled yet, - * so obviously we're not in a theme which supports that version. - * therefore, we don't show the button. return NULL and all will - * be well. - */ - return NULL; - - case META_BUTTON_FUNCTION_LAST: - return NULL; - } - - return NULL; -} - -static gboolean -strip_button (MetaButtonSpace *func_rects[MAX_BUTTONS_PER_CORNER], - GdkRectangle *bg_rects[MAX_BUTTONS_PER_CORNER], - int *n_rects, - MetaButtonSpace *to_strip) -{ - int i; - - i = 0; - while (i < *n_rects) - { - if (func_rects[i] == to_strip) - { - *n_rects -= 1; - - /* shift the other rects back in the array */ - while (i < *n_rects) - { - func_rects[i] = func_rects[i+1]; - bg_rects[i] = bg_rects[i+1]; - - ++i; - } - - func_rects[i] = NULL; - bg_rects[i] = NULL; - - return TRUE; - } - - ++i; - } - - return FALSE; /* did not strip anything */ -} - -void -meta_frame_layout_calc_geometry (const MetaFrameLayout *layout, - int text_height, - MetaFrameFlags flags, - int client_width, - int client_height, - const MetaButtonLayout *button_layout, - MetaFrameGeometry *fgeom, - MetaTheme *theme) -{ - int i, n_left, n_right, n_left_spacers, n_right_spacers; - int x; - int button_y; - int title_right_edge; - int width, height; - int button_width, button_height; - int min_size_for_rounding; - - /* the left/right rects in order; the max # of rects - * is the number of button functions - */ - MetaButtonSpace *left_func_rects[MAX_BUTTONS_PER_CORNER]; - MetaButtonSpace *right_func_rects[MAX_BUTTONS_PER_CORNER]; - GdkRectangle *left_bg_rects[MAX_BUTTONS_PER_CORNER]; - gboolean left_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; - GdkRectangle *right_bg_rects[MAX_BUTTONS_PER_CORNER]; - gboolean right_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; - - meta_frame_layout_get_borders (layout, text_height, - flags, - &fgeom->top_height, - &fgeom->bottom_height, - &fgeom->left_width, - &fgeom->right_width); - - width = client_width + fgeom->left_width + fgeom->right_width; - - height = ((flags & META_FRAME_SHADED) ? 0: client_height) + - fgeom->top_height + fgeom->bottom_height; - - fgeom->width = width; - fgeom->height = height; - - fgeom->top_titlebar_edge = layout->title_border.top; - fgeom->bottom_titlebar_edge = layout->title_border.bottom; - fgeom->left_titlebar_edge = layout->left_titlebar_edge; - fgeom->right_titlebar_edge = layout->right_titlebar_edge; - - /* gcc warnings */ - button_width = -1; - button_height = -1; - - switch (layout->button_sizing) - { - case META_BUTTON_SIZING_ASPECT: - button_height = fgeom->top_height - layout->button_border.top - layout->button_border.bottom; - button_width = button_height / layout->button_aspect; - break; - case META_BUTTON_SIZING_FIXED: - button_width = layout->button_width; - button_height = layout->button_height; - break; - case META_BUTTON_SIZING_LAST: - g_assert_not_reached (); - break; - } - - /* FIXME all this code sort of pretends that duplicate buttons - * with the same function are allowed, but that breaks the - * code in frames.c, so isn't really allowed right now. - * Would need left_close_rect, right_close_rect, etc. - */ - - /* Init all button rects to 0, lame hack */ - memset (ADDRESS_OF_BUTTON_RECTS (fgeom), '\0', - LENGTH_OF_BUTTON_RECTS); - - n_left = 0; - n_right = 0; - n_left_spacers = 0; - n_right_spacers = 0; - - if (!layout->hide_buttons) - { - /* Try to fill in rects */ - for (i = 0; i < MAX_BUTTONS_PER_CORNER && button_layout->left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++) - { - left_func_rects[n_left] = rect_for_function (fgeom, flags, - button_layout->left_buttons[i], - theme); - if (left_func_rects[n_left] != NULL) - { - left_buttons_has_spacer[n_left] = button_layout->left_buttons_has_spacer[i]; - if (button_layout->left_buttons_has_spacer[i]) - ++n_left_spacers; - - ++n_left; - } - } - - for (i = 0; i < MAX_BUTTONS_PER_CORNER && button_layout->right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++) - { - right_func_rects[n_right] = rect_for_function (fgeom, flags, - button_layout->right_buttons[i], - theme); - if (right_func_rects[n_right] != NULL) - { - right_buttons_has_spacer[n_right] = button_layout->right_buttons_has_spacer[i]; - if (button_layout->right_buttons_has_spacer[i]) - ++n_right_spacers; - - ++n_right; - } - } - } - - for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++) - { - left_bg_rects[i] = NULL; - right_bg_rects[i] = NULL; - } - - for (i = 0; i < n_left; i++) - { - if (i == 0) /* prefer left background if only one button */ - left_bg_rects[i] = &fgeom->left_left_background; - else if (i == (n_left - 1)) - left_bg_rects[i] = &fgeom->left_right_background; - else - left_bg_rects[i] = &fgeom->left_middle_backgrounds[i - 1]; - } - - for (i = 0; i < n_right; i++) - { - /* prefer right background if only one button */ - if (i == (n_right - 1)) - right_bg_rects[i] = &fgeom->right_right_background; - else if (i == 0) - right_bg_rects[i] = &fgeom->right_left_background; - else - right_bg_rects[i] = &fgeom->right_middle_backgrounds[i - 1]; - } - - /* Be sure buttons fit */ - while (n_left > 0 || n_right > 0) - { - int space_used_by_buttons; - int space_available; - - space_available = fgeom->width - layout->left_titlebar_edge - layout->right_titlebar_edge; - - space_used_by_buttons = 0; - - space_used_by_buttons += button_width * n_left; - space_used_by_buttons += (button_width * 0.75) * n_left_spacers; - space_used_by_buttons += layout->button_border.left * n_left; - space_used_by_buttons += layout->button_border.right * n_left; - - space_used_by_buttons += button_width * n_right; - space_used_by_buttons += (button_width * 0.75) * n_right_spacers; - space_used_by_buttons += layout->button_border.left * n_right; - space_used_by_buttons += layout->button_border.right * n_right; - - if (space_used_by_buttons <= space_available) - break; /* Everything fits, bail out */ - - /* First try to remove separators */ - if (n_left_spacers > 0) - { - left_buttons_has_spacer[--n_left_spacers] = FALSE; - continue; - } - else if (n_right_spacers > 0) - { - right_buttons_has_spacer[--n_right_spacers] = FALSE; - continue; - } - - /* Otherwise we need to shave out a button. Shave - * above, stick, shade, min, max, close, then menu (menu is most useful); - * prefer the default button locations. - */ - if (strip_button (left_func_rects, left_bg_rects, - &n_left, &fgeom->above_rect)) - continue; - else if (strip_button (right_func_rects, right_bg_rects, - &n_right, &fgeom->above_rect)) - continue; - else if (strip_button (left_func_rects, left_bg_rects, - &n_left, &fgeom->stick_rect)) - continue; - else if (strip_button (right_func_rects, right_bg_rects, - &n_right, &fgeom->stick_rect)) - continue; - else if (strip_button (left_func_rects, left_bg_rects, - &n_left, &fgeom->shade_rect)) - continue; - else if (strip_button (right_func_rects, right_bg_rects, - &n_right, &fgeom->shade_rect)) - continue; - else if (strip_button (left_func_rects, left_bg_rects, - &n_left, &fgeom->min_rect)) - continue; - else if (strip_button (right_func_rects, right_bg_rects, - &n_right, &fgeom->min_rect)) - continue; - else if (strip_button (left_func_rects, left_bg_rects, - &n_left, &fgeom->max_rect)) - continue; - else if (strip_button (right_func_rects, right_bg_rects, - &n_right, &fgeom->max_rect)) - continue; - else if (strip_button (left_func_rects, left_bg_rects, - &n_left, &fgeom->close_rect)) - continue; - else if (strip_button (right_func_rects, right_bg_rects, - &n_right, &fgeom->close_rect)) - continue; - else if (strip_button (right_func_rects, right_bg_rects, - &n_right, &fgeom->menu_rect)) - continue; - else if (strip_button (left_func_rects, left_bg_rects, - &n_left, &fgeom->menu_rect)) - continue; - else - { - meta_bug ("Could not find a button to strip. n_left = %d n_right = %d\n", - n_left, n_right); - } - } - - /* center buttons vertically */ - button_y = (fgeom->top_height - - (button_height + layout->button_border.top + layout->button_border.bottom)) / 2 + layout->button_border.top; - - /* right edge of farthest-right button */ - x = width - layout->right_titlebar_edge; - - i = n_right - 1; - while (i >= 0) - { - MetaButtonSpace *rect; - - if (x < 0) /* if we go negative, leave the buttons we don't get to as 0-width */ - break; - - rect = right_func_rects[i]; - rect->visible.x = x - layout->button_border.right - button_width; - if (right_buttons_has_spacer[i]) - rect->visible.x -= (button_width * 0.75); - - rect->visible.y = button_y; - rect->visible.width = button_width; - rect->visible.height = button_height; - - if (flags & META_FRAME_MAXIMIZED) - { - rect->clickable.x = rect->visible.x; - rect->clickable.y = 0; - rect->clickable.width = rect->visible.width; - rect->clickable.height = button_height + button_y; - - if (i == n_right - 1) - rect->clickable.width += layout->right_titlebar_edge + layout->right_width + layout->button_border.right; - - } - else - g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable)); - - *(right_bg_rects[i]) = rect->visible; - - x = rect->visible.x - layout->button_border.left; - - --i; - } - - /* save right edge of titlebar for later use */ - title_right_edge = x - layout->title_border.right; - - /* Now x changes to be position from the left and we go through - * the left-side buttons - */ - x = layout->left_titlebar_edge; - for (i = 0; i < n_left; i++) - { - MetaButtonSpace *rect; - - rect = left_func_rects[i]; - - rect->visible.x = x + layout->button_border.left; - rect->visible.y = button_y; - rect->visible.width = button_width; - rect->visible.height = button_height; - - if (flags & META_FRAME_MAXIMIZED) - { - if (i==0) - { - rect->clickable.x = 0; - rect->clickable.width = button_width + x; - } - else - { - rect->clickable.x = rect->visible.x; - rect->clickable.width = button_width; - } - - rect->clickable.y = 0; - rect->clickable.height = button_height + button_y; - } - else - g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable)); - - - x = rect->visible.x + rect->visible.width + layout->button_border.right; - if (left_buttons_has_spacer[i]) - x += (button_width * 0.75); - - *(left_bg_rects[i]) = rect->visible; - } - - /* We always fill as much vertical space as possible with title rect, - * rather than centering it like the buttons - */ - fgeom->title_rect.x = x + layout->title_border.left; - fgeom->title_rect.y = layout->title_border.top; - fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x; - fgeom->title_rect.height = fgeom->top_height - layout->title_border.top - layout->title_border.bottom; - - /* Nuke title if it won't fit */ - if (fgeom->title_rect.width < 0 || - fgeom->title_rect.height < 0) - { - fgeom->title_rect.width = 0; - fgeom->title_rect.height = 0; - } - - if (flags & META_FRAME_SHADED) - min_size_for_rounding = 0; - else - min_size_for_rounding = 5; - - fgeom->top_left_corner_rounded_radius = 0; - fgeom->top_right_corner_rounded_radius = 0; - fgeom->bottom_left_corner_rounded_radius = 0; - fgeom->bottom_right_corner_rounded_radius = 0; - - if (fgeom->top_height + fgeom->left_width >= min_size_for_rounding) - fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius; - if (fgeom->top_height + fgeom->right_width >= min_size_for_rounding) - fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius; - - if (fgeom->bottom_height + fgeom->left_width >= min_size_for_rounding) - fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius; - if (fgeom->bottom_height + fgeom->right_width >= min_size_for_rounding) - fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius; -} - -MetaGradientSpec* -meta_gradient_spec_new (MetaGradientType type) -{ - MetaGradientSpec *spec; - - spec = g_new (MetaGradientSpec, 1); - - spec->type = type; - spec->color_specs = NULL; - - return spec; -} - -static void -free_color_spec (gpointer spec, gpointer user_data) -{ - meta_color_spec_free (spec); -} - -void -meta_gradient_spec_free (MetaGradientSpec *spec) -{ - g_return_if_fail (spec != NULL); - - g_slist_foreach (spec->color_specs, free_color_spec, NULL); - g_slist_free (spec->color_specs); - - DEBUG_FILL_STRUCT (spec); - g_free (spec); -} - -GdkPixbuf* -meta_gradient_spec_render (const MetaGradientSpec *spec, - GtkWidget *widget, - int width, - int height) -{ - int n_colors; - GdkColor *colors; - GSList *tmp; - int i; - GdkPixbuf *pixbuf; - - n_colors = g_slist_length (spec->color_specs); - - if (n_colors == 0) - return NULL; - - colors = g_new (GdkColor, n_colors); - - i = 0; - tmp = spec->color_specs; - while (tmp != NULL) - { - meta_color_spec_render (tmp->data, widget, &colors[i]); - - tmp = tmp->next; - ++i; - } - - pixbuf = meta_gradient_create_multi (width, height, - colors, n_colors, - spec->type); - - g_free (colors); - - return pixbuf; -} - -gboolean -meta_gradient_spec_validate (MetaGradientSpec *spec, - GError **error) -{ - g_return_val_if_fail (spec != NULL, FALSE); - - if (g_slist_length (spec->color_specs) < 2) - { - g_set_error (error, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Gradients should have at least two colors")); - return FALSE; - } - - return TRUE; -} - -MetaAlphaGradientSpec* -meta_alpha_gradient_spec_new (MetaGradientType type, - int n_alphas) -{ - MetaAlphaGradientSpec *spec; - - g_return_val_if_fail (n_alphas > 0, NULL); - - spec = g_new0 (MetaAlphaGradientSpec, 1); - - spec->type = type; - spec->alphas = g_new0 (unsigned char, n_alphas); - spec->n_alphas = n_alphas; - - return spec; -} - -void -meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec) -{ - g_return_if_fail (spec != NULL); - - g_free (spec->alphas); - g_free (spec); -} - -MetaColorSpec* -meta_color_spec_new (MetaColorSpecType type) -{ - MetaColorSpec *spec; - MetaColorSpec dummy; - int size; - - size = G_STRUCT_OFFSET (MetaColorSpec, data); - - switch (type) - { - case META_COLOR_SPEC_BASIC: - size += sizeof (dummy.data.basic); - break; - - case META_COLOR_SPEC_GTK: - size += sizeof (dummy.data.gtk); - break; - - case META_COLOR_SPEC_BLEND: - size += sizeof (dummy.data.blend); - break; - - case META_COLOR_SPEC_SHADE: - size += sizeof (dummy.data.shade); - break; - } - - spec = g_malloc0 (size); - - spec->type = type; - - return spec; -} - -void -meta_color_spec_free (MetaColorSpec *spec) -{ - g_return_if_fail (spec != NULL); - - switch (spec->type) - { - case META_COLOR_SPEC_BASIC: - DEBUG_FILL_STRUCT (&spec->data.basic); - break; - - case META_COLOR_SPEC_GTK: - DEBUG_FILL_STRUCT (&spec->data.gtk); - break; - - case META_COLOR_SPEC_BLEND: - if (spec->data.blend.foreground) - meta_color_spec_free (spec->data.blend.foreground); - if (spec->data.blend.background) - meta_color_spec_free (spec->data.blend.background); - DEBUG_FILL_STRUCT (&spec->data.blend); - break; - - case META_COLOR_SPEC_SHADE: - if (spec->data.shade.base) - meta_color_spec_free (spec->data.shade.base); - DEBUG_FILL_STRUCT (&spec->data.shade); - break; - } - - g_free (spec); -} - -MetaColorSpec* -meta_color_spec_new_from_string (const char *str, - GError **err) -{ - MetaColorSpec *spec; - - spec = NULL; - - if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':') - { - /* GTK color */ - const char *bracket; - const char *end_bracket; - char *tmp; - GtkStateType state; - MetaGtkColorComponent component; - - bracket = str; - while (*bracket && *bracket != '[') - ++bracket; - - if (*bracket == '\0') - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""), - str); - return NULL; - } - - end_bracket = bracket; - ++end_bracket; - while (*end_bracket && *end_bracket != ']') - ++end_bracket; - - if (*end_bracket == '\0') - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("GTK color specification must have a close bracket after the state, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""), - str); - return NULL; - } - - tmp = g_strndup (bracket + 1, end_bracket - bracket - 1); - state = meta_gtk_state_from_string (tmp); - if (((int) state) == -1) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Did not understand state \"%s\" in color specification"), - tmp); - g_free (tmp); - return NULL; - } - g_free (tmp); - - tmp = g_strndup (str + 4, bracket - str - 4); - component = meta_color_component_from_string (tmp); - if (component == META_GTK_COLOR_LAST) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Did not understand color component \"%s\" in color specification"), - tmp); - g_free (tmp); - return NULL; - } - g_free (tmp); - - spec = meta_color_spec_new (META_COLOR_SPEC_GTK); - spec->data.gtk.state = state; - spec->data.gtk.component = component; - g_assert (spec->data.gtk.state < N_GTK_STATES); - g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST); - } - else if (str[0] == 'b' && str[1] == 'l' && str[2] == 'e' && str[3] == 'n' && - str[4] == 'd' && str[5] == '/') - { - /* blend */ - char **split; - double alpha; - char *end; - MetaColorSpec *fg; - MetaColorSpec *bg; - - split = g_strsplit (str, "/", 4); - - if (split[0] == NULL || split[1] == NULL || - split[2] == NULL || split[3] == NULL) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the format"), - str); - g_strfreev (split); - return NULL; - } - - alpha = g_ascii_strtod (split[3], &end); - if (end == split[3]) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Could not parse alpha value \"%s\" in blended color"), - split[3]); - g_strfreev (split); - return NULL; - } - - if (alpha < (0.0 - 1e6) || alpha > (1.0 + 1e6)) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Alpha value \"%s\" in blended color is not between 0.0 and 1.0"), - split[3]); - g_strfreev (split); - return NULL; - } - - fg = NULL; - bg = NULL; - - bg = meta_color_spec_new_from_string (split[1], err); - if (bg == NULL) - { - g_strfreev (split); - return NULL; - } - - fg = meta_color_spec_new_from_string (split[2], err); - if (fg == NULL) - { - meta_color_spec_free (bg); - g_strfreev (split); - return NULL; - } - - g_strfreev (split); - - spec = meta_color_spec_new (META_COLOR_SPEC_BLEND); - spec->data.blend.alpha = alpha; - spec->data.blend.background = bg; - spec->data.blend.foreground = fg; - } - else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' && - str[4] == 'e' && str[5] == '/') - { - /* shade */ - char **split; - double factor; - char *end; - MetaColorSpec *base; - - split = g_strsplit (str, "/", 3); - - if (split[0] == NULL || split[1] == NULL || - split[2] == NULL) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"), - str); - g_strfreev (split); - return NULL; - } - - factor = g_ascii_strtod (split[2], &end); - if (end == split[2]) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Could not parse shade factor \"%s\" in shaded color"), - split[2]); - g_strfreev (split); - return NULL; - } - - if (factor < (0.0 - 1e6)) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Shade factor \"%s\" in shaded color is negative"), - split[2]); - g_strfreev (split); - return NULL; - } - - base = NULL; - - base = meta_color_spec_new_from_string (split[1], err); - if (base == NULL) - { - g_strfreev (split); - return NULL; - } - - g_strfreev (split); - - spec = meta_color_spec_new (META_COLOR_SPEC_SHADE); - spec->data.shade.factor = factor; - spec->data.shade.base = base; - } - else - { - spec = meta_color_spec_new (META_COLOR_SPEC_BASIC); - - if (!gdk_color_parse (str, &spec->data.basic.color)) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Could not parse color \"%s\""), - str); - meta_color_spec_free (spec); - return NULL; - } - } - - g_assert (spec); - - return spec; -} - -MetaColorSpec* -meta_color_spec_new_gtk (MetaGtkColorComponent component, - GtkStateType state) -{ - MetaColorSpec *spec; - - spec = meta_color_spec_new (META_COLOR_SPEC_GTK); - - spec->data.gtk.component = component; - spec->data.gtk.state = state; - - return spec; -} - -void -meta_color_spec_render (MetaColorSpec *spec, - GtkWidget *widget, - GdkColor *color) -{ - g_return_if_fail (spec != NULL); - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (widget->style != NULL); - - switch (spec->type) - { - case META_COLOR_SPEC_BASIC: - *color = spec->data.basic.color; - break; - - case META_COLOR_SPEC_GTK: - switch (spec->data.gtk.component) - { - case META_GTK_COLOR_BG: - *color = widget->style->bg[spec->data.gtk.state]; - break; - case META_GTK_COLOR_FG: - *color = widget->style->fg[spec->data.gtk.state]; - break; - case META_GTK_COLOR_BASE: - *color = widget->style->base[spec->data.gtk.state]; - break; - case META_GTK_COLOR_TEXT: - *color = widget->style->text[spec->data.gtk.state]; - break; - case META_GTK_COLOR_LIGHT: - *color = widget->style->light[spec->data.gtk.state]; - break; - case META_GTK_COLOR_DARK: - *color = widget->style->dark[spec->data.gtk.state]; - break; - case META_GTK_COLOR_MID: - *color = widget->style->mid[spec->data.gtk.state]; - break; - case META_GTK_COLOR_TEXT_AA: - *color = widget->style->text_aa[spec->data.gtk.state]; - break; - case META_GTK_COLOR_LAST: - g_assert_not_reached (); - break; - } - break; - - case META_COLOR_SPEC_BLEND: - { - GdkColor bg, fg; - - meta_color_spec_render (spec->data.blend.background, widget, &bg); - meta_color_spec_render (spec->data.blend.foreground, widget, &fg); - - color_composite (&bg, &fg, spec->data.blend.alpha, - &spec->data.blend.color); - - *color = spec->data.blend.color; - } - break; - - case META_COLOR_SPEC_SHADE: - { - meta_color_spec_render (spec->data.shade.base, widget, - &spec->data.shade.color); - - gtk_style_shade (&spec->data.shade.color, - &spec->data.shade.color, spec->data.shade.factor); - - *color = spec->data.shade.color; - } - break; - } -} - -/** - * Represents an operation as a string. - * - * \param type an operation, such as addition - * \return a string, such as "+" - */ -static const char* -op_name (PosOperatorType type) -{ - switch (type) - { - case POS_OP_ADD: - return "+"; - case POS_OP_SUBTRACT: - return "-"; - case POS_OP_MULTIPLY: - return "*"; - case POS_OP_DIVIDE: - return "/"; - case POS_OP_MOD: - return "%"; - case POS_OP_MAX: - return "`max`"; - case POS_OP_MIN: - return "`min`"; - case POS_OP_NONE: - break; - } - - return "<unknown>"; -} - -/** - * Parses a string and returns an operation. - * - * \param p a pointer into a string representing an operation; part of an - * expression somewhere, so not null-terminated - * \param len set to the length of the string found. Set to 0 if none is. - * \return the operation found. If none was, returns POS_OP_NONE. - */ -static PosOperatorType -op_from_string (const char *p, - int *len) -{ - *len = 0; - - switch (*p) - { - case '+': - *len = 1; - return POS_OP_ADD; - case '-': - *len = 1; - return POS_OP_SUBTRACT; - case '*': - *len = 1; - return POS_OP_MULTIPLY; - case '/': - *len = 1; - return POS_OP_DIVIDE; - case '%': - *len = 1; - return POS_OP_MOD; - - case '`': - if (p[0] == '`' && - p[1] == 'm' && - p[2] == 'a' && - p[3] == 'x' && - p[4] == '`') - { - *len = 5; - return POS_OP_MAX; - } - else if (p[0] == '`' && - p[1] == 'm' && - p[2] == 'i' && - p[3] == 'n' && - p[4] == '`') - { - *len = 5; - return POS_OP_MIN; - } - } - - return POS_OP_NONE; -} - -/** - * Frees an array of tokens. All the tokens and their associated memory - * will be freed. - * - * \param tokens an array of tokens to be freed - * \param n_tokens how many tokens are in the array. - */ -static void -free_tokens (PosToken *tokens, - int n_tokens) -{ - int i; - - /* n_tokens can be 0 since tokens may have been allocated more than - * it was initialized - */ - - for (i = 0; i < n_tokens; i++) - if (tokens[i].type == POS_TOKEN_VARIABLE) - g_free (tokens[i].d.v.name); - - g_free (tokens); -} - -/** - * Tokenises a number in an expression. - * - * \param p a pointer into a string representing an operation; part of an - * expression somewhere, so not null-terminated - * \param end_return set to a pointer to the end of the number found; but - * not updated if no number was found at all - * \param next set to either an integer or a float token - * \param[out] err set to the problem if there was a problem - * \return TRUE if a valid number was found, FALSE otherwise (and "err" will - * have been set) - * - * \bug The "while (*start)..." part: what's wrong with strchr-ish things? - * \bug The name is wrong: it doesn't parse anything. - * \ingroup tokenizer - */ -static gboolean -parse_number (const char *p, - const char **end_return, - PosToken *next, - GError **err) -{ - const char *start = p; - char *end; - gboolean is_float; - char *num_str; - - while (*p && (*p == '.' || g_ascii_isdigit (*p))) - ++p; - - if (p == start) - { - char buf[7] = { '\0' }; - buf[g_unichar_to_utf8 (g_utf8_get_char (p), buf)] = '\0'; - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_BAD_CHARACTER, - _("Coordinate expression contains character '%s' which is not allowed"), - buf); - return FALSE; - } - - *end_return = p; - - /* we need this to exclude floats like "1e6" */ - num_str = g_strndup (start, p - start); - start = num_str; - is_float = FALSE; - while (*start) - { - if (*start == '.') - is_float = TRUE; - ++start; - } - - if (is_float) - { - next->type = POS_TOKEN_DOUBLE; - next->d.d.val = g_ascii_strtod (num_str, &end); - - if (end == num_str) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression contains floating point number '%s' which could not be parsed"), - num_str); - g_free (num_str); - return FALSE; - } - } - else - { - next->type = POS_TOKEN_INT; - next->d.i.val = strtol (num_str, &end, 10); - if (end == num_str) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression contains integer '%s' which could not be parsed"), - num_str); - g_free (num_str); - return FALSE; - } - } - - g_free (num_str); - - g_assert (next->type == POS_TOKEN_INT || next->type == POS_TOKEN_DOUBLE); - - return TRUE; -} - -/** - * Whether a variable can validly appear as part of the name of a variable. - */ -#define IS_VARIABLE_CHAR(c) (g_ascii_isalpha ((c)) || (c) == '_') - -#if 0 -static void -debug_print_tokens (PosToken *tokens, - int n_tokens) -{ - int i; - - for (i = 0; i < n_tokens; i++) - { - PosToken *t = &tokens[i]; - - g_print (" "); - - switch (t->type) - { - case POS_TOKEN_INT: - g_print ("\"%d\"", t->d.i.val); - break; - case POS_TOKEN_DOUBLE: - g_print ("\"%g\"", t->d.d.val); - break; - case POS_TOKEN_OPEN_PAREN: - g_print ("\"(\""); - break; - case POS_TOKEN_CLOSE_PAREN: - g_print ("\")\""); - break; - case POS_TOKEN_VARIABLE: - g_print ("\"%s\"", t->d.v.name); - break; - case POS_TOKEN_OPERATOR: - g_print ("\"%s\"", op_name (t->d.o.op)); - break; - } - } - - g_print ("\n"); -} -#endif - -/** - * Tokenises an expression. - * - * \param expr The expression - * \param[out] tokens_p The resulting tokens - * \param[out] n_tokens_p The number of resulting tokens - * \param[out] err set to the problem if there was a problem - * - * \return True if the expression was successfully tokenised; false otherwise. - * - * \ingroup tokenizer - */ -static gboolean -pos_tokenize (const char *expr, - PosToken **tokens_p, - int *n_tokens_p, - GError **err) -{ - PosToken *tokens; - int n_tokens; - int allocated; - const char *p; - - *tokens_p = NULL; - *n_tokens_p = 0; - - allocated = 3; - n_tokens = 0; - tokens = g_new (PosToken, allocated); - - p = expr; - while (*p) - { - PosToken *next; - int len; - - if (n_tokens == allocated) - { - allocated *= 2; - tokens = g_renew (PosToken, tokens, allocated); - } - - next = &tokens[n_tokens]; - - switch (*p) - { - case '*': - case '/': - case '+': - case '-': /* negative numbers aren't allowed so this is easy */ - case '%': - case '`': - next->type = POS_TOKEN_OPERATOR; - next->d.o.op = op_from_string (p, &len); - if (next->d.o.op != POS_OP_NONE) - { - ++n_tokens; - p = p + (len - 1); /* -1 since we ++p later */ - } - else - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression contained unknown operator at the start of this text: \"%s\""), - p); - - goto error; - } - break; - - case '(': - next->type = POS_TOKEN_OPEN_PAREN; - ++n_tokens; - break; - - case ')': - next->type = POS_TOKEN_CLOSE_PAREN; - ++n_tokens; - break; - - case ' ': - case '\t': - case '\n': - break; - - default: - if (IS_VARIABLE_CHAR (*p)) - { - /* Assume variable */ - const char *start = p; - while (*p && IS_VARIABLE_CHAR (*p)) - ++p; - g_assert (p != start); - next->type = POS_TOKEN_VARIABLE; - next->d.v.name = g_strndup (start, p - start); - ++n_tokens; - --p; /* since we ++p again at the end of while loop */ - } - else - { - /* Assume number */ - const char *end; - - if (!parse_number (p, &end, next, err)) - goto error; - - ++n_tokens; - p = end - 1; /* -1 since we ++p again at the end of while loop */ - } - - break; - } - - ++p; - } - - if (n_tokens == 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression was empty or not understood")); - - goto error; - } - - *tokens_p = tokens; - *n_tokens_p = n_tokens; - - return TRUE; - - error: - g_assert (err == NULL || *err != NULL); - - free_tokens (tokens, n_tokens); - return FALSE; -} - -/** - * The type of a PosExpr: either integer, double, or an operation. - * \ingroup parser - */ -typedef enum -{ - POS_EXPR_INT, - POS_EXPR_DOUBLE, - POS_EXPR_OPERATOR -} PosExprType; - -/** - * Type and value of an expression in a parsed sequence. We don't - * keep expressions in a tree; if this is of type POS_EXPR_OPERATOR, - * the arguments of the operator will be in the array positions - * immediately preceding and following this operator; they cannot - * themselves be operators. - * - * \bug operator is char; it should really be of PosOperatorType. - * \ingroup parser - */ -typedef struct -{ - PosExprType type; - union - { - double double_val; - int int_val; - char operator; - } d; -} PosExpr; - -#if 0 -static void -debug_print_exprs (PosExpr *exprs, - int n_exprs) -{ - int i; - - for (i = 0; i < n_exprs; i++) - { - switch (exprs[i].type) - { - case POS_EXPR_INT: - g_print (" %d", exprs[i].d.int_val); - break; - case POS_EXPR_DOUBLE: - g_print (" %g", exprs[i].d.double_val); - break; - case POS_EXPR_OPERATOR: - g_print (" %s", op_name (exprs[i].d.operator)); - break; - } - } - g_print ("\n"); -} -#endif - -static gboolean -do_operation (PosExpr *a, - PosExpr *b, - PosOperatorType op, - GError **err) -{ - /* Promote types to double if required */ - if (a->type == POS_EXPR_DOUBLE || - b->type == POS_EXPR_DOUBLE) - { - if (a->type != POS_EXPR_DOUBLE) - { - a->type = POS_EXPR_DOUBLE; - a->d.double_val = a->d.int_val; - } - if (b->type != POS_EXPR_DOUBLE) - { - b->type = POS_EXPR_DOUBLE; - b->d.double_val = b->d.int_val; - } - } - - g_assert (a->type == b->type); - - if (a->type == POS_EXPR_INT) - { - switch (op) - { - case POS_OP_MULTIPLY: - a->d.int_val = a->d.int_val * b->d.int_val; - break; - case POS_OP_DIVIDE: - if (b->d.int_val == 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_DIVIDE_BY_ZERO, - _("Coordinate expression results in division by zero")); - return FALSE; - } - a->d.int_val = a->d.int_val / b->d.int_val; - break; - case POS_OP_MOD: - if (b->d.int_val == 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_DIVIDE_BY_ZERO, - _("Coordinate expression results in division by zero")); - return FALSE; - } - a->d.int_val = a->d.int_val % b->d.int_val; - break; - case POS_OP_ADD: - a->d.int_val = a->d.int_val + b->d.int_val; - break; - case POS_OP_SUBTRACT: - a->d.int_val = a->d.int_val - b->d.int_val; - break; - case POS_OP_MAX: - a->d.int_val = MAX (a->d.int_val, b->d.int_val); - break; - case POS_OP_MIN: - a->d.int_val = MIN (a->d.int_val, b->d.int_val); - break; - case POS_OP_NONE: - g_assert_not_reached (); - break; - } - } - else if (a->type == POS_EXPR_DOUBLE) - { - switch (op) - { - case POS_OP_MULTIPLY: - a->d.double_val = a->d.double_val * b->d.double_val; - break; - case POS_OP_DIVIDE: - if (b->d.double_val == 0.0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_DIVIDE_BY_ZERO, - _("Coordinate expression results in division by zero")); - return FALSE; - } - a->d.double_val = a->d.double_val / b->d.double_val; - break; - case POS_OP_MOD: - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_MOD_ON_FLOAT, - _("Coordinate expression tries to use mod operator on a floating-point number")); - return FALSE; - case POS_OP_ADD: - a->d.double_val = a->d.double_val + b->d.double_val; - break; - case POS_OP_SUBTRACT: - a->d.double_val = a->d.double_val - b->d.double_val; - break; - case POS_OP_MAX: - a->d.double_val = MAX (a->d.double_val, b->d.double_val); - break; - case POS_OP_MIN: - a->d.double_val = MIN (a->d.double_val, b->d.double_val); - break; - case POS_OP_NONE: - g_assert_not_reached (); - break; - } - } - else - g_assert_not_reached (); - - return TRUE; -} - -static gboolean -do_operations (PosExpr *exprs, - int *n_exprs, - int precedence, - GError **err) -{ - int i; - -#if 0 - g_print ("Doing prec %d ops on %d exprs\n", precedence, *n_exprs); - debug_print_exprs (exprs, *n_exprs); -#endif - - i = 1; - while (i < *n_exprs) - { - gboolean compress; - - /* exprs[i-1] first operand - * exprs[i] operator - * exprs[i+1] second operand - * - * we replace first operand with result of mul/div/mod, - * or skip over operator and second operand if we have - * an add/subtract - */ - - if (exprs[i-1].type == POS_EXPR_OPERATOR) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression has an operator \"%s\" where an operand was expected"), - op_name (exprs[i-1].d.operator)); - return FALSE; - } - - if (exprs[i].type != POS_EXPR_OPERATOR) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression had an operand where an operator was expected")); - return FALSE; - } - - if (i == (*n_exprs - 1)) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression ended with an operator instead of an operand")); - return FALSE; - } - - g_assert ((i+1) < *n_exprs); - - if (exprs[i+1].type == POS_EXPR_OPERATOR) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression has operator \"%c\" following operator \"%c\" with no operand in between"), - exprs[i+1].d.operator, - exprs[i].d.operator); - return FALSE; - } - - compress = FALSE; - - switch (precedence) - { - case 2: - switch (exprs[i].d.operator) - { - case POS_OP_DIVIDE: - case POS_OP_MOD: - case POS_OP_MULTIPLY: - compress = TRUE; - if (!do_operation (&exprs[i-1], &exprs[i+1], - exprs[i].d.operator, - err)) - return FALSE; - break; - } - break; - case 1: - switch (exprs[i].d.operator) - { - case POS_OP_ADD: - case POS_OP_SUBTRACT: - compress = TRUE; - if (!do_operation (&exprs[i-1], &exprs[i+1], - exprs[i].d.operator, - err)) - return FALSE; - break; - } - break; - /* I have no rationale at all for making these low-precedence */ - case 0: - switch (exprs[i].d.operator) - { - case POS_OP_MAX: - case POS_OP_MIN: - compress = TRUE; - if (!do_operation (&exprs[i-1], &exprs[i+1], - exprs[i].d.operator, - err)) - return FALSE; - break; - } - break; - } - - if (compress) - { - /* exprs[i-1] first operand (now result) - * exprs[i] operator - * exprs[i+1] second operand - * exprs[i+2] new operator - * - * we move new operator just after first operand - */ - if ((i+2) < *n_exprs) - { - g_memmove (&exprs[i], &exprs[i+2], - sizeof (PosExpr) * (*n_exprs - i - 2)); - } - - *n_exprs -= 2; - } - else - { - /* Skip operator and next operand */ - i += 2; - } - } - - return TRUE; -} - -/** - * There is a predefined set of variables which can appear in an expression. - * Here we take a token representing a variable, and return the current value - * of that variable in a particular environment. - * (The value is always an integer.) - * - * There are supposedly some circumstances in which this function can be - * called from outside Metacity, in which case env->theme will be NULL, and - * therefore we can't use it to find out quark values, so we do the comparison - * using strcmp, which is slower. - * - * \param t The token representing a variable - * \param[out] result The value of that variable; not set if the token did - * not represent a known variable - * \param env The environment within which t should be evaluated - * \param[out] err set to the problem if there was a problem - * - * \return true if we found the variable asked for, false if we didn't - * - * \bug shouldn't t be const? - * \bug we should perhaps consider some sort of lookup arrangement into an - * array; also, the duplication of code is unlovely; perhaps using glib - * string hashes instead of quarks would fix both problems? - * \ingroup parser - */ -static gboolean -pos_eval_get_variable (PosToken *t, - int *result, - const MetaPositionExprEnv *env, - GError **err) -{ - if (env->theme) - { - if (t->d.v.name_quark == env->theme->quark_width) - *result = env->rect.width; - else if (t->d.v.name_quark == env->theme->quark_height) - *result = env->rect.height; - else if (env->object_width >= 0 && - t->d.v.name_quark == env->theme->quark_object_width) - *result = env->object_width; - else if (env->object_height >= 0 && - t->d.v.name_quark == env->theme->quark_object_height) - *result = env->object_height; - else if (t->d.v.name_quark == env->theme->quark_left_width) - *result = env->left_width; - else if (t->d.v.name_quark == env->theme->quark_right_width) - *result = env->right_width; - else if (t->d.v.name_quark == env->theme->quark_top_height) - *result = env->top_height; - else if (t->d.v.name_quark == env->theme->quark_bottom_height) - *result = env->bottom_height; - else if (t->d.v.name_quark == env->theme->quark_mini_icon_width) - *result = env->mini_icon_width; - else if (t->d.v.name_quark == env->theme->quark_mini_icon_height) - *result = env->mini_icon_height; - else if (t->d.v.name_quark == env->theme->quark_icon_width) - *result = env->icon_width; - else if (t->d.v.name_quark == env->theme->quark_icon_height) - *result = env->icon_height; - else if (t->d.v.name_quark == env->theme->quark_title_width) - *result = env->title_width; - else if (t->d.v.name_quark == env->theme->quark_title_height) - *result = env->title_height; - else - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_UNKNOWN_VARIABLE, - _("Coordinate expression had unknown variable or constant \"%s\""), - t->d.v.name); - return FALSE; - } - } - else - { - if (strcmp (t->d.v.name, "width") == 0) - *result = env->rect.width; - else if (strcmp (t->d.v.name, "height") == 0) - *result = env->rect.height; - else if (env->object_width >= 0 && - strcmp (t->d.v.name, "object_width") == 0) - *result = env->object_width; - else if (env->object_height >= 0 && - strcmp (t->d.v.name, "object_height") == 0) - *result = env->object_height; - else if (strcmp (t->d.v.name, "left_width") == 0) - *result = env->left_width; - else if (strcmp (t->d.v.name, "right_width") == 0) - *result = env->right_width; - else if (strcmp (t->d.v.name, "top_height") == 0) - *result = env->top_height; - else if (strcmp (t->d.v.name, "bottom_height") == 0) - *result = env->bottom_height; - else if (strcmp (t->d.v.name, "mini_icon_width") == 0) - *result = env->mini_icon_width; - else if (strcmp (t->d.v.name, "mini_icon_height") == 0) - *result = env->mini_icon_height; - else if (strcmp (t->d.v.name, "icon_width") == 0) - *result = env->icon_width; - else if (strcmp (t->d.v.name, "icon_height") == 0) - *result = env->icon_height; - else if (strcmp (t->d.v.name, "title_width") == 0) - *result = env->title_width; - else if (strcmp (t->d.v.name, "title_height") == 0) - *result = env->title_height; - else - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_UNKNOWN_VARIABLE, - _("Coordinate expression had unknown variable or constant \"%s\""), - t->d.v.name); - return FALSE; - } - } - - return TRUE; -} - -/** - * Evaluates a sequence of tokens within a particular environment context, - * and returns the current value. May recur if parantheses are found. - * - * \param tokens A list of tokens to evaluate. - * \param n_tokens How many tokens are in the list. - * \param env The environment context in which to evaluate the expression. - * \param[out] result The current value of the expression - * - * \bug Yes, we really do reparse the expression every time it's evaluated. - * We should keep the parse tree around all the time and just - * run the new values through it. - * \ingroup parser - */ -static gboolean -pos_eval_helper (PosToken *tokens, - int n_tokens, - const MetaPositionExprEnv *env, - PosExpr *result, - GError **err) -{ - /* Lazy-ass hardcoded limit on number of terms in expression */ -#define MAX_EXPRS 32 - int paren_level; - int first_paren; - int i; - PosExpr exprs[MAX_EXPRS]; - int n_exprs; - int precedence; - - /* Our first goal is to get a list of PosExpr, essentially - * substituting variables and handling parentheses. - */ - - first_paren = 0; - paren_level = 0; - n_exprs = 0; - for (i = 0; i < n_tokens; i++) - { - PosToken *t = &tokens[i]; - - if (n_exprs >= MAX_EXPRS) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression parser overflowed its buffer.")); - return FALSE; - } - - if (paren_level == 0) - { - switch (t->type) - { - case POS_TOKEN_INT: - exprs[n_exprs].type = POS_EXPR_INT; - exprs[n_exprs].d.int_val = t->d.i.val; - ++n_exprs; - break; - - case POS_TOKEN_DOUBLE: - exprs[n_exprs].type = POS_EXPR_DOUBLE; - exprs[n_exprs].d.double_val = t->d.d.val; - ++n_exprs; - break; - - case POS_TOKEN_OPEN_PAREN: - ++paren_level; - if (paren_level == 1) - first_paren = i; - break; - - case POS_TOKEN_CLOSE_PAREN: - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_BAD_PARENS, - _("Coordinate expression had a close parenthesis with no open parenthesis")); - return FALSE; - - case POS_TOKEN_VARIABLE: - exprs[n_exprs].type = POS_EXPR_INT; - - /* FIXME we should just dump all this crap - * in a hash, maybe keep width/height out - * for optimization purposes - */ - if (!pos_eval_get_variable (t, &exprs[n_exprs].d.int_val, env, err)) - return FALSE; - - ++n_exprs; - break; - - case POS_TOKEN_OPERATOR: - exprs[n_exprs].type = POS_EXPR_OPERATOR; - exprs[n_exprs].d.operator = t->d.o.op; - ++n_exprs; - break; - } - } - else - { - g_assert (paren_level > 0); - - switch (t->type) - { - case POS_TOKEN_INT: - case POS_TOKEN_DOUBLE: - case POS_TOKEN_VARIABLE: - case POS_TOKEN_OPERATOR: - break; - - case POS_TOKEN_OPEN_PAREN: - ++paren_level; - break; - - case POS_TOKEN_CLOSE_PAREN: - if (paren_level == 1) - { - /* We closed a toplevel paren group, so recurse */ - if (!pos_eval_helper (&tokens[first_paren+1], - i - first_paren - 1, - env, - &exprs[n_exprs], - err)) - return FALSE; - - ++n_exprs; - } - - --paren_level; - break; - - } - } - } - - if (paren_level > 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_BAD_PARENS, - _("Coordinate expression had an open parenthesis with no close parenthesis")); - return FALSE; - } - - /* Now we have no parens and no vars; so we just do all the multiplies - * and divides, then all the add and subtract. - */ - if (n_exprs == 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression doesn't seem to have any operators or operands")); - return FALSE; - } - - /* precedence 1 ops */ - precedence = 2; - while (precedence >= 0) - { - if (!do_operations (exprs, &n_exprs, precedence, err)) - return FALSE; - --precedence; - } - - g_assert (n_exprs == 1); - - *result = *exprs; - - return TRUE; -} - -/* - * expr = int | double | expr * expr | expr / expr | - * expr + expr | expr - expr | (expr) - * - * so very not worth fooling with bison, yet so very painful by hand. - */ -/** - * Evaluates an expression. - * - * \param spec The expression to evaluate. - * \param env The environment context to evaluate the expression in. - * \param[out] val_p The integer value of the expression; if the expression - * is of type float, this will be rounded. If we return - * FALSE because the expression is invalid, this will be - * zero. - * \param[out] err The error, if anything went wrong. - * - * \return True if we evaluated the expression successfully; false otherwise. - * - * \bug Shouldn't spec be const? - * \ingroup parser - */ -static gboolean -pos_eval (MetaDrawSpec *spec, - const MetaPositionExprEnv *env, - int *val_p, - GError **err) -{ - PosExpr expr; - - *val_p = 0; - - if (pos_eval_helper (spec->tokens, spec->n_tokens, env, &expr, err)) - { - switch (expr.type) - { - case POS_EXPR_INT: - *val_p = expr.d.int_val; - break; - case POS_EXPR_DOUBLE: - *val_p = expr.d.double_val; - break; - case POS_EXPR_OPERATOR: - g_assert_not_reached (); - break; - } - return TRUE; - } - else - { - return FALSE; - } -} - -/* We always return both X and Y, but only one will be meaningful in - * most contexts. - */ - -gboolean -meta_parse_position_expression (MetaDrawSpec *spec, - const MetaPositionExprEnv *env, - int *x_return, - int *y_return, - GError **err) -{ - /* All positions are in a coordinate system with x, y at the origin. - * The expression can have -, +, *, / as operators, floating point - * or integer constants, and the variables "width" and "height" and - * optionally "object_width" and object_height". Negative numbers - * aren't allowed. - */ - int val; - - if (spec->constant) - val = spec->value; - else - { - if (pos_eval (spec, env, &spec->value, err) == FALSE) - { - g_assert (err == NULL || *err != NULL); - return FALSE; - } - - val = spec->value; - } - - if (x_return) - *x_return = env->rect.x + val; - if (y_return) - *y_return = env->rect.y + val; - - return TRUE; -} - - -gboolean -meta_parse_size_expression (MetaDrawSpec *spec, - const MetaPositionExprEnv *env, - int *val_return, - GError **err) -{ - int val; - - if (spec->constant) - val = spec->value; - else - { - if (pos_eval (spec, env, &spec->value, err) == FALSE) - { - g_assert (err == NULL || *err != NULL); - return FALSE; - } - - val = spec->value; - } - - if (val_return) - *val_return = MAX (val, 1); /* require that sizes be at least 1x1 */ - - return TRUE; -} - -/* To do this we tokenize, replace variable tokens - * that are constants, then reassemble. The purpose - * here is to optimize expressions so we don't do hash - * lookups to eval them. Obviously it's a tradeoff that - * slows down theme load times. - */ -gboolean -meta_theme_replace_constants (MetaTheme *theme, - PosToken *tokens, - int n_tokens, - GError **err) -{ - int i; - double dval; - int ival; - gboolean is_constant = TRUE; - - /* Loop through tokenized string looking for variables to replace */ - for (i = 0; i < n_tokens; i++) - { - PosToken *t = &tokens[i]; - - if (t->type == POS_TOKEN_VARIABLE) - { - if (meta_theme_lookup_int_constant (theme, t->d.v.name, &ival)) - { - t->type = POS_TOKEN_INT; - t->d.i.val = ival; - } - else if (meta_theme_lookup_float_constant (theme, t->d.v.name, &dval)) - { - t->type = POS_TOKEN_DOUBLE; - t->d.d.val = dval; - } - else - { - /* If we've found a variable that cannot be replaced then the - expression is not a constant expression and we want to - replace it with a GQuark */ - - t->d.v.name_quark = g_quark_from_string (t->d.v.name); - is_constant = FALSE; - } - } - } - - return is_constant; -} - -static int -parse_x_position_unchecked (MetaDrawSpec *spec, - const MetaPositionExprEnv *env) -{ - int retval; - GError *error; - - retval = 0; - error = NULL; - if (!meta_parse_position_expression (spec, env, &retval, NULL, &error)) - { - meta_warning (_("Theme contained an expression that resulted in an error: %s\n"), - error->message); - - g_error_free (error); - } - - return retval; -} - -static int -parse_y_position_unchecked (MetaDrawSpec *spec, - const MetaPositionExprEnv *env) -{ - int retval; - GError *error; - - retval = 0; - error = NULL; - if (!meta_parse_position_expression (spec, env, NULL, &retval, &error)) - { - meta_warning (_("Theme contained an expression that resulted in an error: %s\n"), - error->message); - - g_error_free (error); - } - - return retval; -} - -static int -parse_size_unchecked (MetaDrawSpec *spec, - MetaPositionExprEnv *env) -{ - int retval; - GError *error; - - retval = 0; - error = NULL; - if (!meta_parse_size_expression (spec, env, &retval, &error)) - { - meta_warning (_("Theme contained an expression that resulted in an error: %s\n"), - error->message); - - g_error_free (error); - } - - return retval; -} - -void -meta_draw_spec_free (MetaDrawSpec *spec) -{ - free_tokens (spec->tokens, spec->n_tokens); - g_slice_free (MetaDrawSpec, spec); -} - -MetaDrawSpec * -meta_draw_spec_new (MetaTheme *theme, - const char *expr, - GError **error) -{ - MetaDrawSpec *spec; - - spec = g_slice_new0 (MetaDrawSpec); - - pos_tokenize (expr, &spec->tokens, &spec->n_tokens, NULL); - - spec->constant = meta_theme_replace_constants (theme, spec->tokens, - spec->n_tokens, NULL); - if (spec->constant) - { - gboolean result; - - result = pos_eval (spec, NULL, &spec->value, error); - if (result == FALSE) - { - meta_draw_spec_free (spec); - return NULL; - } - } - - return spec; -} - -MetaDrawOp* -meta_draw_op_new (MetaDrawType type) -{ - MetaDrawOp *op; - MetaDrawOp dummy; - int size; - - size = G_STRUCT_OFFSET (MetaDrawOp, data); - - switch (type) - { - case META_DRAW_LINE: - size += sizeof (dummy.data.line); - break; - - case META_DRAW_RECTANGLE: - size += sizeof (dummy.data.rectangle); - break; - - case META_DRAW_ARC: - size += sizeof (dummy.data.arc); - break; - - case META_DRAW_CLIP: - size += sizeof (dummy.data.clip); - break; - - case META_DRAW_TINT: - size += sizeof (dummy.data.tint); - break; - - case META_DRAW_GRADIENT: - size += sizeof (dummy.data.gradient); - break; - - case META_DRAW_IMAGE: - size += sizeof (dummy.data.image); - break; - - case META_DRAW_GTK_ARROW: - size += sizeof (dummy.data.gtk_arrow); - break; - - case META_DRAW_GTK_BOX: - size += sizeof (dummy.data.gtk_box); - break; - - case META_DRAW_GTK_VLINE: - size += sizeof (dummy.data.gtk_vline); - break; - - case META_DRAW_ICON: - size += sizeof (dummy.data.icon); - break; - - case META_DRAW_TITLE: - size += sizeof (dummy.data.title); - break; - case META_DRAW_OP_LIST: - size += sizeof (dummy.data.op_list); - break; - case META_DRAW_TILE: - size += sizeof (dummy.data.tile); - break; - } - - op = g_malloc0 (size); - - op->type = type; - - return op; -} - -void -meta_draw_op_free (MetaDrawOp *op) -{ - g_return_if_fail (op != NULL); - - switch (op->type) - { - case META_DRAW_LINE: - if (op->data.line.color_spec) - meta_color_spec_free (op->data.line.color_spec); - - meta_draw_spec_free (op->data.line.x1); - meta_draw_spec_free (op->data.line.y1); - meta_draw_spec_free (op->data.line.x2); - meta_draw_spec_free (op->data.line.y2); - break; - - case META_DRAW_RECTANGLE: - if (op->data.rectangle.color_spec) - g_free (op->data.rectangle.color_spec); - - meta_draw_spec_free (op->data.rectangle.x); - meta_draw_spec_free (op->data.rectangle.y); - meta_draw_spec_free (op->data.rectangle.width); - meta_draw_spec_free (op->data.rectangle.height); - break; - - case META_DRAW_ARC: - if (op->data.arc.color_spec) - g_free (op->data.arc.color_spec); - - meta_draw_spec_free (op->data.arc.x); - meta_draw_spec_free (op->data.arc.y); - meta_draw_spec_free (op->data.arc.width); - meta_draw_spec_free (op->data.arc.height); - break; - - case META_DRAW_CLIP: - meta_draw_spec_free (op->data.clip.x); - meta_draw_spec_free (op->data.clip.y); - meta_draw_spec_free (op->data.clip.width); - meta_draw_spec_free (op->data.clip.height); - break; - - case META_DRAW_TINT: - if (op->data.tint.color_spec) - meta_color_spec_free (op->data.tint.color_spec); - - if (op->data.tint.alpha_spec) - meta_alpha_gradient_spec_free (op->data.tint.alpha_spec); - - meta_draw_spec_free (op->data.tint.x); - meta_draw_spec_free (op->data.tint.y); - meta_draw_spec_free (op->data.tint.width); - meta_draw_spec_free (op->data.tint.height); - break; - - case META_DRAW_GRADIENT: - if (op->data.gradient.gradient_spec) - meta_gradient_spec_free (op->data.gradient.gradient_spec); - - if (op->data.gradient.alpha_spec) - meta_alpha_gradient_spec_free (op->data.gradient.alpha_spec); - - meta_draw_spec_free (op->data.gradient.x); - meta_draw_spec_free (op->data.gradient.y); - meta_draw_spec_free (op->data.gradient.width); - meta_draw_spec_free (op->data.gradient.height); - break; - - case META_DRAW_IMAGE: - if (op->data.image.alpha_spec) - meta_alpha_gradient_spec_free (op->data.image.alpha_spec); - - if (op->data.image.pixbuf) - g_object_unref (G_OBJECT (op->data.image.pixbuf)); - - if (op->data.image.colorize_spec) - meta_color_spec_free (op->data.image.colorize_spec); - - if (op->data.image.colorize_cache_pixbuf) - g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf)); - - meta_draw_spec_free (op->data.image.x); - meta_draw_spec_free (op->data.image.y); - meta_draw_spec_free (op->data.image.width); - meta_draw_spec_free (op->data.image.height); - break; - - case META_DRAW_GTK_ARROW: - meta_draw_spec_free (op->data.gtk_arrow.x); - meta_draw_spec_free (op->data.gtk_arrow.y); - meta_draw_spec_free (op->data.gtk_arrow.width); - meta_draw_spec_free (op->data.gtk_arrow.height); - break; - - case META_DRAW_GTK_BOX: - meta_draw_spec_free (op->data.gtk_box.x); - meta_draw_spec_free (op->data.gtk_box.y); - meta_draw_spec_free (op->data.gtk_box.width); - meta_draw_spec_free (op->data.gtk_box.height); - break; - - case META_DRAW_GTK_VLINE: - meta_draw_spec_free (op->data.gtk_vline.x); - meta_draw_spec_free (op->data.gtk_vline.y1); - meta_draw_spec_free (op->data.gtk_vline.y2); - break; - - case META_DRAW_ICON: - if (op->data.icon.alpha_spec) - meta_alpha_gradient_spec_free (op->data.icon.alpha_spec); - - meta_draw_spec_free (op->data.icon.x); - meta_draw_spec_free (op->data.icon.y); - meta_draw_spec_free (op->data.icon.width); - meta_draw_spec_free (op->data.icon.height); - break; - - case META_DRAW_TITLE: - if (op->data.title.color_spec) - meta_color_spec_free (op->data.title.color_spec); - - meta_draw_spec_free (op->data.title.x); - meta_draw_spec_free (op->data.title.y); - break; - - case META_DRAW_OP_LIST: - if (op->data.op_list.op_list) - meta_draw_op_list_unref (op->data.op_list.op_list); - - meta_draw_spec_free (op->data.op_list.x); - meta_draw_spec_free (op->data.op_list.y); - meta_draw_spec_free (op->data.op_list.width); - meta_draw_spec_free (op->data.op_list.height); - break; - - case META_DRAW_TILE: - if (op->data.tile.op_list) - meta_draw_op_list_unref (op->data.tile.op_list); - - meta_draw_spec_free (op->data.tile.x); - meta_draw_spec_free (op->data.tile.y); - meta_draw_spec_free (op->data.tile.width); - meta_draw_spec_free (op->data.tile.height); - meta_draw_spec_free (op->data.tile.tile_xoffset); - meta_draw_spec_free (op->data.tile.tile_yoffset); - meta_draw_spec_free (op->data.tile.tile_width); - meta_draw_spec_free (op->data.tile.tile_height); - break; - } - - g_free (op); -} - -static GdkGC* -get_gc_for_primitive (GtkWidget *widget, - GdkDrawable *drawable, - MetaColorSpec *color_spec, - const GdkRectangle *clip, - int line_width) -{ - GdkGC *gc; - GdkGCValues values; - GdkColor color; - - meta_color_spec_render (color_spec, widget, &color); - - values.foreground = color; - - gdk_rgb_find_color (gdk_drawable_get_colormap (drawable), - &values.foreground); - - values.line_width = line_width; - - gc = gdk_gc_new_with_values (drawable, &values, - GDK_GC_FOREGROUND | GDK_GC_LINE_WIDTH); - - if (clip) - gdk_gc_set_clip_rectangle (gc, - (GdkRectangle*) clip); /* const cast */ - - return gc; -} - -static GdkPixbuf* -apply_alpha (GdkPixbuf *pixbuf, - MetaAlphaGradientSpec *spec, - gboolean force_copy) -{ - GdkPixbuf *new_pixbuf; - gboolean needs_alpha; - - g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); - - needs_alpha = spec && (spec->n_alphas > 1 || - spec->alphas[0] != 0xff); - - if (!needs_alpha) - return pixbuf; - - if (!gdk_pixbuf_get_has_alpha (pixbuf)) - { - new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = new_pixbuf; - } - else if (force_copy) - { - new_pixbuf = gdk_pixbuf_copy (pixbuf); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = new_pixbuf; - } - - g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); - - meta_gradient_add_alpha (pixbuf, spec->alphas, spec->n_alphas, spec->type); - - return pixbuf; -} - -static void -render_pixbuf (GdkDrawable *drawable, - const GdkRectangle *clip, - GdkPixbuf *pixbuf, - int x, - int y) -{ - /* grumble, render_to_drawable_alpha does not accept a clip - * mask, so we have to go through some BS - */ - /* FIXME once GTK 1.3.13 has been out a while we can use - * render_to_drawable() which now does alpha with clip. - * - * Though the gdk_rectangle_intersect() check may be a useful - * optimization anyway. - */ - GdkRectangle pixbuf_rect; - GdkRectangle draw_rect; - - pixbuf_rect.x = x; - pixbuf_rect.y = y; - pixbuf_rect.width = gdk_pixbuf_get_width (pixbuf); - pixbuf_rect.height = gdk_pixbuf_get_height (pixbuf); - - if (clip) - { - if (!gdk_rectangle_intersect ((GdkRectangle*)clip, - &pixbuf_rect, &draw_rect)) - return; - } - else - { - draw_rect = pixbuf_rect; - } - - gdk_draw_pixbuf (drawable, - NULL, - pixbuf, - draw_rect.x - pixbuf_rect.x, - draw_rect.y - pixbuf_rect.y, - draw_rect.x, draw_rect.y, - draw_rect.width, - draw_rect.height, - GDK_RGB_DITHER_NORMAL, - draw_rect.x - pixbuf_rect.x, - draw_rect.y - pixbuf_rect.y); -} - -static GdkPixbuf* -pixbuf_tile (GdkPixbuf *tile, - int width, - int height) -{ - GdkPixbuf *pixbuf; - int tile_width; - int tile_height; - int i, j; - - tile_width = gdk_pixbuf_get_width (tile); - tile_height = gdk_pixbuf_get_height (tile); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha (tile), - 8, width, height); - - i = 0; - while (i < width) - { - j = 0; - while (j < height) - { - int w, h; - - w = MIN (tile_width, width - i); - h = MIN (tile_height, height - j); - - gdk_pixbuf_copy_area (tile, - 0, 0, - w, h, - pixbuf, - i, j); - - j += tile_height; - } - - i += tile_width; - } - - return pixbuf; -} - -static GdkPixbuf * -replicate_rows (GdkPixbuf *src, - int src_x, - int src_y, - int width, - int height) -{ - unsigned int n_channels = gdk_pixbuf_get_n_channels (src); - unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src); - unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x - * n_channels); - unsigned char *dest_pixels; - GdkPixbuf *result; - unsigned int dest_rowstride; - int i; - - result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8, - width, height); - dest_rowstride = gdk_pixbuf_get_rowstride (result); - dest_pixels = gdk_pixbuf_get_pixels (result); - - for (i = 0; i < height; i++) - memcpy (dest_pixels + dest_rowstride * i, pixels, n_channels * width); - - return result; -} - -static GdkPixbuf * -replicate_cols (GdkPixbuf *src, - int src_x, - int src_y, - int width, - int height) -{ - unsigned int n_channels = gdk_pixbuf_get_n_channels (src); - unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src); - unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x - * n_channels); - unsigned char *dest_pixels; - GdkPixbuf *result; - unsigned int dest_rowstride; - int i, j; - - result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8, - width, height); - dest_rowstride = gdk_pixbuf_get_rowstride (result); - dest_pixels = gdk_pixbuf_get_pixels (result); - - for (i = 0; i < height; i++) - { - unsigned char *p = dest_pixels + dest_rowstride * i; - unsigned char *q = pixels + src_rowstride * i; - - unsigned char r = *(q++); - unsigned char g = *(q++); - unsigned char b = *(q++); - - if (n_channels == 4) - { - unsigned char a; - - a = *(q++); - - for (j = 0; j < width; j++) - { - *(p++) = r; - *(p++) = g; - *(p++) = b; - *(p++) = a; - } - } - else - { - for (j = 0; j < width; j++) - { - *(p++) = r; - *(p++) = g; - *(p++) = b; - } - } - } - - return result; -} - -static GdkPixbuf* -scale_and_alpha_pixbuf (GdkPixbuf *src, - MetaAlphaGradientSpec *alpha_spec, - MetaImageFillType fill_type, - int width, - int height, - gboolean vertical_stripes, - gboolean horizontal_stripes) -{ - GdkPixbuf *pixbuf; - GdkPixbuf *temp_pixbuf; - - pixbuf = NULL; - - pixbuf = src; - - if (gdk_pixbuf_get_width (pixbuf) == width && - gdk_pixbuf_get_height (pixbuf) == height) - { - g_object_ref (G_OBJECT (pixbuf)); - } - else - { - if (fill_type == META_IMAGE_FILL_TILE) - { - pixbuf = pixbuf_tile (pixbuf, width, height); - } - else - { - int src_h, src_w, dest_h, dest_w; - src_h = gdk_pixbuf_get_height (src); - src_w = gdk_pixbuf_get_width (src); - - /* prefer to replicate_cols if possible, as that - * is faster (no memory reads) - */ - if (horizontal_stripes) - { - dest_w = gdk_pixbuf_get_width (src); - dest_h = height; - } - else if (vertical_stripes) - { - dest_w = width; - dest_h = gdk_pixbuf_get_height (src); - } - - else - { - dest_w = width; - dest_h = height; - } - - if (dest_w == src_w && dest_h == src_h) - { - temp_pixbuf = src; - g_object_ref (G_OBJECT (temp_pixbuf)); - } - else - { - temp_pixbuf = gdk_pixbuf_scale_simple (src, - dest_w, dest_h, - GDK_INTERP_BILINEAR); - } - - /* prefer to replicate_cols if possible, as that - * is faster (no memory reads) - */ - if (horizontal_stripes) - { - pixbuf = replicate_cols (temp_pixbuf, 0, 0, width, height); - g_object_unref (G_OBJECT (temp_pixbuf)); - } - else if (vertical_stripes) - { - pixbuf = replicate_rows (temp_pixbuf, 0, 0, width, height); - g_object_unref (G_OBJECT (temp_pixbuf)); - } - else - { - pixbuf = temp_pixbuf; - } - } - } - - if (pixbuf) - pixbuf = apply_alpha (pixbuf, alpha_spec, pixbuf == src); - - return pixbuf; -} - -static GdkPixbuf* -draw_op_as_pixbuf (const MetaDrawOp *op, - GtkWidget *widget, - const MetaDrawInfo *info, - int width, - int height) -{ - /* Try to get the op as a pixbuf, assuming w/h in the op - * matches the width/height passed in. return NULL - * if the op can't be converted to an equivalent pixbuf. - */ - GdkPixbuf *pixbuf; - - pixbuf = NULL; - - switch (op->type) - { - case META_DRAW_LINE: - break; - - case META_DRAW_RECTANGLE: - if (op->data.rectangle.filled) - { - GdkColor color; - - meta_color_spec_render (op->data.rectangle.color_spec, - widget, - &color); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - FALSE, - 8, width, height); - - gdk_pixbuf_fill (pixbuf, GDK_COLOR_RGBA (color)); - } - break; - - case META_DRAW_ARC: - break; - - case META_DRAW_CLIP: - break; - - case META_DRAW_TINT: - { - GdkColor color; - guint32 rgba; - gboolean has_alpha; - - meta_color_spec_render (op->data.rectangle.color_spec, - widget, - &color); - - has_alpha = - op->data.tint.alpha_spec && - (op->data.tint.alpha_spec->n_alphas > 1 || - op->data.tint.alpha_spec->alphas[0] != 0xff); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - has_alpha, - 8, width, height); - - if (!has_alpha) - { - rgba = GDK_COLOR_RGBA (color); - - gdk_pixbuf_fill (pixbuf, rgba); - } - else if (op->data.tint.alpha_spec->n_alphas == 1) - { - rgba = GDK_COLOR_RGBA (color); - rgba &= ~0xff; - rgba |= op->data.tint.alpha_spec->alphas[0]; - - gdk_pixbuf_fill (pixbuf, rgba); - } - else - { - rgba = GDK_COLOR_RGBA (color); - - gdk_pixbuf_fill (pixbuf, rgba); - - meta_gradient_add_alpha (pixbuf, - op->data.tint.alpha_spec->alphas, - op->data.tint.alpha_spec->n_alphas, - op->data.tint.alpha_spec->type); - } - } - break; - - case META_DRAW_GRADIENT: - { - pixbuf = meta_gradient_spec_render (op->data.gradient.gradient_spec, - widget, width, height); - - pixbuf = apply_alpha (pixbuf, - op->data.gradient.alpha_spec, - FALSE); - } - break; - - - case META_DRAW_IMAGE: - { - if (op->data.image.colorize_spec) - { - GdkColor color; - - meta_color_spec_render (op->data.image.colorize_spec, - widget, &color); - - if (op->data.image.colorize_cache_pixbuf == NULL || - op->data.image.colorize_cache_pixel != GDK_COLOR_RGB (color)) - { - if (op->data.image.colorize_cache_pixbuf) - g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf)); - - /* const cast here */ - ((MetaDrawOp*)op)->data.image.colorize_cache_pixbuf = - colorize_pixbuf (op->data.image.pixbuf, - &color); - ((MetaDrawOp*)op)->data.image.colorize_cache_pixel = - GDK_COLOR_RGB (color); - } - - if (op->data.image.colorize_cache_pixbuf) - { - pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf, - op->data.image.alpha_spec, - op->data.image.fill_type, - width, height, - op->data.image.vertical_stripes, - op->data.image.horizontal_stripes); - } - } - else - { - pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf, - op->data.image.alpha_spec, - op->data.image.fill_type, - width, height, - op->data.image.vertical_stripes, - op->data.image.horizontal_stripes); - } - break; - } - - case META_DRAW_GTK_ARROW: - case META_DRAW_GTK_BOX: - case META_DRAW_GTK_VLINE: - break; - - case META_DRAW_ICON: - if (info->mini_icon && - width <= gdk_pixbuf_get_width (info->mini_icon) && - height <= gdk_pixbuf_get_height (info->mini_icon)) - pixbuf = scale_and_alpha_pixbuf (info->mini_icon, - op->data.icon.alpha_spec, - op->data.icon.fill_type, - width, height, - FALSE, FALSE); - else if (info->icon) - pixbuf = scale_and_alpha_pixbuf (info->icon, - op->data.icon.alpha_spec, - op->data.icon.fill_type, - width, height, - FALSE, FALSE); - break; - - case META_DRAW_TITLE: - break; - - case META_DRAW_OP_LIST: - break; - - case META_DRAW_TILE: - break; - } - - return pixbuf; -} - -static void -fill_env (MetaPositionExprEnv *env, - const MetaDrawInfo *info, - MetaRectangle logical_region) -{ - /* FIXME this stuff could be raised into draw_op_list_draw() probably - */ - env->rect = logical_region; - env->object_width = -1; - env->object_height = -1; - if (info->fgeom) - { - env->left_width = info->fgeom->left_width; - env->right_width = info->fgeom->right_width; - env->top_height = info->fgeom->top_height; - env->bottom_height = info->fgeom->bottom_height; - } - else - { - env->left_width = 0; - env->right_width = 0; - env->top_height = 0; - env->bottom_height = 0; - } - - env->mini_icon_width = info->mini_icon ? gdk_pixbuf_get_width (info->mini_icon) : 0; - env->mini_icon_height = info->mini_icon ? gdk_pixbuf_get_height (info->mini_icon) : 0; - env->icon_width = info->icon ? gdk_pixbuf_get_width (info->icon) : 0; - env->icon_height = info->icon ? gdk_pixbuf_get_height (info->icon) : 0; - - env->title_width = info->title_layout_width; - env->title_height = info->title_layout_height; - env->theme = meta_current_theme; -} - -static void -meta_draw_op_draw_with_env (const MetaDrawOp *op, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - const MetaDrawInfo *info, - MetaRectangle rect, - MetaPositionExprEnv *env) -{ - GdkGC *gc; - - switch (op->type) - { - case META_DRAW_LINE: - { - int x1, x2, y1, y2; - - gc = get_gc_for_primitive (widget, drawable, - op->data.line.color_spec, - clip, - op->data.line.width); - - if (op->data.line.dash_on_length > 0 && - op->data.line.dash_off_length > 0) - { - gint8 dash_list[2]; - dash_list[0] = op->data.line.dash_on_length; - dash_list[1] = op->data.line.dash_off_length; - gdk_gc_set_dashes (gc, 0, dash_list, 2); - } - - x1 = parse_x_position_unchecked (op->data.line.x1, env); - y1 = parse_y_position_unchecked (op->data.line.y1, env); - x2 = parse_x_position_unchecked (op->data.line.x2, env); - y2 = parse_y_position_unchecked (op->data.line.y2, env); - - gdk_draw_line (drawable, gc, x1, y1, x2, y2); - - g_object_unref (G_OBJECT (gc)); - } - break; - - case META_DRAW_RECTANGLE: - { - int rx, ry, rwidth, rheight; - - gc = get_gc_for_primitive (widget, drawable, - op->data.rectangle.color_spec, - clip, 0); - - rx = parse_x_position_unchecked (op->data.rectangle.x, env); - ry = parse_y_position_unchecked (op->data.rectangle.y, env); - rwidth = parse_size_unchecked (op->data.rectangle.width, env); - rheight = parse_size_unchecked (op->data.rectangle.height, env); - - gdk_draw_rectangle (drawable, gc, - op->data.rectangle.filled, - rx, ry, rwidth, rheight); - - g_object_unref (G_OBJECT (gc)); - } - break; - - case META_DRAW_ARC: - { - int rx, ry, rwidth, rheight; - - gc = get_gc_for_primitive (widget, drawable, - op->data.arc.color_spec, - clip, 0); - - rx = parse_x_position_unchecked (op->data.arc.x, env); - ry = parse_y_position_unchecked (op->data.arc.y, env); - rwidth = parse_size_unchecked (op->data.arc.width, env); - rheight = parse_size_unchecked (op->data.arc.height, env); - - gdk_draw_arc (drawable, - gc, - op->data.arc.filled, - rx, ry, rwidth, rheight, - op->data.arc.start_angle * (360.0 * 64.0) - - (90.0 * 64.0), /* start at 12 instead of 3 oclock */ - op->data.arc.extent_angle * (360.0 * 64.0)); - - g_object_unref (G_OBJECT (gc)); - } - break; - - case META_DRAW_CLIP: - break; - - case META_DRAW_TINT: - { - int rx, ry, rwidth, rheight; - gboolean needs_alpha; - - needs_alpha = op->data.tint.alpha_spec && - (op->data.tint.alpha_spec->n_alphas > 1 || - op->data.tint.alpha_spec->alphas[0] != 0xff); - - rx = parse_x_position_unchecked (op->data.tint.x, env); - ry = parse_y_position_unchecked (op->data.tint.y, env); - rwidth = parse_size_unchecked (op->data.tint.width, env); - rheight = parse_size_unchecked (op->data.tint.height, env); - - if (!needs_alpha) - { - gc = get_gc_for_primitive (widget, drawable, - op->data.tint.color_spec, - clip, 0); - - gdk_draw_rectangle (drawable, gc, - TRUE, - rx, ry, rwidth, rheight); - - g_object_unref (G_OBJECT (gc)); - } - else - { - GdkPixbuf *pixbuf; - - pixbuf = draw_op_as_pixbuf (op, widget, info, - rwidth, rheight); - - if (pixbuf) - { - render_pixbuf (drawable, clip, pixbuf, rx, ry); - - g_object_unref (G_OBJECT (pixbuf)); - } - } - } - break; - - case META_DRAW_GRADIENT: - { - int rx, ry, rwidth, rheight; - GdkPixbuf *pixbuf; - - rx = parse_x_position_unchecked (op->data.gradient.x, env); - ry = parse_y_position_unchecked (op->data.gradient.y, env); - rwidth = parse_size_unchecked (op->data.gradient.width, env); - rheight = parse_size_unchecked (op->data.gradient.height, env); - - pixbuf = draw_op_as_pixbuf (op, widget, info, - rwidth, rheight); - - if (pixbuf) - { - render_pixbuf (drawable, clip, pixbuf, rx, ry); - - g_object_unref (G_OBJECT (pixbuf)); - } - } - break; - - case META_DRAW_IMAGE: - { - int rx, ry, rwidth, rheight; - GdkPixbuf *pixbuf; - - if (op->data.image.pixbuf) - { - env->object_width = gdk_pixbuf_get_width (op->data.image.pixbuf); - env->object_height = gdk_pixbuf_get_height (op->data.image.pixbuf); - } - - rwidth = parse_size_unchecked (op->data.image.width, env); - rheight = parse_size_unchecked (op->data.image.height, env); - - pixbuf = draw_op_as_pixbuf (op, widget, info, - rwidth, rheight); - - if (pixbuf) - { - rx = parse_x_position_unchecked (op->data.image.x, env); - ry = parse_y_position_unchecked (op->data.image.y, env); - - render_pixbuf (drawable, clip, pixbuf, rx, ry); - - g_object_unref (G_OBJECT (pixbuf)); - } - } - break; - - case META_DRAW_GTK_ARROW: - { - int rx, ry, rwidth, rheight; - - rx = parse_x_position_unchecked (op->data.gtk_arrow.x, env); - ry = parse_y_position_unchecked (op->data.gtk_arrow.y, env); - rwidth = parse_size_unchecked (op->data.gtk_arrow.width, env); - rheight = parse_size_unchecked (op->data.gtk_arrow.height, env); - - gtk_paint_arrow (widget->style, - drawable, - op->data.gtk_arrow.state, - op->data.gtk_arrow.shadow, - (GdkRectangle*) clip, - widget, - "metacity", - op->data.gtk_arrow.arrow, - op->data.gtk_arrow.filled, - rx, ry, rwidth, rheight); - } - break; - - case META_DRAW_GTK_BOX: - { - int rx, ry, rwidth, rheight; - - rx = parse_x_position_unchecked (op->data.gtk_box.x, env); - ry = parse_y_position_unchecked (op->data.gtk_box.y, env); - rwidth = parse_size_unchecked (op->data.gtk_box.width, env); - rheight = parse_size_unchecked (op->data.gtk_box.height, env); - - gtk_paint_box (widget->style, - drawable, - op->data.gtk_box.state, - op->data.gtk_box.shadow, - (GdkRectangle*) clip, - widget, - "metacity", - rx, ry, rwidth, rheight); - } - break; - - case META_DRAW_GTK_VLINE: - { - int rx, ry1, ry2; - - rx = parse_x_position_unchecked (op->data.gtk_vline.x, env); - ry1 = parse_y_position_unchecked (op->data.gtk_vline.y1, env); - ry2 = parse_y_position_unchecked (op->data.gtk_vline.y2, env); - - gtk_paint_vline (widget->style, - drawable, - op->data.gtk_vline.state, - (GdkRectangle*) clip, - widget, - "metacity", - ry1, ry2, rx); - } - break; - - case META_DRAW_ICON: - { - int rx, ry, rwidth, rheight; - GdkPixbuf *pixbuf; - - rwidth = parse_size_unchecked (op->data.icon.width, env); - rheight = parse_size_unchecked (op->data.icon.height, env); - - pixbuf = draw_op_as_pixbuf (op, widget, info, - rwidth, rheight); - - if (pixbuf) - { - rx = parse_x_position_unchecked (op->data.icon.x, env); - ry = parse_y_position_unchecked (op->data.icon.y, env); - - render_pixbuf (drawable, clip, pixbuf, rx, ry); - - g_object_unref (G_OBJECT (pixbuf)); - } - } - break; - - case META_DRAW_TITLE: - if (info->title_layout) - { - int rx, ry; - - gc = get_gc_for_primitive (widget, drawable, - op->data.title.color_spec, - clip, 0); - - rx = parse_x_position_unchecked (op->data.title.x, env); - ry = parse_y_position_unchecked (op->data.title.y, env); - - gdk_draw_layout (drawable, gc, - rx, ry, - info->title_layout); - - g_object_unref (G_OBJECT (gc)); - } - break; - - case META_DRAW_OP_LIST: - { - MetaRectangle d_rect; - - d_rect.x = parse_x_position_unchecked (op->data.op_list.x, env); - d_rect.y = parse_y_position_unchecked (op->data.op_list.y, env); - d_rect.width = parse_size_unchecked (op->data.op_list.width, env); - d_rect.height = parse_size_unchecked (op->data.op_list.height, env); - - meta_draw_op_list_draw (op->data.op_list.op_list, - widget, drawable, clip, info, - d_rect); - } - break; - - case META_DRAW_TILE: - { - int rx, ry, rwidth, rheight; - int tile_xoffset, tile_yoffset; - GdkRectangle new_clip; - MetaRectangle tile; - - rx = parse_x_position_unchecked (op->data.tile.x, env); - ry = parse_y_position_unchecked (op->data.tile.y, env); - rwidth = parse_size_unchecked (op->data.tile.width, env); - rheight = parse_size_unchecked (op->data.tile.height, env); - - new_clip.x = rx; - new_clip.y = ry; - new_clip.width = rwidth; - new_clip.height = rheight; - - if (clip == NULL || gdk_rectangle_intersect ((GdkRectangle*)clip, &new_clip, - &new_clip)) - { - tile_xoffset = parse_x_position_unchecked (op->data.tile.tile_xoffset, env); - tile_yoffset = parse_y_position_unchecked (op->data.tile.tile_yoffset, env); - /* tile offset should not include x/y */ - tile_xoffset -= rect.x; - tile_yoffset -= rect.y; - - tile.width = parse_size_unchecked (op->data.tile.tile_width, env); - tile.height = parse_size_unchecked (op->data.tile.tile_height, env); - - tile.x = rx - tile_xoffset; - - while (tile.x < (rx + rwidth)) - { - tile.y = ry - tile_yoffset; - while (tile.y < (ry + rheight)) - { - meta_draw_op_list_draw (op->data.tile.op_list, - widget, drawable, &new_clip, info, - tile); - - tile.y += tile.height; - } - - tile.x += tile.width; - } - } - } - break; - } -} - -void -meta_draw_op_draw (const MetaDrawOp *op, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - const MetaDrawInfo *info, - MetaRectangle logical_region) -{ - MetaPositionExprEnv env; - - fill_env (&env, info, logical_region); - - meta_draw_op_draw_with_env (op, widget, drawable, clip, - info, logical_region, - &env); - -} - -MetaDrawOpList* -meta_draw_op_list_new (int n_preallocs) -{ - MetaDrawOpList *op_list; - - g_return_val_if_fail (n_preallocs >= 0, NULL); - - op_list = g_new (MetaDrawOpList, 1); - - op_list->refcount = 1; - op_list->n_allocated = n_preallocs; - op_list->ops = g_new (MetaDrawOp*, op_list->n_allocated); - op_list->n_ops = 0; - - return op_list; -} - -void -meta_draw_op_list_ref (MetaDrawOpList *op_list) -{ - g_return_if_fail (op_list != NULL); - - op_list->refcount += 1; -} - -void -meta_draw_op_list_unref (MetaDrawOpList *op_list) -{ - g_return_if_fail (op_list != NULL); - g_return_if_fail (op_list->refcount > 0); - - op_list->refcount -= 1; - - if (op_list->refcount == 0) - { - int i; - - for (i = 0; i < op_list->n_ops; i++) - meta_draw_op_free (op_list->ops[i]); - - g_free (op_list->ops); - - DEBUG_FILL_STRUCT (op_list); - g_free (op_list); - } -} - -void -meta_draw_op_list_draw (const MetaDrawOpList *op_list, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - const MetaDrawInfo *info, - MetaRectangle rect) -{ - int i; - GdkRectangle active_clip; - GdkRectangle orig_clip; - MetaPositionExprEnv env; - - if (op_list->n_ops == 0) - return; - - fill_env (&env, info, rect); - - /* FIXME this can be optimized, potentially a lot, by - * compressing multiple ops when possible. For example, - * anything convertible to a pixbuf can be composited - * client-side, and putting a color tint over a pixbuf - * can be done without creating the solid-color pixbuf. - * - * To implement this my plan is to have the idea of a - * compiled draw op (with the string expressions already - * evaluated), we make an array of those, and then fold - * adjacent items when possible. - */ - if (clip) - { - orig_clip = *clip; - } - else - { - orig_clip.x = rect.x; - orig_clip.y = rect.y; - orig_clip.width = rect.width; - orig_clip.height = rect.height; - } - - active_clip = orig_clip; - - for (i = 0; i < op_list->n_ops; i++) - { - MetaDrawOp *op = op_list->ops[i]; - - if (op->type == META_DRAW_CLIP) - { - active_clip.x = parse_x_position_unchecked (op->data.clip.x, &env); - active_clip.y = parse_y_position_unchecked (op->data.clip.y, &env); - active_clip.width = parse_size_unchecked (op->data.clip.width, &env); - active_clip.height = parse_size_unchecked (op->data.clip.height, &env); - - gdk_rectangle_intersect (&orig_clip, &active_clip, &active_clip); - } - else if (active_clip.width > 0 && - active_clip.height > 0) - { - meta_draw_op_draw_with_env (op, - widget, drawable, &active_clip, info, - rect, - &env); - } - } -} - -void -meta_draw_op_list_append (MetaDrawOpList *op_list, - MetaDrawOp *op) -{ - if (op_list->n_ops == op_list->n_allocated) - { - op_list->n_allocated *= 2; - op_list->ops = g_renew (MetaDrawOp*, op_list->ops, op_list->n_allocated); - } - - op_list->ops[op_list->n_ops] = op; - op_list->n_ops += 1; -} - -gboolean -meta_draw_op_list_validate (MetaDrawOpList *op_list, - GError **error) -{ - g_return_val_if_fail (op_list != NULL, FALSE); - - /* empty lists are OK, nothing else to check really */ - - return TRUE; -} - -/* This is not done in validate, since we wouldn't know the name - * of the list to report the error. It might be nice to - * store names inside the list sometime. - */ -gboolean -meta_draw_op_list_contains (MetaDrawOpList *op_list, - MetaDrawOpList *child) -{ - int i; - - /* mmm, huge tree recursion */ - - for (i = 0; i < op_list->n_ops; i++) - { - if (op_list->ops[i]->type == META_DRAW_OP_LIST) - { - if (op_list->ops[i]->data.op_list.op_list == child) - return TRUE; - - if (meta_draw_op_list_contains (op_list->ops[i]->data.op_list.op_list, - child)) - return TRUE; - } - else if (op_list->ops[i]->type == META_DRAW_TILE) - { - if (op_list->ops[i]->data.tile.op_list == child) - return TRUE; - - if (meta_draw_op_list_contains (op_list->ops[i]->data.tile.op_list, - child)) - return TRUE; - } - } - - return FALSE; -} - -/** - * Constructor for a MetaFrameStyle. - * - * \param parent The parent style. Data not filled in here will be - * looked for in the parent style, and in its parent - * style, and so on. - * - * \return The newly-constructed style. - */ -MetaFrameStyle* -meta_frame_style_new (MetaFrameStyle *parent) -{ - MetaFrameStyle *style; - - style = g_new0 (MetaFrameStyle, 1); - - style->refcount = 1; - - /* Default alpha is fully opaque */ - style->window_background_alpha = 255; - - style->parent = parent; - if (parent) - meta_frame_style_ref (parent); - - return style; -} - -/** - * Increases the reference count of a frame style. - * If the style is NULL, this is a no-op. - * - * \param style The style. - */ -void -meta_frame_style_ref (MetaFrameStyle *style) -{ - g_return_if_fail (style != NULL); - - style->refcount += 1; -} - -static void -free_button_ops (MetaDrawOpList *op_lists[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]) -{ - int i, j; - - for (i = 0; i < META_BUTTON_TYPE_LAST; i++) - for (j = 0; j < META_BUTTON_STATE_LAST; j++) - if (op_lists[i][j]) - meta_draw_op_list_unref (op_lists[i][j]); -} - -void -meta_frame_style_unref (MetaFrameStyle *style) -{ - g_return_if_fail (style != NULL); - g_return_if_fail (style->refcount > 0); - - style->refcount -= 1; - - if (style->refcount == 0) - { - int i; - - free_button_ops (style->buttons); - - for (i = 0; i < META_FRAME_PIECE_LAST; i++) - if (style->pieces[i]) - meta_draw_op_list_unref (style->pieces[i]); - - if (style->layout) - meta_frame_layout_unref (style->layout); - - if (style->window_background_color) - meta_color_spec_free (style->window_background_color); - - /* we hold a reference to any parent style */ - if (style->parent) - meta_frame_style_unref (style->parent); - - DEBUG_FILL_STRUCT (style); - g_free (style); - } -} - -static MetaDrawOpList* -get_button (MetaFrameStyle *style, - MetaButtonType type, - MetaButtonState state) -{ - MetaDrawOpList *op_list; - MetaFrameStyle *parent; - - parent = style; - op_list = NULL; - while (parent && op_list == NULL) - { - op_list = parent->buttons[type][state]; - parent = parent->parent; - } - - /* We fall back to middle button backgrounds if we don't - * have the ones on the sides - */ - - if (op_list == NULL && - (type == META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND || - type == META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND)) - return get_button (style, META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND, - state); - - if (op_list == NULL && - (type == META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND || - type == META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND)) - return get_button (style, META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND, - state); - - /* We fall back to normal if no prelight */ - if (op_list == NULL && - state == META_BUTTON_STATE_PRELIGHT) - return get_button (style, type, META_BUTTON_STATE_NORMAL); - - return op_list; -} - -gboolean -meta_frame_style_validate (MetaFrameStyle *style, - guint current_theme_version, - GError **error) -{ - int i, j; - - g_return_val_if_fail (style != NULL, FALSE); - g_return_val_if_fail (style->layout != NULL, FALSE); - - for (i = 0; i < META_BUTTON_TYPE_LAST; i++) - { - /* for now the "positional" buttons are optional */ - if (i >= META_BUTTON_TYPE_CLOSE) - { - for (j = 0; j < META_BUTTON_STATE_LAST; j++) - { - if (get_button (style, i, j) == NULL && - meta_theme_earliest_version_with_button (i) <= current_theme_version - ) - { - g_set_error (error, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be specified for this frame style"), - meta_button_type_to_string (i), - meta_button_state_to_string (j)); - return FALSE; - } - } - } - } - - return TRUE; -} - -static void -button_rect (MetaButtonType type, - const MetaFrameGeometry *fgeom, - int middle_background_offset, - GdkRectangle *rect) -{ - switch (type) - { - case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND: - *rect = fgeom->left_left_background; - break; - - case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND: - *rect = fgeom->left_middle_backgrounds[middle_background_offset]; - break; - - case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND: - *rect = fgeom->left_right_background; - break; - - case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND: - *rect = fgeom->right_left_background; - break; - - case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND: - *rect = fgeom->right_middle_backgrounds[middle_background_offset]; - break; - - case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND: - *rect = fgeom->right_right_background; - break; - - case META_BUTTON_TYPE_CLOSE: - *rect = fgeom->close_rect.visible; - break; - - case META_BUTTON_TYPE_SHADE: - *rect = fgeom->shade_rect.visible; - break; - - case META_BUTTON_TYPE_UNSHADE: - *rect = fgeom->unshade_rect.visible; - break; - - case META_BUTTON_TYPE_ABOVE: - *rect = fgeom->above_rect.visible; - break; - - case META_BUTTON_TYPE_UNABOVE: - *rect = fgeom->unabove_rect.visible; - break; - - case META_BUTTON_TYPE_STICK: - *rect = fgeom->stick_rect.visible; - break; - - case META_BUTTON_TYPE_UNSTICK: - *rect = fgeom->unstick_rect.visible; - break; - - case META_BUTTON_TYPE_MAXIMIZE: - *rect = fgeom->max_rect.visible; - break; - - case META_BUTTON_TYPE_MINIMIZE: - *rect = fgeom->min_rect.visible; - break; - - case META_BUTTON_TYPE_MENU: - *rect = fgeom->menu_rect.visible; - break; - - case META_BUTTON_TYPE_LAST: - g_assert_not_reached (); - break; - } -} - -void -meta_frame_style_draw (MetaFrameStyle *style, - GtkWidget *widget, - GdkDrawable *drawable, - int x_offset, - int y_offset, - const GdkRectangle *clip, - const MetaFrameGeometry *fgeom, - int client_width, - int client_height, - PangoLayout *title_layout, - int text_height, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - GdkPixbuf *mini_icon, - GdkPixbuf *icon) -{ - int i, j; - GdkRectangle titlebar_rect; - GdkRectangle left_titlebar_edge; - GdkRectangle right_titlebar_edge; - GdkRectangle bottom_titlebar_edge; - GdkRectangle top_titlebar_edge; - GdkRectangle left_edge, right_edge, bottom_edge; - PangoRectangle extents; - MetaDrawInfo draw_info; - - titlebar_rect.x = 0; - titlebar_rect.y = 0; - titlebar_rect.width = fgeom->width; - titlebar_rect.height = fgeom->top_height; - - left_titlebar_edge.x = titlebar_rect.x; - left_titlebar_edge.y = titlebar_rect.y + fgeom->top_titlebar_edge; - left_titlebar_edge.width = fgeom->left_titlebar_edge; - left_titlebar_edge.height = titlebar_rect.height - fgeom->top_titlebar_edge - fgeom->bottom_titlebar_edge; - - right_titlebar_edge.y = left_titlebar_edge.y; - right_titlebar_edge.height = left_titlebar_edge.height; - right_titlebar_edge.width = fgeom->right_titlebar_edge; - right_titlebar_edge.x = titlebar_rect.x + titlebar_rect.width - right_titlebar_edge.width; - - top_titlebar_edge.x = titlebar_rect.x; - top_titlebar_edge.y = titlebar_rect.y; - top_titlebar_edge.width = titlebar_rect.width; - top_titlebar_edge.height = fgeom->top_titlebar_edge; - - bottom_titlebar_edge.x = titlebar_rect.x; - bottom_titlebar_edge.width = titlebar_rect.width; - bottom_titlebar_edge.height = fgeom->bottom_titlebar_edge; - bottom_titlebar_edge.y = titlebar_rect.y + titlebar_rect.height - bottom_titlebar_edge.height; - - left_edge.x = 0; - left_edge.y = fgeom->top_height; - left_edge.width = fgeom->left_width; - left_edge.height = fgeom->height - fgeom->top_height - fgeom->bottom_height; - - right_edge.x = fgeom->width - fgeom->right_width; - right_edge.y = fgeom->top_height; - right_edge.width = fgeom->right_width; - right_edge.height = fgeom->height - fgeom->top_height - fgeom->bottom_height; - - bottom_edge.x = 0; - bottom_edge.y = fgeom->height - fgeom->bottom_height; - bottom_edge.width = fgeom->width; - bottom_edge.height = fgeom->bottom_height; - - if (title_layout) - pango_layout_get_pixel_extents (title_layout, - NULL, &extents); - - draw_info.mini_icon = mini_icon; - draw_info.icon = icon; - draw_info.title_layout = title_layout; - draw_info.title_layout_width = title_layout ? extents.width : 0; - draw_info.title_layout_height = title_layout ? extents.height : 0; - draw_info.fgeom = fgeom; - - /* The enum is in the order the pieces should be rendered. */ - i = 0; - while (i < META_FRAME_PIECE_LAST) - { - GdkRectangle rect; - GdkRectangle combined_clip; - - switch ((MetaFramePiece) i) - { - case META_FRAME_PIECE_ENTIRE_BACKGROUND: - rect.x = 0; - rect.y = 0; - rect.width = fgeom->width; - rect.height = fgeom->height; - break; - - case META_FRAME_PIECE_TITLEBAR: - rect = titlebar_rect; - break; - - case META_FRAME_PIECE_LEFT_TITLEBAR_EDGE: - rect = left_titlebar_edge; - break; - - case META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE: - rect = right_titlebar_edge; - break; - - case META_FRAME_PIECE_TOP_TITLEBAR_EDGE: - rect = top_titlebar_edge; - break; - - case META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE: - rect = bottom_titlebar_edge; - break; - - case META_FRAME_PIECE_TITLEBAR_MIDDLE: - rect.x = left_titlebar_edge.x + left_titlebar_edge.width; - rect.y = top_titlebar_edge.y + top_titlebar_edge.height; - rect.width = titlebar_rect.width - left_titlebar_edge.width - - right_titlebar_edge.width; - rect.height = titlebar_rect.height - top_titlebar_edge.height - bottom_titlebar_edge.height; - break; - - case META_FRAME_PIECE_TITLE: - rect = fgeom->title_rect; - break; - - case META_FRAME_PIECE_LEFT_EDGE: - rect = left_edge; - break; - - case META_FRAME_PIECE_RIGHT_EDGE: - rect = right_edge; - break; - - case META_FRAME_PIECE_BOTTOM_EDGE: - rect = bottom_edge; - break; - - case META_FRAME_PIECE_OVERLAY: - rect.x = 0; - rect.y = 0; - rect.width = fgeom->width; - rect.height = fgeom->height; - break; - - case META_FRAME_PIECE_LAST: - g_assert_not_reached (); - break; - } - - rect.x += x_offset; - rect.y += y_offset; - - if (clip == NULL) - combined_clip = rect; - else - gdk_rectangle_intersect ((GdkRectangle*) clip, /* const cast */ - &rect, - &combined_clip); - - if (combined_clip.width > 0 && combined_clip.height > 0) - { - MetaDrawOpList *op_list; - MetaFrameStyle *parent; - - parent = style; - op_list = NULL; - while (parent && op_list == NULL) - { - op_list = parent->pieces[i]; - parent = parent->parent; - } - - if (op_list) - { - MetaRectangle m_rect; - m_rect = meta_rect (rect.x, rect.y, rect.width, rect.height); - meta_draw_op_list_draw (op_list, - widget, - drawable, - &combined_clip, - &draw_info, - m_rect); - } - } - - - /* Draw buttons just before overlay */ - if ((i + 1) == META_FRAME_PIECE_OVERLAY) - { - int middle_bg_offset; - - middle_bg_offset = 0; - j = 0; - while (j < META_BUTTON_TYPE_LAST) - { - button_rect (j, fgeom, middle_bg_offset, &rect); - - rect.x += x_offset; - rect.y += y_offset; - - if (clip == NULL) - combined_clip = rect; - else - gdk_rectangle_intersect ((GdkRectangle*) clip, /* const cast */ - &rect, - &combined_clip); - - if (combined_clip.width > 0 && combined_clip.height > 0) - { - MetaDrawOpList *op_list; - - op_list = get_button (style, j, button_states[j]); - - if (op_list) - { - MetaRectangle m_rect; - m_rect = meta_rect (rect.x, rect.y, - rect.width, rect.height); - meta_draw_op_list_draw (op_list, - widget, - drawable, - &combined_clip, - &draw_info, - m_rect); - } - } - - /* MIDDLE_BACKGROUND type may get drawn more than once */ - if ((j == META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND || - j == META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND) && - middle_bg_offset < MAX_MIDDLE_BACKGROUNDS) - { - ++middle_bg_offset; - } - else - { - middle_bg_offset = 0; - ++j; - } - } - } - - ++i; - } -} - -MetaFrameStyleSet* -meta_frame_style_set_new (MetaFrameStyleSet *parent) -{ - MetaFrameStyleSet *style_set; - - style_set = g_new0 (MetaFrameStyleSet, 1); - - style_set->parent = parent; - if (parent) - meta_frame_style_set_ref (parent); - - style_set->refcount = 1; - - return style_set; -} - -static void -free_focus_styles (MetaFrameStyle *focus_styles[META_FRAME_FOCUS_LAST]) -{ - int i; - - for (i = 0; i < META_FRAME_FOCUS_LAST; i++) - if (focus_styles[i]) - meta_frame_style_unref (focus_styles[i]); -} - -void -meta_frame_style_set_ref (MetaFrameStyleSet *style_set) -{ - g_return_if_fail (style_set != NULL); - - style_set->refcount += 1; -} - -void -meta_frame_style_set_unref (MetaFrameStyleSet *style_set) -{ - g_return_if_fail (style_set != NULL); - g_return_if_fail (style_set->refcount > 0); - - style_set->refcount -= 1; - - if (style_set->refcount == 0) - { - int i; - - for (i = 0; i < META_FRAME_RESIZE_LAST; i++) - { - free_focus_styles (style_set->normal_styles[i]); - free_focus_styles (style_set->shaded_styles[i]); - } - - free_focus_styles (style_set->maximized_styles); - free_focus_styles (style_set->maximized_and_shaded_styles); - - if (style_set->parent) - meta_frame_style_set_unref (style_set->parent); - - DEBUG_FILL_STRUCT (style_set); - g_free (style_set); - } -} - - -static MetaFrameStyle* -get_style (MetaFrameStyleSet *style_set, - MetaFrameState state, - MetaFrameResize resize, - MetaFrameFocus focus) -{ - MetaFrameStyle *style; - - style = NULL; - - switch (state) - { - case META_FRAME_STATE_NORMAL: - case META_FRAME_STATE_SHADED: - { - if (state == META_FRAME_STATE_SHADED) - style = style_set->shaded_styles[resize][focus]; - else - style = style_set->normal_styles[resize][focus]; - - /* Try parent if we failed here */ - if (style == NULL && style_set->parent) - style = get_style (style_set->parent, state, resize, focus); - - /* Allow people to omit the vert/horz/none resize modes */ - if (style == NULL && - resize != META_FRAME_RESIZE_BOTH) - style = get_style (style_set, state, META_FRAME_RESIZE_BOTH, focus); - } - break; - default: - { - MetaFrameStyle **styles; - - styles = NULL; - - switch (state) - { - case META_FRAME_STATE_MAXIMIZED: - styles = style_set->maximized_styles; - break; - case META_FRAME_STATE_MAXIMIZED_AND_SHADED: - styles = style_set->maximized_and_shaded_styles; - break; - case META_FRAME_STATE_NORMAL: - case META_FRAME_STATE_SHADED: - case META_FRAME_STATE_LAST: - g_assert_not_reached (); - break; - } - - style = styles[focus]; - - /* Try parent if we failed here */ - if (style == NULL && style_set->parent) - style = get_style (style_set->parent, state, resize, focus); - } - } - - return style; -} - -static gboolean -check_state (MetaFrameStyleSet *style_set, - MetaFrameState state, - GError **error) -{ - int i; - - for (i = 0; i < META_FRAME_FOCUS_LAST; i++) - { - if (get_style (style_set, state, - META_FRAME_RESIZE_NONE, i) == NULL) - { - /* Translators: This error occurs when a <frame> tag is missing - * in theme XML. The "<frame ...>" is intended as a noun phrase, - * and the "missing" qualifies it. You should translate "whatever". - */ - g_set_error (error, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"), - meta_frame_state_to_string (state), - meta_frame_resize_to_string (META_FRAME_RESIZE_NONE), - meta_frame_focus_to_string (i)); - return FALSE; - } - } - - return TRUE; -} - -gboolean -meta_frame_style_set_validate (MetaFrameStyleSet *style_set, - GError **error) -{ - int i, j; - - g_return_val_if_fail (style_set != NULL, FALSE); - - for (i = 0; i < META_FRAME_RESIZE_LAST; i++) - for (j = 0; j < META_FRAME_FOCUS_LAST; j++) - if (get_style (style_set, META_FRAME_STATE_NORMAL, i, j) == NULL) - { - g_set_error (error, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"), - meta_frame_state_to_string (META_FRAME_STATE_NORMAL), - meta_frame_resize_to_string (i), - meta_frame_focus_to_string (j)); - return FALSE; - } - - if (!check_state (style_set, META_FRAME_STATE_SHADED, error)) - return FALSE; - - if (!check_state (style_set, META_FRAME_STATE_MAXIMIZED, error)) - return FALSE; - - if (!check_state (style_set, META_FRAME_STATE_MAXIMIZED_AND_SHADED, error)) - return FALSE; - - return TRUE; -} - -MetaTheme* -meta_theme_get_current (void) -{ - return meta_current_theme; -} - -void -meta_theme_set_current (const char *name, - gboolean force_reload) -{ - MetaTheme *new_theme; - GError *err; - - meta_topic (META_DEBUG_THEMES, "Setting current theme to \"%s\"\n", name); - - if (!force_reload && - meta_current_theme && - strcmp (name, meta_current_theme->name) == 0) - return; - - err = NULL; - new_theme = meta_theme_load (name, &err); - - if (new_theme == NULL) - { - meta_warning (_("Failed to load theme \"%s\": %s\n"), - name, err->message); - g_error_free (err); - } - else - { - if (meta_current_theme) - meta_theme_free (meta_current_theme); - - meta_current_theme = new_theme; - - meta_topic (META_DEBUG_THEMES, "New theme is \"%s\"\n", meta_current_theme->name); - } -} - -MetaTheme* -meta_theme_new (void) -{ - MetaTheme *theme; - - theme = g_new0 (MetaTheme, 1); - - theme->images_by_filename = - g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_object_unref); - - theme->layouts_by_name = - g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) meta_frame_layout_unref); - - theme->draw_op_lists_by_name = - g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) meta_draw_op_list_unref); - - theme->styles_by_name = - g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) meta_frame_style_unref); - - theme->style_sets_by_name = - g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) meta_frame_style_set_unref); - - /* Create our variable quarks so we can look up variables without - having to strcmp for the names */ - theme->quark_width = g_quark_from_static_string ("width"); - theme->quark_height = g_quark_from_static_string ("height"); - theme->quark_object_width = g_quark_from_static_string ("object_width"); - theme->quark_object_height = g_quark_from_static_string ("object_height"); - theme->quark_left_width = g_quark_from_static_string ("left_width"); - theme->quark_right_width = g_quark_from_static_string ("right_width"); - theme->quark_top_height = g_quark_from_static_string ("top_height"); - theme->quark_bottom_height = g_quark_from_static_string ("bottom_height"); - theme->quark_mini_icon_width = g_quark_from_static_string ("mini_icon_width"); - theme->quark_mini_icon_height = g_quark_from_static_string ("mini_icon_height"); - theme->quark_icon_width = g_quark_from_static_string ("icon_width"); - theme->quark_icon_height = g_quark_from_static_string ("icon_height"); - theme->quark_title_width = g_quark_from_static_string ("title_width"); - theme->quark_title_height = g_quark_from_static_string ("title_height"); - return theme; -} - - -void -meta_theme_free (MetaTheme *theme) -{ - int i; - - g_return_if_fail (theme != NULL); - - g_free (theme->name); - g_free (theme->dirname); - g_free (theme->filename); - g_free (theme->readable_name); - g_free (theme->date); - g_free (theme->description); - g_free (theme->author); - g_free (theme->copyright); - - /* be more careful when destroying the theme hash tables, - since they are only constructed as needed, and may be NULL. */ - if (theme->integer_constants) - g_hash_table_destroy (theme->integer_constants); - if (theme->images_by_filename) - g_hash_table_destroy (theme->images_by_filename); - if (theme->layouts_by_name) - g_hash_table_destroy (theme->layouts_by_name); - if (theme->draw_op_lists_by_name) - g_hash_table_destroy (theme->draw_op_lists_by_name); - if (theme->styles_by_name) - g_hash_table_destroy (theme->styles_by_name); - if (theme->style_sets_by_name) - g_hash_table_destroy (theme->style_sets_by_name); - - for (i = 0; i < META_FRAME_TYPE_LAST; i++) - if (theme->style_sets_by_type[i]) - meta_frame_style_set_unref (theme->style_sets_by_type[i]); - - DEBUG_FILL_STRUCT (theme); - g_free (theme); -} - -gboolean -meta_theme_validate (MetaTheme *theme, - GError **error) -{ - int i; - - g_return_val_if_fail (theme != NULL, FALSE); - - /* FIXME what else should be checked? */ - - g_assert (theme->name); - - if (theme->readable_name == NULL) - { - /* Translators: This error means that a necessary XML tag (whose name - * is given in angle brackets) was not found in a given theme (whose - * name is given second, in quotation marks). - */ - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("No <%s> set for theme \"%s\""), "name", theme->name); - return FALSE; - } - - if (theme->author == NULL) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("No <%s> set for theme \"%s\""), "author", theme->name); - return FALSE; - } - - if (theme->date == NULL) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("No <%s> set for theme \"%s\""), "date", theme->name); - return FALSE; - } - - if (theme->description == NULL) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("No <%s> set for theme \"%s\""), "description", theme->name); - return FALSE; - } - - if (theme->copyright == NULL) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("No <%s> set for theme \"%s\""), "copyright", theme->name); - return FALSE; - } - - for (i = 0; i < (int)META_FRAME_TYPE_LAST; i++) - if (theme->style_sets_by_type[i] == NULL) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("No frame style set for window type \"%s\" in theme \"%s\", add a <window type=\"%s\" style_set=\"whatever\"/> element"), - meta_frame_type_to_string (i), - theme->name, - meta_frame_type_to_string (i)); - - return FALSE; - } - - return TRUE; -} - -GdkPixbuf* -meta_theme_load_image (MetaTheme *theme, - const char *filename, - guint size_of_theme_icons, - GError **error) -{ - GdkPixbuf *pixbuf; - - pixbuf = g_hash_table_lookup (theme->images_by_filename, - filename); - - if (pixbuf == NULL) - { - - if (g_str_has_prefix (filename, "theme:") && - META_THEME_ALLOWS (theme, META_THEME_IMAGES_FROM_ICON_THEMES)) - { - pixbuf = gtk_icon_theme_load_icon ( - gtk_icon_theme_get_default (), - filename+6, - size_of_theme_icons, - 0, - error); - if (pixbuf == NULL) return NULL; - } - else - { - char *full_path; - full_path = g_build_filename (theme->dirname, filename, NULL); - - pixbuf = gdk_pixbuf_new_from_file (full_path, error); - if (pixbuf == NULL) - { - g_free (full_path); - return NULL; - } - - g_free (full_path); - } - g_hash_table_replace (theme->images_by_filename, - g_strdup (filename), - pixbuf); - } - - g_assert (pixbuf); - - g_object_ref (G_OBJECT (pixbuf)); - - return pixbuf; -} - -static MetaFrameStyle* -theme_get_style (MetaTheme *theme, - MetaFrameType type, - MetaFrameFlags flags) -{ - MetaFrameState state; - MetaFrameResize resize; - MetaFrameFocus focus; - MetaFrameStyle *style; - MetaFrameStyleSet *style_set; - - style_set = theme->style_sets_by_type[type]; - - /* Right now the parser forces a style set for all types, - * but this fallback code is here in case I take that out. - */ - if (style_set == NULL) - style_set = theme->style_sets_by_type[META_FRAME_TYPE_NORMAL]; - if (style_set == NULL) - return NULL; - - switch (flags & (META_FRAME_MAXIMIZED | META_FRAME_SHADED)) - { - case 0: - state = META_FRAME_STATE_NORMAL; - break; - case META_FRAME_MAXIMIZED: - state = META_FRAME_STATE_MAXIMIZED; - break; - case META_FRAME_SHADED: - state = META_FRAME_STATE_SHADED; - break; - case (META_FRAME_MAXIMIZED | META_FRAME_SHADED): - state = META_FRAME_STATE_MAXIMIZED_AND_SHADED; - break; - default: - g_assert_not_reached (); - state = META_FRAME_STATE_LAST; /* compiler */ - break; - } - - switch (flags & (META_FRAME_ALLOWS_VERTICAL_RESIZE | META_FRAME_ALLOWS_HORIZONTAL_RESIZE)) - { - case 0: - resize = META_FRAME_RESIZE_NONE; - break; - case META_FRAME_ALLOWS_VERTICAL_RESIZE: - resize = META_FRAME_RESIZE_VERTICAL; - break; - case META_FRAME_ALLOWS_HORIZONTAL_RESIZE: - resize = META_FRAME_RESIZE_HORIZONTAL; - break; - case (META_FRAME_ALLOWS_VERTICAL_RESIZE | META_FRAME_ALLOWS_HORIZONTAL_RESIZE): - resize = META_FRAME_RESIZE_BOTH; - break; - default: - g_assert_not_reached (); - resize = META_FRAME_RESIZE_LAST; /* compiler */ - break; - } - - /* re invert the styles used for focus/unfocussed while flashing a frame */ - if (((flags & META_FRAME_HAS_FOCUS) && !(flags & META_FRAME_IS_FLASHING)) - || (!(flags & META_FRAME_HAS_FOCUS) && (flags & META_FRAME_IS_FLASHING))) - focus = META_FRAME_FOCUS_YES; - else - focus = META_FRAME_FOCUS_NO; - - style = get_style (style_set, state, resize, focus); - - return style; -} - -MetaFrameStyle* -meta_theme_get_frame_style (MetaTheme *theme, - MetaFrameType type, - MetaFrameFlags flags) -{ - MetaFrameStyle *style; - - g_return_val_if_fail (type < META_FRAME_TYPE_LAST, NULL); - - style = theme_get_style (theme, type, flags); - - return style; -} - -double -meta_theme_get_title_scale (MetaTheme *theme, - MetaFrameType type, - MetaFrameFlags flags) -{ - MetaFrameStyle *style; - - g_return_val_if_fail (type < META_FRAME_TYPE_LAST, 1.0); - - style = theme_get_style (theme, type, flags); - - /* Parser is not supposed to allow this currently */ - if (style == NULL) - return 1.0; - - return style->layout->title_scale; -} - -void -meta_theme_draw_frame (MetaTheme *theme, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - int x_offset, - int y_offset, - MetaFrameType type, - MetaFrameFlags flags, - int client_width, - int client_height, - PangoLayout *title_layout, - int text_height, - const MetaButtonLayout *button_layout, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - GdkPixbuf *mini_icon, - GdkPixbuf *icon) -{ - MetaFrameGeometry fgeom; - MetaFrameStyle *style; - - g_return_if_fail (type < META_FRAME_TYPE_LAST); - - style = theme_get_style (theme, type, flags); - - /* Parser is not supposed to allow this currently */ - if (style == NULL) - return; - - meta_frame_layout_calc_geometry (style->layout, - text_height, - flags, - client_width, client_height, - button_layout, - &fgeom, - theme); - - meta_frame_style_draw (style, - widget, - drawable, - x_offset, y_offset, - clip, - &fgeom, - client_width, client_height, - title_layout, - text_height, - button_states, - mini_icon, icon); -} - -void -meta_theme_draw_frame_by_name (MetaTheme *theme, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - int x_offset, - int y_offset, - const gchar *style_name, - MetaFrameFlags flags, - int client_width, - int client_height, - PangoLayout *title_layout, - int text_height, - const MetaButtonLayout *button_layout, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - GdkPixbuf *mini_icon, - GdkPixbuf *icon) -{ - MetaFrameGeometry fgeom; - MetaFrameStyle *style; - - style = meta_theme_lookup_style (theme, style_name); - - /* Parser is not supposed to allow this currently */ - if (style == NULL) - return; - - meta_frame_layout_calc_geometry (style->layout, - text_height, - flags, - client_width, client_height, - button_layout, - &fgeom, - theme); - - meta_frame_style_draw (style, - widget, - drawable, - x_offset, y_offset, - clip, - &fgeom, - client_width, client_height, - title_layout, - text_height, - button_states, - mini_icon, icon); -} - - - - - - - - - - - -void -meta_theme_get_frame_borders (MetaTheme *theme, - MetaFrameType type, - int text_height, - MetaFrameFlags flags, - int *top_height, - int *bottom_height, - int *left_width, - int *right_width) -{ - MetaFrameStyle *style; - - g_return_if_fail (type < META_FRAME_TYPE_LAST); - - if (top_height) - *top_height = 0; - if (bottom_height) - *bottom_height = 0; - if (left_width) - *left_width = 0; - if (right_width) - *right_width = 0; - - style = theme_get_style (theme, type, flags); - - /* Parser is not supposed to allow this currently */ - if (style == NULL) - return; - - meta_frame_layout_get_borders (style->layout, - text_height, - flags, - top_height, bottom_height, - left_width, right_width); -} - -void -meta_theme_calc_geometry (MetaTheme *theme, - MetaFrameType type, - int text_height, - MetaFrameFlags flags, - int client_width, - int client_height, - const MetaButtonLayout *button_layout, - MetaFrameGeometry *fgeom) -{ - MetaFrameStyle *style; - - g_return_if_fail (type < META_FRAME_TYPE_LAST); - - style = theme_get_style (theme, type, flags); - - /* Parser is not supposed to allow this currently */ - if (style == NULL) - return; - - meta_frame_layout_calc_geometry (style->layout, - text_height, - flags, - client_width, client_height, - button_layout, - fgeom, - theme); -} - -MetaFrameLayout* -meta_theme_lookup_layout (MetaTheme *theme, - const char *name) -{ - return g_hash_table_lookup (theme->layouts_by_name, name); -} - -void -meta_theme_insert_layout (MetaTheme *theme, - const char *name, - MetaFrameLayout *layout) -{ - meta_frame_layout_ref (layout); - g_hash_table_replace (theme->layouts_by_name, g_strdup (name), layout); -} - -MetaDrawOpList* -meta_theme_lookup_draw_op_list (MetaTheme *theme, - const char *name) -{ - return g_hash_table_lookup (theme->draw_op_lists_by_name, name); -} - -void -meta_theme_insert_draw_op_list (MetaTheme *theme, - const char *name, - MetaDrawOpList *op_list) -{ - meta_draw_op_list_ref (op_list); - g_hash_table_replace (theme->draw_op_lists_by_name, g_strdup (name), op_list); -} - -MetaFrameStyle* -meta_theme_lookup_style (MetaTheme *theme, - const char *name) -{ - return g_hash_table_lookup (theme->styles_by_name, name); -} - -void -meta_theme_insert_style (MetaTheme *theme, - const char *name, - MetaFrameStyle *style) -{ - meta_frame_style_ref (style); - g_hash_table_replace (theme->styles_by_name, g_strdup (name), style); -} - -MetaFrameStyleSet* -meta_theme_lookup_style_set (MetaTheme *theme, - const char *name) -{ - return g_hash_table_lookup (theme->style_sets_by_name, name); -} - -void -meta_theme_insert_style_set (MetaTheme *theme, - const char *name, - MetaFrameStyleSet *style_set) -{ - meta_frame_style_set_ref (style_set); - g_hash_table_replace (theme->style_sets_by_name, g_strdup (name), style_set); -} - -static gboolean -first_uppercase (const char *str) -{ - return g_ascii_isupper (*str); -} - -gboolean -meta_theme_define_int_constant (MetaTheme *theme, - const char *name, - int value, - GError **error) -{ - if (theme->integer_constants == NULL) - theme->integer_constants = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); - - if (!first_uppercase (name)) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("User-defined constants must begin with a capital letter; \"%s\" does not"), - name); - return FALSE; - } - - if (g_hash_table_lookup_extended (theme->integer_constants, name, NULL, NULL)) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("Constant \"%s\" has already been defined"), - name); - - return FALSE; - } - - g_hash_table_insert (theme->integer_constants, - g_strdup (name), - GINT_TO_POINTER (value)); - - return TRUE; -} - -gboolean -meta_theme_lookup_int_constant (MetaTheme *theme, - const char *name, - int *value) -{ - gpointer old_value; - - *value = 0; - - if (theme->integer_constants == NULL) - return FALSE; - - if (g_hash_table_lookup_extended (theme->integer_constants, - name, NULL, &old_value)) - { - *value = GPOINTER_TO_INT (old_value); - return TRUE; - } - else - { - return FALSE; - } -} - -gboolean -meta_theme_define_float_constant (MetaTheme *theme, - const char *name, - double value, - GError **error) -{ - double *d; - - if (theme->float_constants == NULL) - theme->float_constants = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); - - if (!first_uppercase (name)) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("User-defined constants must begin with a capital letter; \"%s\" does not"), - name); - return FALSE; - } - - if (g_hash_table_lookup_extended (theme->float_constants, name, NULL, NULL)) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("Constant \"%s\" has already been defined"), - name); - - return FALSE; - } - - d = g_new (double, 1); - *d = value; - - g_hash_table_insert (theme->float_constants, - g_strdup (name), d); - - return TRUE; -} - -gboolean -meta_theme_lookup_float_constant (MetaTheme *theme, - const char *name, - double *value) -{ - double *d; - - *value = 0.0; - - if (theme->float_constants == NULL) - return FALSE; - - d = g_hash_table_lookup (theme->float_constants, name); - - if (d) - { - *value = *d; - return TRUE; - } - else - { - return FALSE; - } -} - -gboolean -meta_theme_define_color_constant (MetaTheme *theme, - const char *name, - const char *value, - GError **error) -{ - if (theme->color_constants == NULL) - theme->color_constants = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); - - if (!first_uppercase (name)) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("User-defined constants must begin with a capital letter; \"%s\" does not"), - name); - return FALSE; - } - - if (g_hash_table_lookup_extended (theme->color_constants, name, NULL, NULL)) - { - g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED, - _("Constant \"%s\" has already been defined"), - name); - - return FALSE; - } - - g_hash_table_insert (theme->color_constants, - g_strdup (name), - g_strdup (value)); - - return TRUE; -} - -gboolean -meta_theme_lookup_color_constant (MetaTheme *theme, - const char *name, - char **value) -{ - char *result; - - *value = NULL; - - if (theme->color_constants == NULL) - return FALSE; - - result = g_hash_table_lookup (theme->color_constants, name); - - if (result) - { - *value = result; - return TRUE; - } - else - { - return FALSE; - } -} - - -PangoFontDescription* -meta_gtk_widget_get_font_desc (GtkWidget *widget, - double scale, - const PangoFontDescription *override) -{ - PangoFontDescription *font_desc; - - g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL); - - font_desc = pango_font_description_copy (widget->style->font_desc); - - if (override) - pango_font_description_merge (font_desc, override, TRUE); - - pango_font_description_set_size (font_desc, - MAX (pango_font_description_get_size (font_desc) * scale, 1)); - - return font_desc; -} - -int -meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc, - PangoContext *context) -{ - PangoFontMetrics *metrics; - PangoLanguage *lang; - int retval; - - lang = pango_context_get_language (context); - metrics = pango_context_get_metrics (context, font_desc, lang); - - retval = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + - pango_font_metrics_get_descent (metrics)); - - pango_font_metrics_unref (metrics); - - return retval; -} - -MetaGtkColorComponent -meta_color_component_from_string (const char *str) -{ - if (strcmp ("fg", str) == 0) - return META_GTK_COLOR_FG; - else if (strcmp ("bg", str) == 0) - return META_GTK_COLOR_BG; - else if (strcmp ("light", str) == 0) - return META_GTK_COLOR_LIGHT; - else if (strcmp ("dark", str) == 0) - return META_GTK_COLOR_DARK; - else if (strcmp ("mid", str) == 0) - return META_GTK_COLOR_MID; - else if (strcmp ("text", str) == 0) - return META_GTK_COLOR_TEXT; - else if (strcmp ("base", str) == 0) - return META_GTK_COLOR_BASE; - else if (strcmp ("text_aa", str) == 0) - return META_GTK_COLOR_TEXT_AA; - else - return META_GTK_COLOR_LAST; -} - -const char* -meta_color_component_to_string (MetaGtkColorComponent component) -{ - switch (component) - { - case META_GTK_COLOR_FG: - return "fg"; - case META_GTK_COLOR_BG: - return "bg"; - case META_GTK_COLOR_LIGHT: - return "light"; - case META_GTK_COLOR_DARK: - return "dark"; - case META_GTK_COLOR_MID: - return "mid"; - case META_GTK_COLOR_TEXT: - return "text"; - case META_GTK_COLOR_BASE: - return "base"; - case META_GTK_COLOR_TEXT_AA: - return "text_aa"; - case META_GTK_COLOR_LAST: - break; - } - - return "<unknown>"; -} - -MetaButtonState -meta_button_state_from_string (const char *str) -{ - if (strcmp ("normal", str) == 0) - return META_BUTTON_STATE_NORMAL; - else if (strcmp ("pressed", str) == 0) - return META_BUTTON_STATE_PRESSED; - else if (strcmp ("prelight", str) == 0) - return META_BUTTON_STATE_PRELIGHT; - else - return META_BUTTON_STATE_LAST; -} - -const char* -meta_button_state_to_string (MetaButtonState state) -{ - switch (state) - { - case META_BUTTON_STATE_NORMAL: - return "normal"; - case META_BUTTON_STATE_PRESSED: - return "pressed"; - case META_BUTTON_STATE_PRELIGHT: - return "prelight"; - case META_BUTTON_STATE_LAST: - break; - } - - return "<unknown>"; -} - -MetaButtonType -meta_button_type_from_string (const char *str, MetaTheme *theme) -{ - if (META_THEME_ALLOWS(theme, META_THEME_SHADE_STICK_ABOVE_BUTTONS)) - { - if (strcmp ("shade", str) == 0) - return META_BUTTON_TYPE_SHADE; - else if (strcmp ("above", str) == 0) - return META_BUTTON_TYPE_ABOVE; - else if (strcmp ("stick", str) == 0) - return META_BUTTON_TYPE_STICK; - else if (strcmp ("unshade", str) == 0) - return META_BUTTON_TYPE_UNSHADE; - else if (strcmp ("unabove", str) == 0) - return META_BUTTON_TYPE_UNABOVE; - else if (strcmp ("unstick", str) == 0) - return META_BUTTON_TYPE_UNSTICK; - } - - if (strcmp ("close", str) == 0) - return META_BUTTON_TYPE_CLOSE; - else if (strcmp ("maximize", str) == 0) - return META_BUTTON_TYPE_MAXIMIZE; - else if (strcmp ("minimize", str) == 0) - return META_BUTTON_TYPE_MINIMIZE; - else if (strcmp ("menu", str) == 0) - return META_BUTTON_TYPE_MENU; - else if (strcmp ("left_left_background", str) == 0) - return META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND; - else if (strcmp ("left_middle_background", str) == 0) - return META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND; - else if (strcmp ("left_right_background", str) == 0) - return META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND; - else if (strcmp ("right_left_background", str) == 0) - return META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND; - else if (strcmp ("right_middle_background", str) == 0) - return META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND; - else if (strcmp ("right_right_background", str) == 0) - return META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND; - else - return META_BUTTON_TYPE_LAST; -} - -const char* -meta_button_type_to_string (MetaButtonType type) -{ - switch (type) - { - case META_BUTTON_TYPE_CLOSE: - return "close"; - case META_BUTTON_TYPE_MAXIMIZE: - return "maximize"; - case META_BUTTON_TYPE_MINIMIZE: - return "minimize"; - case META_BUTTON_TYPE_SHADE: - return "shade"; - case META_BUTTON_TYPE_ABOVE: - return "above"; - case META_BUTTON_TYPE_STICK: - return "stick"; - case META_BUTTON_TYPE_UNSHADE: - return "unshade"; - case META_BUTTON_TYPE_UNABOVE: - return "unabove"; - case META_BUTTON_TYPE_UNSTICK: - return "unstick"; - case META_BUTTON_TYPE_MENU: - return "menu"; - case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND: - return "left_left_background"; - case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND: - return "left_middle_background"; - case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND: - return "left_right_background"; - case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND: - return "right_left_background"; - case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND: - return "right_middle_background"; - case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND: - return "right_right_background"; - case META_BUTTON_TYPE_LAST: - break; - } - - return "<unknown>"; -} - -MetaFramePiece -meta_frame_piece_from_string (const char *str) -{ - if (strcmp ("entire_background", str) == 0) - return META_FRAME_PIECE_ENTIRE_BACKGROUND; - else if (strcmp ("titlebar", str) == 0) - return META_FRAME_PIECE_TITLEBAR; - else if (strcmp ("titlebar_middle", str) == 0) - return META_FRAME_PIECE_TITLEBAR_MIDDLE; - else if (strcmp ("left_titlebar_edge", str) == 0) - return META_FRAME_PIECE_LEFT_TITLEBAR_EDGE; - else if (strcmp ("right_titlebar_edge", str) == 0) - return META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE; - else if (strcmp ("top_titlebar_edge", str) == 0) - return META_FRAME_PIECE_TOP_TITLEBAR_EDGE; - else if (strcmp ("bottom_titlebar_edge", str) == 0) - return META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE; - else if (strcmp ("title", str) == 0) - return META_FRAME_PIECE_TITLE; - else if (strcmp ("left_edge", str) == 0) - return META_FRAME_PIECE_LEFT_EDGE; - else if (strcmp ("right_edge", str) == 0) - return META_FRAME_PIECE_RIGHT_EDGE; - else if (strcmp ("bottom_edge", str) == 0) - return META_FRAME_PIECE_BOTTOM_EDGE; - else if (strcmp ("overlay", str) == 0) - return META_FRAME_PIECE_OVERLAY; - else - return META_FRAME_PIECE_LAST; -} - -const char* -meta_frame_piece_to_string (MetaFramePiece piece) -{ - switch (piece) - { - case META_FRAME_PIECE_ENTIRE_BACKGROUND: - return "entire_background"; - case META_FRAME_PIECE_TITLEBAR: - return "titlebar"; - case META_FRAME_PIECE_TITLEBAR_MIDDLE: - return "titlebar_middle"; - case META_FRAME_PIECE_LEFT_TITLEBAR_EDGE: - return "left_titlebar_edge"; - case META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE: - return "right_titlebar_edge"; - case META_FRAME_PIECE_TOP_TITLEBAR_EDGE: - return "top_titlebar_edge"; - case META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE: - return "bottom_titlebar_edge"; - case META_FRAME_PIECE_TITLE: - return "title"; - case META_FRAME_PIECE_LEFT_EDGE: - return "left_edge"; - case META_FRAME_PIECE_RIGHT_EDGE: - return "right_edge"; - case META_FRAME_PIECE_BOTTOM_EDGE: - return "bottom_edge"; - case META_FRAME_PIECE_OVERLAY: - return "overlay"; - case META_FRAME_PIECE_LAST: - break; - } - - return "<unknown>"; -} - -MetaFrameState -meta_frame_state_from_string (const char *str) -{ - if (strcmp ("normal", str) == 0) - return META_FRAME_STATE_NORMAL; - else if (strcmp ("maximized", str) == 0) - return META_FRAME_STATE_MAXIMIZED; - else if (strcmp ("shaded", str) == 0) - return META_FRAME_STATE_SHADED; - else if (strcmp ("maximized_and_shaded", str) == 0) - return META_FRAME_STATE_MAXIMIZED_AND_SHADED; - else - return META_FRAME_STATE_LAST; -} - -const char* -meta_frame_state_to_string (MetaFrameState state) -{ - switch (state) - { - case META_FRAME_STATE_NORMAL: - return "normal"; - case META_FRAME_STATE_MAXIMIZED: - return "maximized"; - case META_FRAME_STATE_SHADED: - return "shaded"; - case META_FRAME_STATE_MAXIMIZED_AND_SHADED: - return "maximized_and_shaded"; - case META_FRAME_STATE_LAST: - break; - } - - return "<unknown>"; -} - -MetaFrameResize -meta_frame_resize_from_string (const char *str) -{ - if (strcmp ("none", str) == 0) - return META_FRAME_RESIZE_NONE; - else if (strcmp ("vertical", str) == 0) - return META_FRAME_RESIZE_VERTICAL; - else if (strcmp ("horizontal", str) == 0) - return META_FRAME_RESIZE_HORIZONTAL; - else if (strcmp ("both", str) == 0) - return META_FRAME_RESIZE_BOTH; - else - return META_FRAME_RESIZE_LAST; -} - -const char* -meta_frame_resize_to_string (MetaFrameResize resize) -{ - switch (resize) - { - case META_FRAME_RESIZE_NONE: - return "none"; - case META_FRAME_RESIZE_VERTICAL: - return "vertical"; - case META_FRAME_RESIZE_HORIZONTAL: - return "horizontal"; - case META_FRAME_RESIZE_BOTH: - return "both"; - case META_FRAME_RESIZE_LAST: - break; - } - - return "<unknown>"; -} - -MetaFrameFocus -meta_frame_focus_from_string (const char *str) -{ - if (strcmp ("no", str) == 0) - return META_FRAME_FOCUS_NO; - else if (strcmp ("yes", str) == 0) - return META_FRAME_FOCUS_YES; - else - return META_FRAME_FOCUS_LAST; -} - -const char* -meta_frame_focus_to_string (MetaFrameFocus focus) -{ - switch (focus) - { - case META_FRAME_FOCUS_NO: - return "no"; - case META_FRAME_FOCUS_YES: - return "yes"; - case META_FRAME_FOCUS_LAST: - break; - } - - return "<unknown>"; -} - -MetaFrameType -meta_frame_type_from_string (const char *str) -{ - if (strcmp ("normal", str) == 0) - return META_FRAME_TYPE_NORMAL; - else if (strcmp ("dialog", str) == 0) - return META_FRAME_TYPE_DIALOG; - else if (strcmp ("modal_dialog", str) == 0) - return META_FRAME_TYPE_MODAL_DIALOG; - else if (strcmp ("utility", str) == 0) - return META_FRAME_TYPE_UTILITY; - else if (strcmp ("menu", str) == 0) - return META_FRAME_TYPE_MENU; - else if (strcmp ("border", str) == 0) - return META_FRAME_TYPE_BORDER; -#if 0 - else if (strcmp ("toolbar", str) == 0) - return META_FRAME_TYPE_TOOLBAR; -#endif - else - return META_FRAME_TYPE_LAST; -} - -const char* -meta_frame_type_to_string (MetaFrameType type) -{ - switch (type) - { - case META_FRAME_TYPE_NORMAL: - return "normal"; - case META_FRAME_TYPE_DIALOG: - return "dialog"; - case META_FRAME_TYPE_MODAL_DIALOG: - return "modal_dialog"; - case META_FRAME_TYPE_UTILITY: - return "utility"; - case META_FRAME_TYPE_MENU: - return "menu"; - case META_FRAME_TYPE_BORDER: - return "border"; -#if 0 - case META_FRAME_TYPE_TOOLBAR: - return "toolbar"; -#endif - case META_FRAME_TYPE_LAST: - break; - } - - return "<unknown>"; -} - -MetaGradientType -meta_gradient_type_from_string (const char *str) -{ - if (strcmp ("vertical", str) == 0) - return META_GRADIENT_VERTICAL; - else if (strcmp ("horizontal", str) == 0) - return META_GRADIENT_HORIZONTAL; - else if (strcmp ("diagonal", str) == 0) - return META_GRADIENT_DIAGONAL; - else - return META_GRADIENT_LAST; -} - -const char* -meta_gradient_type_to_string (MetaGradientType type) -{ - switch (type) - { - case META_GRADIENT_VERTICAL: - return "vertical"; - case META_GRADIENT_HORIZONTAL: - return "horizontal"; - case META_GRADIENT_DIAGONAL: - return "diagonal"; - case META_GRADIENT_LAST: - break; - } - - return "<unknown>"; -} - -GtkStateType -meta_gtk_state_from_string (const char *str) -{ - if (strcmp ("normal", str) == 0 || strcmp ("NORMAL", str) == 0) - return GTK_STATE_NORMAL; - else if (strcmp ("prelight", str) == 0 || strcmp ("PRELIGHT", str) == 0) - return GTK_STATE_PRELIGHT; - else if (strcmp ("active", str) == 0 || strcmp ("ACTIVE", str) == 0) - return GTK_STATE_ACTIVE; - else if (strcmp ("selected", str) == 0 || strcmp ("SELECTED", str) == 0) - return GTK_STATE_SELECTED; - else if (strcmp ("insensitive", str) == 0 || strcmp ("INSENSITIVE", str) == 0) - return GTK_STATE_INSENSITIVE; - else - return -1; /* hack */ -} - -const char* -meta_gtk_state_to_string (GtkStateType state) -{ - switch (state) - { - case GTK_STATE_NORMAL: - return "NORMAL"; - case GTK_STATE_PRELIGHT: - return "PRELIGHT"; - case GTK_STATE_ACTIVE: - return "ACTIVE"; - case GTK_STATE_SELECTED: - return "SELECTED"; - case GTK_STATE_INSENSITIVE: - return "INSENSITIVE"; - } - - return "<unknown>"; -} - -GtkShadowType -meta_gtk_shadow_from_string (const char *str) -{ - if (strcmp ("none", str) == 0) - return GTK_SHADOW_NONE; - else if (strcmp ("in", str) == 0) - return GTK_SHADOW_IN; - else if (strcmp ("out", str) == 0) - return GTK_SHADOW_OUT; - else if (strcmp ("etched_in", str) == 0) - return GTK_SHADOW_ETCHED_IN; - else if (strcmp ("etched_out", str) == 0) - return GTK_SHADOW_ETCHED_OUT; - else - return -1; -} - -const char* -meta_gtk_shadow_to_string (GtkShadowType shadow) -{ - switch (shadow) - { - case GTK_SHADOW_NONE: - return "none"; - case GTK_SHADOW_IN: - return "in"; - case GTK_SHADOW_OUT: - return "out"; - case GTK_SHADOW_ETCHED_IN: - return "etched_in"; - case GTK_SHADOW_ETCHED_OUT: - return "etched_out"; - } - - return "<unknown>"; -} - -GtkArrowType -meta_gtk_arrow_from_string (const char *str) -{ - if (strcmp ("up", str) == 0) - return GTK_ARROW_UP; - else if (strcmp ("down", str) == 0) - return GTK_ARROW_DOWN; - else if (strcmp ("left", str) == 0) - return GTK_ARROW_LEFT; - else if (strcmp ("right", str) == 0) - return GTK_ARROW_RIGHT; - else if (strcmp ("none", str) == 0) - return GTK_ARROW_NONE; - else - return -1; -} - -const char* -meta_gtk_arrow_to_string (GtkArrowType arrow) -{ - switch (arrow) - { - case GTK_ARROW_UP: - return "up"; - case GTK_ARROW_DOWN: - return "down"; - case GTK_ARROW_LEFT: - return "left"; - case GTK_ARROW_RIGHT: - return "right"; - case GTK_ARROW_NONE: - return "none"; - } - - return "<unknown>"; -} - -MetaImageFillType -meta_image_fill_type_from_string (const char *str) -{ - if (strcmp ("tile", str) == 0) - return META_IMAGE_FILL_TILE; - else if (strcmp ("scale", str) == 0) - return META_IMAGE_FILL_SCALE; - else - return -1; -} - -const char* -meta_image_fill_type_to_string (MetaImageFillType fill_type) -{ - switch (fill_type) - { - case META_IMAGE_FILL_TILE: - return "tile"; - case META_IMAGE_FILL_SCALE: - return "scale"; - } - - return "<unknown>"; -} - -/* gtkstyle.c cut-and-pastage */ -static void -gtk_style_shade (GdkColor *a, - GdkColor *b, - gdouble k) -{ - gdouble red; - gdouble green; - gdouble blue; - - red = (gdouble) a->red / 65535.0; - green = (gdouble) a->green / 65535.0; - blue = (gdouble) a->blue / 65535.0; - - rgb_to_hls (&red, &green, &blue); - - green *= k; - if (green > 1.0) - green = 1.0; - else if (green < 0.0) - green = 0.0; - - blue *= k; - if (blue > 1.0) - blue = 1.0; - else if (blue < 0.0) - blue = 0.0; - - hls_to_rgb (&red, &green, &blue); - - b->red = red * 65535.0; - b->green = green * 65535.0; - b->blue = blue * 65535.0; -} - -static void -rgb_to_hls (gdouble *r, - gdouble *g, - gdouble *b) -{ - gdouble min; - gdouble max; - gdouble red; - gdouble green; - gdouble blue; - gdouble h, l, s; - gdouble delta; - - red = *r; - green = *g; - blue = *b; - - if (red > green) - { - if (red > blue) - max = red; - else - max = blue; - - if (green < blue) - min = green; - else - min = blue; - } - else - { - if (green > blue) - max = green; - else - max = blue; - - if (red < blue) - min = red; - else - min = blue; - } - - l = (max + min) / 2; - s = 0; - h = 0; - - if (max != min) - { - if (l <= 0.5) - s = (max - min) / (max + min); - else - s = (max - min) / (2 - max - min); - - delta = max -min; - if (red == max) - h = (green - blue) / delta; - else if (green == max) - h = 2 + (blue - red) / delta; - else if (blue == max) - h = 4 + (red - green) / delta; - - h *= 60; - if (h < 0.0) - h += 360; - } - - *r = h; - *g = l; - *b = s; -} - -static void -hls_to_rgb (gdouble *h, - gdouble *l, - gdouble *s) -{ - gdouble hue; - gdouble lightness; - gdouble saturation; - gdouble m1, m2; - gdouble r, g, b; - - lightness = *l; - saturation = *s; - - if (lightness <= 0.5) - m2 = lightness * (1 + saturation); - else - m2 = lightness + saturation - lightness * saturation; - m1 = 2 * lightness - m2; - - if (saturation == 0) - { - *h = lightness; - *l = lightness; - *s = lightness; - } - else - { - hue = *h + 120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - r = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - r = m2; - else if (hue < 240) - r = m1 + (m2 - m1) * (240 - hue) / 60; - else - r = m1; - - hue = *h; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - g = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - g = m2; - else if (hue < 240) - g = m1 + (m2 - m1) * (240 - hue) / 60; - else - g = m1; - - hue = *h - 120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - b = m1 + (m2 - m1) * hue / 60; - else if (hue < 180) - b = m2; - else if (hue < 240) - b = m1 + (m2 - m1) * (240 - hue) / 60; - else - b = m1; - - *h = r; - *l = g; - *s = b; - } -} - -#if 0 -/* These are some functions I'm saving to use in optimizing - * MetaDrawOpList, namely to pre-composite pixbufs on client side - * prior to rendering to the server - */ -static void -draw_bg_solid_composite (const MetaTextureSpec *bg, - const MetaTextureSpec *fg, - double alpha, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - MetaTextureDrawMode mode, - double xalign, - double yalign, - int x, - int y, - int width, - int height) -{ - GdkColor bg_color; - - g_assert (bg->type == META_TEXTURE_SOLID); - g_assert (fg->type != META_TEXTURE_COMPOSITE); - g_assert (fg->type != META_TEXTURE_SHAPE_LIST); - - meta_color_spec_render (bg->data.solid.color_spec, - widget, - &bg_color); - - switch (fg->type) - { - case META_TEXTURE_SOLID: - { - GdkColor fg_color; - - meta_color_spec_render (fg->data.solid.color_spec, - widget, - &fg_color); - - color_composite (&bg_color, &fg_color, - alpha, &fg_color); - - draw_color_rectangle (widget, drawable, &fg_color, clip, - x, y, width, height); - } - break; - - case META_TEXTURE_GRADIENT: - /* FIXME I think we could just composite all the colors in - * the gradient prior to generating the gradient? - */ - /* FALL THRU */ - case META_TEXTURE_IMAGE: - { - GdkPixbuf *pixbuf; - GdkPixbuf *composited; - - pixbuf = meta_texture_spec_render (fg, widget, mode, 255, - width, height); - - if (pixbuf == NULL) - return; - - composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha (pixbuf), 8, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); - - if (composited == NULL) - { - g_object_unref (G_OBJECT (pixbuf)); - return; - } - - gdk_pixbuf_composite_color (pixbuf, - composited, - 0, 0, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - 0.0, 0.0, /* offsets */ - 1.0, 1.0, /* scale */ - GDK_INTERP_BILINEAR, - 255 * alpha, - 0, 0, /* check offsets */ - 0, /* check size */ - GDK_COLOR_RGB (bg_color), - GDK_COLOR_RGB (bg_color)); - - /* Need to draw background since pixbuf is not - * necessarily covering the whole thing - */ - draw_color_rectangle (widget, drawable, &bg_color, clip, - x, y, width, height); - - render_pixbuf_aligned (drawable, clip, composited, - xalign, yalign, - x, y, width, height); - - g_object_unref (G_OBJECT (pixbuf)); - g_object_unref (G_OBJECT (composited)); - } - break; - - case META_TEXTURE_BLANK: - case META_TEXTURE_COMPOSITE: - case META_TEXTURE_SHAPE_LIST: - g_assert_not_reached (); - break; - } -} - -static void -draw_bg_gradient_composite (const MetaTextureSpec *bg, - const MetaTextureSpec *fg, - double alpha, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - MetaTextureDrawMode mode, - double xalign, - double yalign, - int x, - int y, - int width, - int height) -{ - g_assert (bg->type == META_TEXTURE_GRADIENT); - g_assert (fg->type != META_TEXTURE_COMPOSITE); - g_assert (fg->type != META_TEXTURE_SHAPE_LIST); - - switch (fg->type) - { - case META_TEXTURE_SOLID: - case META_TEXTURE_GRADIENT: - case META_TEXTURE_IMAGE: - { - GdkPixbuf *bg_pixbuf; - GdkPixbuf *fg_pixbuf; - GdkPixbuf *composited; - int fg_width, fg_height; - - bg_pixbuf = meta_texture_spec_render (bg, widget, mode, 255, - width, height); - - if (bg_pixbuf == NULL) - return; - - fg_pixbuf = meta_texture_spec_render (fg, widget, mode, 255, - width, height); - - if (fg_pixbuf == NULL) - { - g_object_unref (G_OBJECT (bg_pixbuf)); - return; - } - - /* gradients always fill the entire target area */ - g_assert (gdk_pixbuf_get_width (bg_pixbuf) == width); - g_assert (gdk_pixbuf_get_height (bg_pixbuf) == height); - - composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha (bg_pixbuf), 8, - gdk_pixbuf_get_width (bg_pixbuf), - gdk_pixbuf_get_height (bg_pixbuf)); - - if (composited == NULL) - { - g_object_unref (G_OBJECT (bg_pixbuf)); - g_object_unref (G_OBJECT (fg_pixbuf)); - return; - } - - fg_width = gdk_pixbuf_get_width (fg_pixbuf); - fg_height = gdk_pixbuf_get_height (fg_pixbuf); - - /* If we wanted to be all cool we could deal with the - * offsets and try to composite only in the clip rectangle, - * but I just don't care enough to figure it out. - */ - - gdk_pixbuf_composite (fg_pixbuf, - composited, - x + (width - fg_width) * xalign, - y + (height - fg_height) * yalign, - gdk_pixbuf_get_width (fg_pixbuf), - gdk_pixbuf_get_height (fg_pixbuf), - 0.0, 0.0, /* offsets */ - 1.0, 1.0, /* scale */ - GDK_INTERP_BILINEAR, - 255 * alpha); - - render_pixbuf (drawable, clip, composited, x, y); - - g_object_unref (G_OBJECT (bg_pixbuf)); - g_object_unref (G_OBJECT (fg_pixbuf)); - g_object_unref (G_OBJECT (composited)); - } - break; - - case META_TEXTURE_BLANK: - case META_TEXTURE_SHAPE_LIST: - case META_TEXTURE_COMPOSITE: - g_assert_not_reached (); - break; - } -} -#endif - -guint -meta_theme_earliest_version_with_button (MetaButtonType type) -{ - switch (type) - { - case META_BUTTON_TYPE_CLOSE: - case META_BUTTON_TYPE_MAXIMIZE: - case META_BUTTON_TYPE_MINIMIZE: - case META_BUTTON_TYPE_MENU: - case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND: - case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND: - case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND: - case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND: - case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND: - case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND: - return 1; - - case META_BUTTON_TYPE_SHADE: - case META_BUTTON_TYPE_ABOVE: - case META_BUTTON_TYPE_STICK: - case META_BUTTON_TYPE_UNSHADE: - case META_BUTTON_TYPE_UNABOVE: - case META_BUTTON_TYPE_UNSTICK: - return 2; - - default: - meta_warning("Unknown button %d\n", type); - return 1; - } -} diff --git a/src/ui/theme.h b/src/ui/theme.h deleted file mode 100644 index 737f30a8..00000000 --- a/src/ui/theme.h +++ /dev/null @@ -1,1139 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity Theme Rendering */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_THEME_H -#define META_THEME_H - -#include "boxes.h" -#include "gradient.h" -#include "common.h" -#include <gtk/gtk.h> - -typedef struct _MetaFrameStyle MetaFrameStyle; -typedef struct _MetaFrameStyleSet MetaFrameStyleSet; -typedef struct _MetaDrawOp MetaDrawOp; -typedef struct _MetaDrawOpList MetaDrawOpList; -typedef struct _MetaGradientSpec MetaGradientSpec; -typedef struct _MetaAlphaGradientSpec MetaAlphaGradientSpec; -typedef struct _MetaColorSpec MetaColorSpec; -typedef struct _MetaFrameLayout MetaFrameLayout; -typedef struct _MetaButtonSpace MetaButtonSpace; -typedef struct _MetaFrameGeometry MetaFrameGeometry; -typedef struct _MetaTheme MetaTheme; -typedef struct _MetaPositionExprEnv MetaPositionExprEnv; -typedef struct _MetaDrawInfo MetaDrawInfo; - -#define META_THEME_ERROR (g_quark_from_static_string ("meta-theme-error")) - -typedef enum -{ - META_THEME_ERROR_FRAME_GEOMETRY, - META_THEME_ERROR_BAD_CHARACTER, - META_THEME_ERROR_BAD_PARENS, - META_THEME_ERROR_UNKNOWN_VARIABLE, - META_THEME_ERROR_DIVIDE_BY_ZERO, - META_THEME_ERROR_MOD_ON_FLOAT, - META_THEME_ERROR_FAILED -} MetaThemeError; - -/** - * Whether a button's size is calculated from the area around it (aspect - * sizing) or is given as a fixed height and width in pixels (fixed sizing). - * - * \bug This could be done away with; see the comment at the top of - * MetaFrameLayout. - */ -typedef enum -{ - META_BUTTON_SIZING_ASPECT, - META_BUTTON_SIZING_FIXED, - META_BUTTON_SIZING_LAST -} MetaButtonSizing; - -/** - * Various parameters used to calculate the geometry of a frame. - * They are used inside a MetaFrameStyle. - * This corresponds closely to the <frame_geometry> tag in a theme file. - * - * \bug button_sizing isn't really necessary, because we could easily say - * that if button_aspect is zero, the height and width are fixed values. - * This would also mean that MetaButtonSizing didn't need to exist, and - * save code. - **/ -struct _MetaFrameLayout -{ - /** Reference count. */ - int refcount; - - /** Size of left side */ - int left_width; - /** Size of right side */ - int right_width; - /** Size of bottom side */ - int bottom_height; - - /** Border of blue title region - * \bug (blue?!) - **/ - GtkBorder title_border; - - /** Extra height for inside of title region, above the font height */ - int title_vertical_pad; - - /** Right indent of buttons from edges of frame */ - int right_titlebar_edge; - /** Left indent of buttons from edges of frame */ - int left_titlebar_edge; - - /** - * Sizing rule of buttons, either META_BUTTON_SIZING_ASPECT - * (in which case button_aspect will be honoured, and - * button_width and button_height set from it), or - * META_BUTTON_SIZING_FIXED (in which case we read the width - * and height directly). - */ - MetaButtonSizing button_sizing; - - /** - * Ratio of height/width. Honoured only if - * button_sizing==META_BUTTON_SIZING_ASPECT. - * Otherwise we figure out the height from the button_border. - */ - double button_aspect; - - /** Width of a button; set even when we are using aspect sizing */ - int button_width; - - /** Height of a button; set even when we are using aspect sizing */ - int button_height; - - /** Space around buttons */ - GtkBorder button_border; - - /** scale factor for title text */ - double title_scale; - - /** Whether title text will be displayed */ - guint has_title : 1; - - /** Whether we should hide the buttons */ - guint hide_buttons : 1; - - /** Radius of the top left-hand corner; 0 if not rounded */ - guint top_left_corner_rounded_radius; - /** Radius of the top right-hand corner; 0 if not rounded */ - guint top_right_corner_rounded_radius; - /** Radius of the bottom left-hand corner; 0 if not rounded */ - guint bottom_left_corner_rounded_radius; - /** Radius of the bottom right-hand corner; 0 if not rounded */ - guint bottom_right_corner_rounded_radius; -}; - -/** - * The computed size of a button (really just a way of tying its - * visible and clickable areas together). - * The reason for two different rectangles here is Fitts' law & maximized - * windows; see bug #97703 for more details. - */ -struct _MetaButtonSpace -{ - /** The screen area where the button's image is drawn */ - GdkRectangle visible; - /** The screen area where the button can be activated by clicking */ - GdkRectangle clickable; -}; - -/** - * Calculated actual geometry of the frame - */ -struct _MetaFrameGeometry -{ - int left_width; - int right_width; - int top_height; - int bottom_height; - - int width; - int height; - - GdkRectangle title_rect; - - int left_titlebar_edge; - int right_titlebar_edge; - int top_titlebar_edge; - int bottom_titlebar_edge; - - /* used for a memset hack */ -#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect)) -#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, right_right_background) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect)) - - /* The button rects (if changed adjust memset hack) */ - MetaButtonSpace close_rect; - MetaButtonSpace max_rect; - MetaButtonSpace min_rect; - MetaButtonSpace menu_rect; - MetaButtonSpace shade_rect; - MetaButtonSpace above_rect; - MetaButtonSpace stick_rect; - MetaButtonSpace unshade_rect; - MetaButtonSpace unabove_rect; - MetaButtonSpace unstick_rect; - -#define MAX_MIDDLE_BACKGROUNDS (MAX_BUTTONS_PER_CORNER - 2) - GdkRectangle left_left_background; - GdkRectangle left_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS]; - GdkRectangle left_right_background; - GdkRectangle right_left_background; - GdkRectangle right_middle_backgrounds[MAX_MIDDLE_BACKGROUNDS]; - GdkRectangle right_right_background; - /* End of button rects (if changed adjust memset hack) */ - - /* Round corners */ - guint top_left_corner_rounded_radius; - guint top_right_corner_rounded_radius; - guint bottom_left_corner_rounded_radius; - guint bottom_right_corner_rounded_radius; -}; - -typedef enum -{ - META_IMAGE_FILL_SCALE, /* default, needs to be all-bits-zero for g_new0 */ - META_IMAGE_FILL_TILE -} MetaImageFillType; - -typedef enum -{ - META_COLOR_SPEC_BASIC, - META_COLOR_SPEC_GTK, - META_COLOR_SPEC_BLEND, - META_COLOR_SPEC_SHADE -} MetaColorSpecType; - -typedef enum -{ - META_GTK_COLOR_FG, - META_GTK_COLOR_BG, - META_GTK_COLOR_LIGHT, - META_GTK_COLOR_DARK, - META_GTK_COLOR_MID, - META_GTK_COLOR_TEXT, - META_GTK_COLOR_BASE, - META_GTK_COLOR_TEXT_AA, - META_GTK_COLOR_LAST -} MetaGtkColorComponent; - -struct _MetaColorSpec -{ - MetaColorSpecType type; - union - { - struct { - GdkColor color; - } basic; - struct { - MetaGtkColorComponent component; - GtkStateType state; - } gtk; - struct { - MetaColorSpec *foreground; - MetaColorSpec *background; - double alpha; - - GdkColor color; - } blend; - struct { - MetaColorSpec *base; - double factor; - - GdkColor color; - } shade; - } data; -}; - -struct _MetaGradientSpec -{ - MetaGradientType type; - GSList *color_specs; -}; - -struct _MetaAlphaGradientSpec -{ - MetaGradientType type; - unsigned char *alphas; - int n_alphas; -}; - -struct _MetaDrawInfo -{ - GdkPixbuf *mini_icon; - GdkPixbuf *icon; - PangoLayout *title_layout; - int title_layout_width; - int title_layout_height; - const MetaFrameGeometry *fgeom; -}; - -/** - * A drawing operation in our simple vector drawing language. - */ -typedef enum -{ - /** Basic drawing-- line */ - META_DRAW_LINE, - /** Basic drawing-- rectangle */ - META_DRAW_RECTANGLE, - /** Basic drawing-- arc */ - META_DRAW_ARC, - - /** Clip to a rectangle */ - META_DRAW_CLIP, - - /* Texture thingies */ - - /** Just a filled rectangle with alpha */ - META_DRAW_TINT, - META_DRAW_GRADIENT, - META_DRAW_IMAGE, - - /** GTK theme engine stuff */ - META_DRAW_GTK_ARROW, - META_DRAW_GTK_BOX, - META_DRAW_GTK_VLINE, - - /** App's window icon */ - META_DRAW_ICON, - /** App's window title */ - META_DRAW_TITLE, - /** a draw op list */ - META_DRAW_OP_LIST, - /** tiled draw op list */ - META_DRAW_TILE -} MetaDrawType; - -typedef enum -{ - POS_TOKEN_INT, - POS_TOKEN_DOUBLE, - POS_TOKEN_OPERATOR, - POS_TOKEN_VARIABLE, - POS_TOKEN_OPEN_PAREN, - POS_TOKEN_CLOSE_PAREN -} PosTokenType; - -typedef enum -{ - POS_OP_NONE, - POS_OP_ADD, - POS_OP_SUBTRACT, - POS_OP_MULTIPLY, - POS_OP_DIVIDE, - POS_OP_MOD, - POS_OP_MAX, - POS_OP_MIN -} PosOperatorType; - -/** - * A token, as output by the tokeniser. - * - * \ingroup tokenizer - */ -typedef struct -{ - PosTokenType type; - - union - { - struct { - int val; - } i; - - struct { - double val; - } d; - - struct { - PosOperatorType op; - } o; - - struct { - char *name; - GQuark name_quark; - } v; - - } d; -} PosToken; - -/** - * A computed expression in our simple vector drawing language. - * While it appears to take the form of a tree, this is actually - * merely a list; concerns such as precedence of operators are - * currently recomputed on every recalculation. - * - * Created by meta_draw_spec_new(), destroyed by meta_draw_spec_free(). - * pos_eval() fills this with ...FIXME. Are tokens a tree or a list? - * \ingroup parser - */ -typedef struct _MetaDrawSpec -{ - /** - * If this spec is constant, this is the value of the constant; - * otherwise it is zero. - */ - int value; - - /** A list of tokens in the expression. */ - PosToken *tokens; - - /** How many tokens are in the tokens list. */ - int n_tokens; - - /** Does the expression contain any variables? */ - gboolean constant : 1; -} MetaDrawSpec; - -/** - * A single drawing operation in our simple vector drawing language. - */ -struct _MetaDrawOp -{ - MetaDrawType type; - - /* Positions are strings because they can be expressions */ - union - { - struct { - MetaColorSpec *color_spec; - int dash_on_length; - int dash_off_length; - int width; - MetaDrawSpec *x1; - MetaDrawSpec *y1; - MetaDrawSpec *x2; - MetaDrawSpec *y2; - } line; - - struct { - MetaColorSpec *color_spec; - gboolean filled; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - } rectangle; - - struct { - MetaColorSpec *color_spec; - gboolean filled; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - double start_angle; - double extent_angle; - } arc; - - struct { - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - } clip; - - struct { - MetaColorSpec *color_spec; - MetaAlphaGradientSpec *alpha_spec; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - } tint; - - struct { - MetaGradientSpec *gradient_spec; - MetaAlphaGradientSpec *alpha_spec; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - } gradient; - - struct { - MetaColorSpec *colorize_spec; - MetaAlphaGradientSpec *alpha_spec; - GdkPixbuf *pixbuf; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - - guint32 colorize_cache_pixel; - GdkPixbuf *colorize_cache_pixbuf; - MetaImageFillType fill_type; - unsigned int vertical_stripes : 1; - unsigned int horizontal_stripes : 1; - } image; - - struct { - GtkStateType state; - GtkShadowType shadow; - GtkArrowType arrow; - gboolean filled; - - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - } gtk_arrow; - - struct { - GtkStateType state; - GtkShadowType shadow; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - } gtk_box; - - struct { - GtkStateType state; - MetaDrawSpec *x; - MetaDrawSpec *y1; - MetaDrawSpec *y2; - } gtk_vline; - - struct { - MetaAlphaGradientSpec *alpha_spec; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - MetaImageFillType fill_type; - } icon; - - struct { - MetaColorSpec *color_spec; - MetaDrawSpec *x; - MetaDrawSpec *y; - } title; - - struct { - MetaDrawOpList *op_list; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - } op_list; - - struct { - MetaDrawOpList *op_list; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - MetaDrawSpec *tile_xoffset; - MetaDrawSpec *tile_yoffset; - MetaDrawSpec *tile_width; - MetaDrawSpec *tile_height; - } tile; - - } data; -}; - -/** - * A list of MetaDrawOp objects. Maintains a reference count. - * Grows as necessary and allows the allocation of unused spaces - * to keep reallocations to a minimum. - * - * \bug Do we really win anything from not using the equivalent - * GLib structures? - */ -struct _MetaDrawOpList -{ - int refcount; - MetaDrawOp **ops; - int n_ops; - int n_allocated; -}; - -typedef enum -{ - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_PRESSED, - META_BUTTON_STATE_PRELIGHT, - META_BUTTON_STATE_LAST -} MetaButtonState; - -typedef enum -{ - /* Ordered so that background is drawn first */ - META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND, - META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND, - META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND, - META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND, - META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND, - META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND, - META_BUTTON_TYPE_CLOSE, - META_BUTTON_TYPE_MAXIMIZE, - META_BUTTON_TYPE_MINIMIZE, - META_BUTTON_TYPE_MENU, - META_BUTTON_TYPE_SHADE, - META_BUTTON_TYPE_ABOVE, - META_BUTTON_TYPE_STICK, - META_BUTTON_TYPE_UNSHADE, - META_BUTTON_TYPE_UNABOVE, - META_BUTTON_TYPE_UNSTICK, - META_BUTTON_TYPE_LAST -} MetaButtonType; - -typedef enum -{ - META_MENU_ICON_TYPE_CLOSE, - META_MENU_ICON_TYPE_MAXIMIZE, - META_MENU_ICON_TYPE_UNMAXIMIZE, - META_MENU_ICON_TYPE_MINIMIZE, - META_MENU_ICON_TYPE_LAST -} MetaMenuIconType; - -typedef enum -{ - /* Listed in the order in which the textures are drawn. - * (though this only matters for overlaps of course.) - * Buttons are drawn after the frame textures. - * - * On the corners, horizontal pieces are arbitrarily given the - * corner area: - * - * ===== |==== - * | | - * | rather than | - * - */ - - /* entire frame */ - META_FRAME_PIECE_ENTIRE_BACKGROUND, - /* entire titlebar background */ - META_FRAME_PIECE_TITLEBAR, - /* portion of the titlebar background inside the titlebar - * background edges - */ - META_FRAME_PIECE_TITLEBAR_MIDDLE, - /* left end of titlebar */ - META_FRAME_PIECE_LEFT_TITLEBAR_EDGE, - /* right end of titlebar */ - META_FRAME_PIECE_RIGHT_TITLEBAR_EDGE, - /* top edge of titlebar */ - META_FRAME_PIECE_TOP_TITLEBAR_EDGE, - /* bottom edge of titlebar */ - META_FRAME_PIECE_BOTTOM_TITLEBAR_EDGE, - /* render over title background (text area) */ - META_FRAME_PIECE_TITLE, - /* left edge of the frame */ - META_FRAME_PIECE_LEFT_EDGE, - /* right edge of the frame */ - META_FRAME_PIECE_RIGHT_EDGE, - /* bottom edge of the frame */ - META_FRAME_PIECE_BOTTOM_EDGE, - /* place over entire frame, after drawing everything else */ - META_FRAME_PIECE_OVERLAY, - /* Used to get size of the enum */ - META_FRAME_PIECE_LAST -} MetaFramePiece; - -#define N_GTK_STATES 5 - -/** - * How to draw a frame in a particular state (say, a focussed, non-maximised, - * resizable frame). This corresponds closely to the <frame_style> tag - * in a theme file. - */ -struct _MetaFrameStyle -{ - /** Reference count. */ - int refcount; - /** - * Parent style. - * Settings which are unspecified here will be taken from there. - */ - MetaFrameStyle *parent; - /** Operations for drawing each kind of button in each state. */ - MetaDrawOpList *buttons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST]; - /** Operations for drawing each piece of the frame. */ - MetaDrawOpList *pieces[META_FRAME_PIECE_LAST]; - /** - * Details such as the height and width of each edge, the corner rounding, - * and the aspect ratio of the buttons. - */ - MetaFrameLayout *layout; - /** - * Background colour of the window. Only present in theme formats - * 2 and above. Can be NULL to use the standard GTK theme engine. - */ - MetaColorSpec *window_background_color; - /** - * Transparency of the window background. 0=transparent; 255=opaque. - */ - guint8 window_background_alpha; -}; - -/* Kinds of frame... - * - * normal -> noresize / vert only / horz only / both - * focused / unfocused - * max -> focused / unfocused - * shaded -> focused / unfocused - * max/shaded -> focused / unfocused - * - * so 4 states with 8 sub-states in one, 2 sub-states in the other 3, - * meaning 14 total - * - * 14 window states times 7 or 8 window types. Except some - * window types never get a frame so that narrows it down a bit. - * - */ -typedef enum -{ - META_FRAME_STATE_NORMAL, - META_FRAME_STATE_MAXIMIZED, - META_FRAME_STATE_SHADED, - META_FRAME_STATE_MAXIMIZED_AND_SHADED, - META_FRAME_STATE_LAST -} MetaFrameState; - -typedef enum -{ - META_FRAME_RESIZE_NONE, - META_FRAME_RESIZE_VERTICAL, - META_FRAME_RESIZE_HORIZONTAL, - META_FRAME_RESIZE_BOTH, - META_FRAME_RESIZE_LAST -} MetaFrameResize; - -typedef enum -{ - META_FRAME_FOCUS_NO, - META_FRAME_FOCUS_YES, - META_FRAME_FOCUS_LAST -} MetaFrameFocus; - -/** - * How to draw frames at different times: when it's maximised or not, shaded - * or not, when it's focussed or not, and (for non-maximised windows), when - * it can be horizontally or vertically resized, both, or neither. - * Not all window types actually get a frame. - * - * A theme contains one of these objects for each type of window (each - * MetaFrameType), that is, normal, dialogue (modal and non-modal), etc. - * - * This corresponds closely to the <frame_style_set> tag in a theme file. - */ -struct _MetaFrameStyleSet -{ - int refcount; - MetaFrameStyleSet *parent; - MetaFrameStyle *normal_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST]; - MetaFrameStyle *maximized_styles[META_FRAME_FOCUS_LAST]; - MetaFrameStyle *shaded_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST]; - MetaFrameStyle *maximized_and_shaded_styles[META_FRAME_FOCUS_LAST]; -}; - -/** - * A theme. This is a singleton class which groups all settings from a theme - * on disk together. - * - * \bug It is rather useless to keep the metadata fields in core, I think. - */ -struct _MetaTheme -{ - /** Name of the theme (on disk), e.g. "Crux" */ - char *name; - /** Path to the files associated with the theme */ - char *dirname; - /** - * Filename of the XML theme file. - * \bug Kept lying around for no discernable reason. - */ - char *filename; - /** Metadata: Human-readable name of the theme. */ - char *readable_name; - /** Metadata: Author of the theme. */ - char *author; - /** Metadata: Copyright holder. */ - char *copyright; - /** Metadata: Date of the theme. */ - char *date; - /** Metadata: Description of the theme. */ - char *description; - /** Version of the theme format. Older versions cannot use the features - * of newer versions even if they think they can (this is to allow forward - * and backward compatibility. - */ - guint format_version; - - /** Symbol table of integer constants. */ - GHashTable *integer_constants; - /** Symbol table of float constants. */ - GHashTable *float_constants; - /** - * Symbol table of colour constants (hex triples, and triples - * plus alpha). - * */ - GHashTable *color_constants; - GHashTable *images_by_filename; - GHashTable *layouts_by_name; - GHashTable *draw_op_lists_by_name; - GHashTable *styles_by_name; - GHashTable *style_sets_by_name; - MetaFrameStyleSet *style_sets_by_type[META_FRAME_TYPE_LAST]; - - GQuark quark_width; - GQuark quark_height; - GQuark quark_object_width; - GQuark quark_object_height; - GQuark quark_left_width; - GQuark quark_right_width; - GQuark quark_top_height; - GQuark quark_bottom_height; - GQuark quark_mini_icon_width; - GQuark quark_mini_icon_height; - GQuark quark_icon_width; - GQuark quark_icon_height; - GQuark quark_title_width; - GQuark quark_title_height; -}; - -struct _MetaPositionExprEnv -{ - MetaRectangle rect; - /* size of an object being drawn, if it has a natural size */ - int object_width; - int object_height; - /* global object sizes, always available */ - int left_width; - int right_width; - int top_height; - int bottom_height; - int title_width; - int title_height; - int mini_icon_width; - int mini_icon_height; - int icon_width; - int icon_height; - /* Theme so we can look up constants */ - MetaTheme *theme; -}; - -MetaFrameLayout* meta_frame_layout_new (void); -MetaFrameLayout* meta_frame_layout_copy (const MetaFrameLayout *src); -void meta_frame_layout_ref (MetaFrameLayout *layout); -void meta_frame_layout_unref (MetaFrameLayout *layout); -void meta_frame_layout_get_borders (const MetaFrameLayout *layout, - int text_height, - MetaFrameFlags flags, - int *top_height, - int *bottom_height, - int *left_width, - int *right_width); -void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout, - int text_height, - MetaFrameFlags flags, - int client_width, - int client_height, - const MetaButtonLayout *button_layout, - MetaFrameGeometry *fgeom, - MetaTheme *theme); - -gboolean meta_frame_layout_validate (const MetaFrameLayout *layout, - GError **error); - -gboolean meta_parse_position_expression (MetaDrawSpec *spec, - const MetaPositionExprEnv *env, - int *x_return, - int *y_return, - GError **err); -gboolean meta_parse_size_expression (MetaDrawSpec *spec, - const MetaPositionExprEnv *env, - int *val_return, - GError **err); - -MetaDrawSpec* meta_draw_spec_new (MetaTheme *theme, - const char *expr, - GError **error); -void meta_draw_spec_free (MetaDrawSpec *spec); - -MetaColorSpec* meta_color_spec_new (MetaColorSpecType type); -MetaColorSpec* meta_color_spec_new_from_string (const char *str, - GError **err); -MetaColorSpec* meta_color_spec_new_gtk (MetaGtkColorComponent component, - GtkStateType state); -void meta_color_spec_free (MetaColorSpec *spec); -void meta_color_spec_render (MetaColorSpec *spec, - GtkWidget *widget, - GdkColor *color); - - -MetaDrawOp* meta_draw_op_new (MetaDrawType type); -void meta_draw_op_free (MetaDrawOp *op); -void meta_draw_op_draw (const MetaDrawOp *op, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - const MetaDrawInfo *info, - /* logical region being drawn */ - MetaRectangle logical_region); - -MetaDrawOpList* meta_draw_op_list_new (int n_preallocs); -void meta_draw_op_list_ref (MetaDrawOpList *op_list); -void meta_draw_op_list_unref (MetaDrawOpList *op_list); -void meta_draw_op_list_draw (const MetaDrawOpList *op_list, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - const MetaDrawInfo *info, - MetaRectangle rect); -void meta_draw_op_list_append (MetaDrawOpList *op_list, - MetaDrawOp *op); -gboolean meta_draw_op_list_validate (MetaDrawOpList *op_list, - GError **error); -gboolean meta_draw_op_list_contains (MetaDrawOpList *op_list, - MetaDrawOpList *child); - -MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type); -void meta_gradient_spec_free (MetaGradientSpec *desc); -GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc, - GtkWidget *widget, - int width, - int height); -gboolean meta_gradient_spec_validate (MetaGradientSpec *spec, - GError **error); - -MetaAlphaGradientSpec* meta_alpha_gradient_spec_new (MetaGradientType type, - int n_alphas); -void meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec); - - -MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent); -void meta_frame_style_ref (MetaFrameStyle *style); -void meta_frame_style_unref (MetaFrameStyle *style); - -void meta_frame_style_draw (MetaFrameStyle *style, - GtkWidget *widget, - GdkDrawable *drawable, - int x_offset, - int y_offset, - const GdkRectangle *clip, - const MetaFrameGeometry *fgeom, - int client_width, - int client_height, - PangoLayout *title_layout, - int text_height, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - GdkPixbuf *mini_icon, - GdkPixbuf *icon); - - -gboolean meta_frame_style_validate (MetaFrameStyle *style, - guint current_theme_version, - GError **error); - -MetaFrameStyleSet* meta_frame_style_set_new (MetaFrameStyleSet *parent); -void meta_frame_style_set_ref (MetaFrameStyleSet *style_set); -void meta_frame_style_set_unref (MetaFrameStyleSet *style_set); - -gboolean meta_frame_style_set_validate (MetaFrameStyleSet *style_set, - GError **error); - -MetaTheme* meta_theme_get_current (void); -void meta_theme_set_current (const char *name, - gboolean force_reload); - -MetaTheme* meta_theme_new (void); -void meta_theme_free (MetaTheme *theme); -gboolean meta_theme_validate (MetaTheme *theme, - GError **error); -GdkPixbuf* meta_theme_load_image (MetaTheme *theme, - const char *filename, - guint size_of_theme_icons, - GError **error); - -MetaFrameStyle* meta_theme_get_frame_style (MetaTheme *theme, - MetaFrameType type, - MetaFrameFlags flags); - -double meta_theme_get_title_scale (MetaTheme *theme, - MetaFrameType type, - MetaFrameFlags flags); - -void meta_theme_draw_frame (MetaTheme *theme, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - int x_offset, - int y_offset, - MetaFrameType type, - MetaFrameFlags flags, - int client_width, - int client_height, - PangoLayout *title_layout, - int text_height, - const MetaButtonLayout *button_layout, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - GdkPixbuf *mini_icon, - GdkPixbuf *icon); - -void meta_theme_draw_frame_by_name (MetaTheme *theme, - GtkWidget *widget, - GdkDrawable *drawable, - const GdkRectangle *clip, - int x_offset, - int y_offset, - const gchar *style_name, - MetaFrameFlags flags, - int client_width, - int client_height, - PangoLayout *title_layout, - int text_height, - const MetaButtonLayout *button_layout, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - GdkPixbuf *mini_icon, - GdkPixbuf *icon); - -void meta_theme_get_frame_borders (MetaTheme *theme, - MetaFrameType type, - int text_height, - MetaFrameFlags flags, - int *top_height, - int *bottom_height, - int *left_width, - int *right_width); -void meta_theme_calc_geometry (MetaTheme *theme, - MetaFrameType type, - int text_height, - MetaFrameFlags flags, - int client_width, - int client_height, - const MetaButtonLayout *button_layout, - MetaFrameGeometry *fgeom); - -MetaFrameLayout* meta_theme_lookup_layout (MetaTheme *theme, - const char *name); -void meta_theme_insert_layout (MetaTheme *theme, - const char *name, - MetaFrameLayout *layout); -MetaDrawOpList* meta_theme_lookup_draw_op_list (MetaTheme *theme, - const char *name); -void meta_theme_insert_draw_op_list (MetaTheme *theme, - const char *name, - MetaDrawOpList *op_list); -MetaFrameStyle* meta_theme_lookup_style (MetaTheme *theme, - const char *name); -void meta_theme_insert_style (MetaTheme *theme, - const char *name, - MetaFrameStyle *style); -MetaFrameStyleSet* meta_theme_lookup_style_set (MetaTheme *theme, - const char *name); -void meta_theme_insert_style_set (MetaTheme *theme, - const char *name, - MetaFrameStyleSet *style_set); -gboolean meta_theme_define_int_constant (MetaTheme *theme, - const char *name, - int value, - GError **error); -gboolean meta_theme_lookup_int_constant (MetaTheme *theme, - const char *name, - int *value); -gboolean meta_theme_define_float_constant (MetaTheme *theme, - const char *name, - double value, - GError **error); -gboolean meta_theme_lookup_float_constant (MetaTheme *theme, - const char *name, - double *value); - -gboolean meta_theme_define_color_constant (MetaTheme *theme, - const char *name, - const char *value, - GError **error); -gboolean meta_theme_lookup_color_constant (MetaTheme *theme, - const char *name, - char **value); - -gboolean meta_theme_replace_constants (MetaTheme *theme, - PosToken *tokens, - int n_tokens, - GError **err); - -/* random stuff */ - -PangoFontDescription* meta_gtk_widget_get_font_desc (GtkWidget *widget, - double scale, - const PangoFontDescription *override); -int meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc, - PangoContext *context); - - -/* Enum converters */ -MetaGtkColorComponent meta_color_component_from_string (const char *str); -const char* meta_color_component_to_string (MetaGtkColorComponent component); -MetaButtonState meta_button_state_from_string (const char *str); -const char* meta_button_state_to_string (MetaButtonState state); -MetaButtonType meta_button_type_from_string (const char *str, - MetaTheme *theme); -const char* meta_button_type_to_string (MetaButtonType type); -MetaFramePiece meta_frame_piece_from_string (const char *str); -const char* meta_frame_piece_to_string (MetaFramePiece piece); -MetaFrameState meta_frame_state_from_string (const char *str); -const char* meta_frame_state_to_string (MetaFrameState state); -MetaFrameResize meta_frame_resize_from_string (const char *str); -const char* meta_frame_resize_to_string (MetaFrameResize resize); -MetaFrameFocus meta_frame_focus_from_string (const char *str); -const char* meta_frame_focus_to_string (MetaFrameFocus focus); -MetaFrameType meta_frame_type_from_string (const char *str); -const char* meta_frame_type_to_string (MetaFrameType type); -MetaGradientType meta_gradient_type_from_string (const char *str); -const char* meta_gradient_type_to_string (MetaGradientType type); -GtkStateType meta_gtk_state_from_string (const char *str); -const char* meta_gtk_state_to_string (GtkStateType state); -GtkShadowType meta_gtk_shadow_from_string (const char *str); -const char* meta_gtk_shadow_to_string (GtkShadowType shadow); -GtkArrowType meta_gtk_arrow_from_string (const char *str); -const char* meta_gtk_arrow_to_string (GtkArrowType arrow); -MetaImageFillType meta_image_fill_type_from_string (const char *str); -const char* meta_image_fill_type_to_string (MetaImageFillType fill_type); - -guint meta_theme_earliest_version_with_button (MetaButtonType type); - - -#define META_THEME_ALLOWS(theme, feature) (theme->format_version >= feature) - -/* What version of the theme file format were various features introduced in? */ -#define META_THEME_SHADE_STICK_ABOVE_BUTTONS 2 -#define META_THEME_UBIQUITOUS_CONSTANTS 2 -#define META_THEME_VARIED_ROUND_CORNERS 2 -#define META_THEME_IMAGES_FROM_ICON_THEMES 2 -#define META_THEME_UNRESIZABLE_SHADED_STYLES 2 -#define META_THEME_DEGREES_IN_ARCS 2 -#define META_THEME_HIDDEN_BUTTONS 2 -#define META_THEME_COLOR_CONSTANTS 2 -#define META_THEME_FRAME_BACKGROUNDS 2 - -#endif diff --git a/src/ui/themewidget.c b/src/ui/themewidget.c deleted file mode 100644 index 1cbcb8e2..00000000 --- a/src/ui/themewidget.c +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme widget (displays themed draw operations) */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "themewidget.h" -#include <math.h> - -static void meta_area_class_init (MetaAreaClass *klass); -static void meta_area_init (MetaArea *area); -static void meta_area_size_request (GtkWidget *widget, - GtkRequisition *req); -static gint meta_area_expose (GtkWidget *widget, - GdkEventExpose *event); -static void meta_area_finalize (GObject *object); - - -static GtkMiscClass *parent_class; - -GtkType -meta_area_get_type (void) -{ - static GtkType area_type = 0; - - if (!area_type) - { - static const GtkTypeInfo area_info = - { - "MetaArea", - sizeof (MetaArea), - sizeof (MetaAreaClass), - (GtkClassInitFunc) meta_area_class_init, - (GtkObjectInitFunc) meta_area_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - area_type = gtk_type_unique (GTK_TYPE_MISC, &area_info); - } - - return area_type; -} - -static void -meta_area_class_init (MetaAreaClass *class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (class); - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = (GtkObjectClass*) class; - widget_class = (GtkWidgetClass*) class; - parent_class = gtk_type_class (gtk_misc_get_type ()); - - gobject_class->finalize = meta_area_finalize; - - widget_class->expose_event = meta_area_expose; - widget_class->size_request = meta_area_size_request; -} - -static void -meta_area_init (MetaArea *area) -{ - GTK_WIDGET_SET_FLAGS (area, GTK_NO_WINDOW); -} - -GtkWidget* -meta_area_new (void) -{ - MetaArea *area; - - area = gtk_type_new (META_TYPE_AREA); - - return GTK_WIDGET (area); -} - -static void -meta_area_finalize (GObject *object) -{ - MetaArea *area; - - area = META_AREA (object); - - if (area->dnotify) - (* area->dnotify) (area->user_data); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static gint -meta_area_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - MetaArea *area; - GtkMisc *misc; - gint x, y; - gfloat xalign; - - g_return_val_if_fail (META_IS_AREA (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - if (GTK_WIDGET_DRAWABLE (widget)) - { - area = META_AREA (widget); - misc = GTK_MISC (widget); - - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - xalign = misc->xalign; - else - xalign = 1.0 - misc->xalign; - - x = floor (widget->allocation.x + misc->xpad - + ((widget->allocation.width - widget->requisition.width) * xalign) - + 0.5); - y = floor (widget->allocation.y + misc->ypad - + ((widget->allocation.height - widget->requisition.height) * misc->yalign) - + 0.5); - - if (area->expose_func) - { - (* area->expose_func) (area, event, x, y, - area->user_data); - } - } - - return FALSE; -} - -static void -meta_area_size_request (GtkWidget *widget, - GtkRequisition *req) -{ - MetaArea *area; - - area = META_AREA (widget); - - req->width = 0; - req->height = 0; - - if (area->size_func) - { - (* area->size_func) (area, &req->width, &req->height, - area->user_data); - } -} - -void -meta_area_setup (MetaArea *area, - MetaAreaSizeFunc size_func, - MetaAreaExposeFunc expose_func, - void *user_data, - GDestroyNotify dnotify) -{ - if (area->dnotify) - (* area->dnotify) (area->user_data); - - area->size_func = size_func; - area->expose_func = expose_func; - area->user_data = user_data; - area->dnotify = dnotify; - - gtk_widget_queue_resize (GTK_WIDGET (area)); -} - diff --git a/src/ui/themewidget.h b/src/ui/themewidget.h deleted file mode 100644 index 1568aa86..00000000 --- a/src/ui/themewidget.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity theme widget (displays themed draw operations) */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "theme.h" -#include <gtk/gtk.h> - -#ifndef META_THEME_WIDGET_H -#define META_THEME_WIDGET_H - -#define META_TYPE_AREA (meta_area_get_type ()) -#define META_AREA(obj) (GTK_CHECK_CAST ((obj), META_TYPE_AREA, MetaArea)) -#define META_AREA_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), META_TYPE_AREA, MetaAreaClass)) -#define META_IS_AREA(obj) (GTK_CHECK_TYPE ((obj), META_TYPE_AREA)) -#define META_IS_AREA_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), META_TYPE_AREA)) -#define META_AREA_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), META_TYPE_AREA, MetaAreaClass)) - -typedef struct _MetaArea MetaArea; -typedef struct _MetaAreaClass MetaAreaClass; - - -typedef void (* MetaAreaSizeFunc) (MetaArea *area, - int *width, - int *height, - void *user_data); - -typedef void (* MetaAreaExposeFunc) (MetaArea *area, - GdkEventExpose *event, - int x_offset, - int y_offset, - void *user_data); - -struct _MetaArea -{ - GtkMisc misc; - - MetaAreaSizeFunc size_func; - MetaAreaExposeFunc expose_func; - void *user_data; - GDestroyNotify dnotify; -}; - -struct _MetaAreaClass -{ - GtkMiscClass parent_class; -}; - - -GtkType meta_area_get_type (void) G_GNUC_CONST; -GtkWidget* meta_area_new (void); - -void meta_area_setup (MetaArea *area, - MetaAreaSizeFunc size_func, - MetaAreaExposeFunc expose_func, - void *user_data, - GDestroyNotify dnotify); - - -#endif diff --git a/src/ui/ui.c b/src/ui/ui.c deleted file mode 100644 index 010130c0..00000000 --- a/src/ui/ui.c +++ /dev/null @@ -1,999 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity interface for talking to GTK+ UI module */ - -/* - * Copyright (C) 2002 Havoc Pennington - * stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "prefs.h" -#include "ui.h" -#include "frames.h" -#include "util.h" -#include "menu.h" -#include "core.h" -#include "theme.h" - -#include "inlinepixbufs.h" - -#include <string.h> -#include <stdlib.h> - -static void meta_stock_icons_init (void); -static void meta_ui_accelerator_parse (const char *accel, - guint *keysym, - guint *keycode, - GdkModifierType *keymask); - -struct _MetaUI -{ - Display *xdisplay; - Screen *xscreen; - MetaFrames *frames; -}; - -void -meta_ui_init (int *argc, char ***argv) -{ - if (!gtk_init_check (argc, argv)) - meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL)); - - meta_stock_icons_init (); -} - -Display* -meta_ui_get_display (void) -{ - return gdk_display; -} - -typedef struct _EventFunc EventFunc; - -struct _EventFunc -{ - MetaEventFunc func; - gpointer data; -}; - -static EventFunc *ef = NULL; - -static GdkFilterReturn -filter_func (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - g_return_val_if_fail (ef != NULL, GDK_FILTER_CONTINUE); - - if ((* ef->func) (xevent, ef->data)) - return GDK_FILTER_REMOVE; - else - return GDK_FILTER_CONTINUE; -} - -void -meta_ui_add_event_func (Display *xdisplay, - MetaEventFunc func, - gpointer data) -{ - g_return_if_fail (ef == NULL); - - ef = g_new (EventFunc, 1); - ef->func = func; - ef->data = data; - - gdk_window_add_filter (NULL, filter_func, ef); -} - -/* removal is by data due to proxy function */ -void -meta_ui_remove_event_func (Display *xdisplay, - MetaEventFunc func, - gpointer data) -{ - g_return_if_fail (ef != NULL); - - gdk_window_remove_filter (NULL, filter_func, ef); - - g_free (ef); - ef = NULL; -} - -MetaUI* -meta_ui_new (Display *xdisplay, - Screen *screen) -{ - MetaUI *ui; - - ui = g_new (MetaUI, 1); - ui->xdisplay = xdisplay; - ui->xscreen = screen; - - g_assert (xdisplay == gdk_display); - ui->frames = meta_frames_new (XScreenNumberOfScreen (screen)); - gtk_widget_realize (GTK_WIDGET (ui->frames)); - - return ui; -} - -void -meta_ui_free (MetaUI *ui) -{ - gtk_widget_destroy (GTK_WIDGET (ui->frames)); - - g_free (ui); -} - -void -meta_ui_get_frame_geometry (MetaUI *ui, - Window frame_xwindow, - int *top_height, int *bottom_height, - int *left_width, int *right_width) -{ - meta_frames_get_geometry (ui->frames, frame_xwindow, - top_height, bottom_height, - left_width, right_width); -} - -Window -meta_ui_create_frame_window (MetaUI *ui, - Display *xdisplay, - Visual *xvisual, - gint x, - gint y, - gint width, - gint height, - gint screen_no) -{ - GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay); - GdkScreen *screen = gdk_display_get_screen (display, screen_no); - GdkWindowAttr attrs; - gint attributes_mask; - GdkWindow *window; - GdkVisual *visual; - GdkColormap *cmap = gdk_screen_get_default_colormap (screen); - - /* Default depth/visual handles clients with weird visuals; they can - * always be children of the root depth/visual obviously, but - * e.g. DRI games can't be children of a parent that has the same - * visual as the client. - */ - if (!xvisual) - visual = gdk_screen_get_system_visual (screen); - else - { - visual = gdk_x11_screen_lookup_visual (screen, - XVisualIDFromVisual (xvisual)); - cmap = gdk_colormap_new (visual, FALSE); - } - - attrs.title = NULL; - - /* frame.c is going to replace the event mask immediately, but - * we still have to set it here to let GDK know what it is. - */ - attrs.event_mask = - GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | - GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK; - attrs.x = x; - attrs.y = y; - attrs.wclass = GDK_INPUT_OUTPUT; - attrs.visual = visual; - attrs.colormap = cmap; - attrs.window_type = GDK_WINDOW_CHILD; - attrs.cursor = NULL; - attrs.wmclass_name = NULL; - attrs.wmclass_class = NULL; - attrs.override_redirect = FALSE; - - attrs.width = width; - attrs.height = height; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - - window = - gdk_window_new (gdk_screen_get_root_window(screen), - &attrs, attributes_mask); - - gdk_window_resize (window, width, height); - - meta_frames_manage_window (ui->frames, GDK_WINDOW_XID (window), window); - - return GDK_WINDOW_XID (window); -} - -void -meta_ui_destroy_frame_window (MetaUI *ui, - Window xwindow) -{ - meta_frames_unmanage_window (ui->frames, xwindow); -} - -void -meta_ui_move_resize_frame (MetaUI *ui, - Window frame, - int x, - int y, - int width, - int height) -{ - meta_frames_move_resize_frame (ui->frames, frame, x, y, width, height); -} - -void -meta_ui_map_frame (MetaUI *ui, - Window xwindow) -{ - GdkWindow *window; - - window = gdk_xid_table_lookup (xwindow); - - if (window) - gdk_window_show_unraised (window); -} - -void -meta_ui_unmap_frame (MetaUI *ui, - Window xwindow) -{ - GdkWindow *window; - - window = gdk_xid_table_lookup (xwindow); - - if (window) - gdk_window_hide (window); -} - -void -meta_ui_unflicker_frame_bg (MetaUI *ui, - Window xwindow, - int target_width, - int target_height) -{ - meta_frames_unflicker_bg (ui->frames, xwindow, - target_width, target_height); -} - -void -meta_ui_repaint_frame (MetaUI *ui, - Window xwindow) -{ - meta_frames_repaint_frame (ui->frames, xwindow); -} - -void -meta_ui_reset_frame_bg (MetaUI *ui, - Window xwindow) -{ - meta_frames_reset_bg (ui->frames, xwindow); -} - -void -meta_ui_apply_frame_shape (MetaUI *ui, - Window xwindow, - int new_window_width, - int new_window_height, - gboolean window_has_shape) -{ - meta_frames_apply_shapes (ui->frames, xwindow, - new_window_width, new_window_height, - window_has_shape); -} - -void -meta_ui_queue_frame_draw (MetaUI *ui, - Window xwindow) -{ - meta_frames_queue_draw (ui->frames, xwindow); -} - - -void -meta_ui_set_frame_title (MetaUI *ui, - Window xwindow, - const char *title) -{ - meta_frames_set_title (ui->frames, xwindow, title); -} - -MetaWindowMenu* -meta_ui_window_menu_new (MetaUI *ui, - Window client_xwindow, - MetaMenuOp ops, - MetaMenuOp insensitive, - unsigned long active_workspace, - int n_workspaces, - MetaWindowMenuFunc func, - gpointer data) -{ - return meta_window_menu_new (ui->frames, - ops, insensitive, - client_xwindow, - active_workspace, - n_workspaces, - func, data); -} - -void -meta_ui_window_menu_popup (MetaWindowMenu *menu, - int root_x, - int root_y, - int button, - guint32 timestamp) -{ - meta_window_menu_popup (menu, root_x, root_y, button, timestamp); -} - -void -meta_ui_window_menu_free (MetaWindowMenu *menu) -{ - meta_window_menu_free (menu); -} - -struct _MetaImageWindow -{ - GtkWidget *window; - GdkPixmap *pixmap; -}; - -MetaImageWindow* -meta_image_window_new (Display *xdisplay, - int screen_number, - int max_width, - int max_height) -{ - MetaImageWindow *iw; - GdkDisplay *gdisplay; - GdkScreen *gscreen; - - iw = g_new (MetaImageWindow, 1); - iw->window = gtk_window_new (GTK_WINDOW_POPUP); - - gdisplay = gdk_x11_lookup_xdisplay (xdisplay); - gscreen = gdk_display_get_screen (gdisplay, screen_number); - - gtk_window_set_screen (GTK_WINDOW (iw->window), gscreen); - - gtk_widget_realize (iw->window); - iw->pixmap = gdk_pixmap_new (iw->window->window, - max_width, max_height, - -1); - - gtk_widget_set_size_request (iw->window, 1, 1); - gtk_widget_set_double_buffered (iw->window, FALSE); - gtk_widget_set_app_paintable (iw->window, TRUE); - - return iw; -} - -void -meta_image_window_free (MetaImageWindow *iw) -{ - gtk_widget_destroy (iw->window); - g_object_unref (G_OBJECT (iw->pixmap)); - g_free (iw); -} - -void -meta_image_window_set_showing (MetaImageWindow *iw, - gboolean showing) -{ - if (showing) - gtk_widget_show_all (iw->window); - else - { - gtk_widget_hide (iw->window); - meta_core_increment_event_serial (gdk_display); - } -} - -void -meta_image_window_set (MetaImageWindow *iw, - GdkPixbuf *pixbuf, - int x, - int y) -{ - /* We use a back pixmap to avoid having to handle exposes, because - * it's really too slow for large clients being minimized, etc. - * and this way flicker is genuinely zero. - */ - - gdk_draw_pixbuf (iw->pixmap, - iw->window->style->black_gc, - pixbuf, - 0, 0, - 0, 0, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - GDK_RGB_DITHER_NORMAL, - 0, 0); - - gdk_window_set_back_pixmap (iw->window->window, - iw->pixmap, - FALSE); - - gdk_window_move_resize (iw->window->window, - x, y, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); - - gdk_window_clear (iw->window->window); -} - -static GdkColormap* -get_cmap (GdkPixmap *pixmap) -{ - GdkColormap *cmap; - - cmap = gdk_drawable_get_colormap (pixmap); - if (cmap) - g_object_ref (G_OBJECT (cmap)); - - if (cmap == NULL) - { - if (gdk_drawable_get_depth (pixmap) == 1) - { - meta_verbose ("Using NULL colormap for snapshotting bitmap\n"); - cmap = NULL; - } - else - { - meta_verbose ("Using system cmap to snapshot pixmap\n"); - cmap = gdk_screen_get_system_colormap (gdk_drawable_get_screen (pixmap)); - - g_object_ref (G_OBJECT (cmap)); - } - } - - /* Be sure we aren't going to blow up due to visual mismatch */ - if (cmap && - (gdk_colormap_get_visual (cmap)->depth != - gdk_drawable_get_depth (pixmap))) - { - cmap = NULL; - meta_verbose ("Switching back to NULL cmap because of depth mismatch\n"); - } - - return cmap; -} - -GdkPixbuf* -meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest, - Window xwindow, - int src_x, - int src_y, - int dest_x, - int dest_y, - int width, - int height) -{ - GdkDrawable *drawable; - GdkPixbuf *retval; - GdkColormap *cmap; - - retval = NULL; - - drawable = gdk_xid_table_lookup (xwindow); - - if (drawable) - g_object_ref (G_OBJECT (drawable)); - else - drawable = gdk_window_foreign_new (xwindow); - - cmap = get_cmap (drawable); - - retval = gdk_pixbuf_get_from_drawable (dest, - drawable, - cmap, - src_x, src_y, - dest_x, dest_y, - width, height); - - if (cmap) - g_object_unref (G_OBJECT (cmap)); - g_object_unref (G_OBJECT (drawable)); - - return retval; -} - -GdkPixbuf* -meta_gdk_pixbuf_get_from_pixmap (GdkPixbuf *dest, - Pixmap xpixmap, - int src_x, - int src_y, - int dest_x, - int dest_y, - int width, - int height) -{ - GdkDrawable *drawable; - GdkPixbuf *retval; - GdkColormap *cmap; - - retval = NULL; - cmap = NULL; - - drawable = gdk_xid_table_lookup (xpixmap); - - if (drawable) - g_object_ref (G_OBJECT (drawable)); - else - drawable = gdk_pixmap_foreign_new (xpixmap); - - if (drawable) - { - cmap = get_cmap (drawable); - - retval = gdk_pixbuf_get_from_drawable (dest, - drawable, - cmap, - src_x, src_y, - dest_x, dest_y, - width, height); - } - if (cmap) - g_object_unref (G_OBJECT (cmap)); - if (drawable) - g_object_unref (G_OBJECT (drawable)); - - return retval; -} - -void -meta_ui_push_delay_exposes (MetaUI *ui) -{ - meta_frames_push_delay_exposes (ui->frames); -} - -void -meta_ui_pop_delay_exposes (MetaUI *ui) -{ - meta_frames_pop_delay_exposes (ui->frames); -} - -GdkPixbuf* -meta_ui_get_default_window_icon (MetaUI *ui) -{ - static GdkPixbuf *default_icon = NULL; - - if (default_icon == NULL) - { - GtkIconTheme *theme; - gboolean icon_exists; - - theme = gtk_icon_theme_get_default (); - - icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME); - - if (icon_exists) - default_icon = gtk_icon_theme_load_icon (theme, - META_DEFAULT_ICON_NAME, - META_ICON_WIDTH, - 0, - NULL); - else - default_icon = gtk_icon_theme_load_icon (theme, - "gtk-missing-image", - META_ICON_WIDTH, - 0, - NULL); - - g_assert (default_icon); - } - - g_object_ref (G_OBJECT (default_icon)); - - return default_icon; -} - -GdkPixbuf* -meta_ui_get_default_mini_icon (MetaUI *ui) -{ - static GdkPixbuf *default_icon = NULL; - - if (default_icon == NULL) - { - GtkIconTheme *theme; - gboolean icon_exists; - - theme = gtk_icon_theme_get_default (); - - icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME); - - if (icon_exists) - default_icon = gtk_icon_theme_load_icon (theme, - META_DEFAULT_ICON_NAME, - META_MINI_ICON_WIDTH, - 0, - NULL); - else - default_icon = gtk_icon_theme_load_icon (theme, - "gtk-missing-image", - META_MINI_ICON_WIDTH, - 0, - NULL); - - g_assert (default_icon); - } - - g_object_ref (G_OBJECT (default_icon)); - - return default_icon; -} - -gboolean -meta_ui_window_should_not_cause_focus (Display *xdisplay, - Window xwindow) -{ - GdkWindow *window; - - window = gdk_xid_table_lookup (xwindow); - - /* we shouldn't cause focus if we're an override redirect - * toplevel which is not foreign - */ - if (window && gdk_window_get_type (window) == GDK_WINDOW_TEMP) - return TRUE; - else - return FALSE; -} - -char* -meta_text_property_to_utf8 (Display *xdisplay, - const XTextProperty *prop) -{ - char **list; - int count; - char *retval; - - list = NULL; - - count = gdk_text_property_to_utf8_list (gdk_x11_xatom_to_atom (prop->encoding), - prop->format, - prop->value, - prop->nitems, - &list); - - if (count == 0) - return NULL; - - retval = list[0]; - list[0] = g_strdup (""); /* something to free */ - - g_strfreev (list); - - return retval; -} - -void -meta_ui_theme_get_frame_borders (MetaUI *ui, - MetaFrameType type, - MetaFrameFlags flags, - int *top_height, - int *bottom_height, - int *left_width, - int *right_width) -{ - int text_height; - PangoContext *context; - const PangoFontDescription *font_desc; - GtkStyle *default_style; - - if (meta_ui_have_a_theme ()) - { - context = gtk_widget_get_pango_context (GTK_WIDGET (ui->frames)); - font_desc = meta_prefs_get_titlebar_font (); - - if (!font_desc) - { - default_style = gtk_widget_get_default_style (); - font_desc = default_style->font_desc; - } - - text_height = meta_pango_font_desc_get_text_height (font_desc, context); - - meta_theme_get_frame_borders (meta_theme_get_current (), - type, text_height, flags, - top_height, bottom_height, - left_width, right_width); - } - else - { - *top_height = *bottom_height = *left_width = *right_width = 0; - } -} - -void -meta_ui_set_current_theme (const char *name, - gboolean force_reload) -{ - meta_theme_set_current (name, force_reload); - meta_invalidate_default_icons (); -} - -gboolean -meta_ui_have_a_theme (void) -{ - return meta_theme_get_current () != NULL; -} - -static void -meta_ui_accelerator_parse (const char *accel, - guint *keysym, - guint *keycode, - GdkModifierType *keymask) -{ - if (accel[0] == '0' && accel[1] == 'x') - { - *keysym = 0; - *keycode = (guint) strtoul (accel, NULL, 16); - *keymask = 0; - } - else - gtk_accelerator_parse (accel, keysym, keymask); -} - -gboolean -meta_ui_parse_accelerator (const char *accel, - unsigned int *keysym, - unsigned int *keycode, - MetaVirtualModifier *mask) -{ - GdkModifierType gdk_mask = 0; - guint gdk_sym = 0; - guint gdk_code = 0; - - *keysym = 0; - *keycode = 0; - *mask = 0; - - if (strcmp (accel, "disabled") == 0) - return TRUE; - - meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask); - if (gdk_mask == 0 && gdk_sym == 0 && gdk_code == 0) - return FALSE; - - if (gdk_sym == None && gdk_code == 0) - return FALSE; - - if (gdk_mask & GDK_RELEASE_MASK) /* we don't allow this */ - return FALSE; - - *keysym = gdk_sym; - *keycode = gdk_code; - - if (gdk_mask & GDK_SHIFT_MASK) - *mask |= META_VIRTUAL_SHIFT_MASK; - if (gdk_mask & GDK_CONTROL_MASK) - *mask |= META_VIRTUAL_CONTROL_MASK; - if (gdk_mask & GDK_MOD1_MASK) - *mask |= META_VIRTUAL_ALT_MASK; - if (gdk_mask & GDK_MOD2_MASK) - *mask |= META_VIRTUAL_MOD2_MASK; - if (gdk_mask & GDK_MOD3_MASK) - *mask |= META_VIRTUAL_MOD3_MASK; - if (gdk_mask & GDK_MOD4_MASK) - *mask |= META_VIRTUAL_MOD4_MASK; - if (gdk_mask & GDK_MOD5_MASK) - *mask |= META_VIRTUAL_MOD5_MASK; - if (gdk_mask & GDK_SUPER_MASK) - *mask |= META_VIRTUAL_SUPER_MASK; - if (gdk_mask & GDK_HYPER_MASK) - *mask |= META_VIRTUAL_HYPER_MASK; - if (gdk_mask & GDK_META_MASK) - *mask |= META_VIRTUAL_META_MASK; - - return TRUE; -} - -/* Caller responsible for freeing return string of meta_ui_accelerator_name! */ -gchar* -meta_ui_accelerator_name (unsigned int keysym, - MetaVirtualModifier mask) -{ - GdkModifierType mods = 0; - - if (keysym == 0 && mask == 0) - { - return g_strdup ("disabled"); - } - - if (mask & META_VIRTUAL_SHIFT_MASK) - mods |= GDK_SHIFT_MASK; - if (mask & META_VIRTUAL_CONTROL_MASK) - mods |= GDK_CONTROL_MASK; - if (mask & META_VIRTUAL_ALT_MASK) - mods |= GDK_MOD1_MASK; - if (mask & META_VIRTUAL_MOD2_MASK) - mods |= GDK_MOD2_MASK; - if (mask & META_VIRTUAL_MOD3_MASK) - mods |= GDK_MOD3_MASK; - if (mask & META_VIRTUAL_MOD4_MASK) - mods |= GDK_MOD4_MASK; - if (mask & META_VIRTUAL_MOD5_MASK) - mods |= GDK_MOD5_MASK; - if (mask & META_VIRTUAL_SUPER_MASK) - mods |= GDK_SUPER_MASK; - if (mask & META_VIRTUAL_HYPER_MASK) - mods |= GDK_HYPER_MASK; - if (mask & META_VIRTUAL_META_MASK) - mods |= GDK_META_MASK; - - return gtk_accelerator_name (keysym, mods); - -} - -gboolean -meta_ui_parse_modifier (const char *accel, - MetaVirtualModifier *mask) -{ - GdkModifierType gdk_mask = 0; - guint gdk_sym = 0; - guint gdk_code = 0; - - *mask = 0; - - if (accel == NULL || strcmp (accel, "disabled") == 0) - return TRUE; - - meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask); - if (gdk_mask == 0 && gdk_sym == 0 && gdk_code == 0) - return FALSE; - - if (gdk_sym != None || gdk_code != 0) - return FALSE; - - if (gdk_mask & GDK_RELEASE_MASK) /* we don't allow this */ - return FALSE; - - if (gdk_mask & GDK_SHIFT_MASK) - *mask |= META_VIRTUAL_SHIFT_MASK; - if (gdk_mask & GDK_CONTROL_MASK) - *mask |= META_VIRTUAL_CONTROL_MASK; - if (gdk_mask & GDK_MOD1_MASK) - *mask |= META_VIRTUAL_ALT_MASK; - if (gdk_mask & GDK_MOD2_MASK) - *mask |= META_VIRTUAL_MOD2_MASK; - if (gdk_mask & GDK_MOD3_MASK) - *mask |= META_VIRTUAL_MOD3_MASK; - if (gdk_mask & GDK_MOD4_MASK) - *mask |= META_VIRTUAL_MOD4_MASK; - if (gdk_mask & GDK_MOD5_MASK) - *mask |= META_VIRTUAL_MOD5_MASK; - if (gdk_mask & GDK_SUPER_MASK) - *mask |= META_VIRTUAL_SUPER_MASK; - if (gdk_mask & GDK_HYPER_MASK) - *mask |= META_VIRTUAL_HYPER_MASK; - if (gdk_mask & GDK_META_MASK) - *mask |= META_VIRTUAL_META_MASK; - - return TRUE; -} - -gboolean -meta_ui_window_is_widget (MetaUI *ui, - Window xwindow) -{ - GdkWindow *window; - - window = gdk_xid_table_lookup (xwindow); - - if (window) - { - void *user_data = NULL; - gdk_window_get_user_data (window, &user_data); - return user_data != NULL && user_data != ui->frames; - } - else - return FALSE; -} - -/* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org> */ -typedef struct -{ - char *stock_id; - const guint8 *icon_data; -} MetaStockIcon; - -static void -meta_stock_icons_init (void) -{ - GtkIconFactory *factory; - int i; - - MetaStockIcon items[] = - { - { METACITY_STOCK_DELETE, stock_delete_data }, - { METACITY_STOCK_MINIMIZE, stock_minimize_data }, - { METACITY_STOCK_MAXIMIZE, stock_maximize_data } - }; - - factory = gtk_icon_factory_new (); - gtk_icon_factory_add_default (factory); - - for (i = 0; i < (gint) G_N_ELEMENTS (items); i++) - { - GtkIconSet *icon_set; - GdkPixbuf *pixbuf; - - pixbuf = gdk_pixbuf_new_from_inline (-1, items[i].icon_data, - FALSE, - NULL); - - icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); - gtk_icon_factory_add (factory, items[i].stock_id, icon_set); - gtk_icon_set_unref (icon_set); - - g_object_unref (G_OBJECT (pixbuf)); - } - - g_object_unref (G_OBJECT (factory)); -} - -int -meta_ui_get_drag_threshold (MetaUI *ui) -{ - GtkSettings *settings; - int threshold; - - settings = gtk_widget_get_settings (GTK_WIDGET (ui->frames)); - - threshold = 8; - g_object_get (G_OBJECT (settings), "gtk-dnd-drag-threshold", &threshold, NULL); - - return threshold; -} - -MetaUIDirection -meta_ui_get_direction (void) -{ - if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL) - return META_UI_DIRECTION_RTL; - - return META_UI_DIRECTION_LTR; -} - -GdkPixbuf * -meta_ui_get_pixbuf_from_pixmap (Pixmap pmap) -{ - GdkPixmap *gpmap; - GdkScreen *screen; - GdkPixbuf *pixbuf; - GdkColormap *cmap; - int width, height, depth; - - gpmap = gdk_pixmap_foreign_new (pmap); - screen = gdk_drawable_get_screen (gpmap); - - gdk_drawable_get_size (GDK_DRAWABLE (gpmap), &width, &height); - - depth = gdk_drawable_get_depth (GDK_DRAWABLE (gpmap)); - if (depth <= 24) - cmap = gdk_screen_get_rgb_colormap (screen); - else - cmap = gdk_screen_get_rgba_colormap (screen); - - pixbuf = gdk_pixbuf_get_from_drawable (NULL, gpmap, cmap, 0, 0, 0, 0, - width, height); - - g_object_unref (gpmap); - - return pixbuf; -} diff --git a/src/wm-tester/.cvsignore b/src/wm-tester/.cvsignore deleted file mode 100644 index 0bca29e8..00000000 --- a/src/wm-tester/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile -Makefile.in -focus-window -test-gravity -test-resizing -wm-tester -test-size-hints diff --git a/src/wm-tester/Makefile.am b/src/wm-tester/Makefile.am deleted file mode 100644 index e0c3048e..00000000 --- a/src/wm-tester/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ - -INCLUDES=@METACITY_CFLAGS@ - -wm_tester_SOURCES= \ - main.c - -test_gravity_SOURCES= \ - test-gravity.c - -focus_window_SOURCES= \ - focus-window.c - -test_resizing_SOURCES= \ - test-resizing.c - -test_size_hints_SOURCES= \ - test-size-hints.c - -noinst_PROGRAMS=wm-tester test-gravity test-resizing focus-window test-size-hints - -wm_tester_LDADD= @METACITY_LIBS@ -test_gravity_LDADD= @METACITY_LIBS@ -test_resizing_LDADD= @METACITY_LIBS@ -test_size_hints_LDADD= @METACITY_LIBS@ -focus_window_LDADD= @METACITY_LIBS@
\ No newline at end of file diff --git a/src/wm-tester/focus-window.c b/src/wm-tester/focus-window.c deleted file mode 100644 index dc33bd25..00000000 --- a/src/wm-tester/focus-window.c +++ /dev/null @@ -1,37 +0,0 @@ -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <stdio.h> -#include <stdlib.h> - -int main (int argc, char **argv) -{ - Display *d; - Window w; - const char *w_str; - char *end; - - if (argc != 2) - { - fprintf (stderr, "Usage: focus-window WINDOWID\n"); - exit (1); - } - - d = XOpenDisplay (NULL); - - w_str = argv[1]; - end = NULL; - - w = strtoul (w_str, &end, 16); - if (end == w_str) - { - fprintf (stderr, "Usage: focus-window WINDOWID\n"); - exit (1); - } - - printf ("Setting input focus to 0x%lx\n", w); - XSetInputFocus (d, w, RevertToPointerRoot, CurrentTime); - XFlush (d); - - return 0; -} - diff --git a/src/wm-tester/main.c b/src/wm-tester/main.c deleted file mode 100644 index e56d6606..00000000 --- a/src/wm-tester/main.c +++ /dev/null @@ -1,245 +0,0 @@ -/* WM tester main() */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include <gtk/gtk.h> - -#include <stdlib.h> -#include <sys/types.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -static void set_up_the_evil (void); -static void set_up_icon_windows (void); - -static void -usage (void) -{ - g_print ("wm-tester [--evil] [--icon-windows]\n"); - exit (0); -} - -int -main (int argc, char **argv) -{ - int i; - gboolean do_evil; - gboolean do_icon_windows; - - gtk_init (&argc, &argv); - - do_evil = FALSE; - do_icon_windows = FALSE; - - i = 1; - while (i < argc) - { - const char *arg = argv[i]; - - if (strcmp (arg, "--help") == 0 || - strcmp (arg, "-h") == 0 || - strcmp (arg, "-?") == 0) - usage (); - else if (strcmp (arg, "--evil") == 0) - do_evil = TRUE; - else if (strcmp (arg, "--icon-windows") == 0) - do_icon_windows = TRUE; - else - usage (); - - ++i; - } - - /* Be sure some option was provided */ - if (! (do_evil || do_icon_windows)) - return 1; - - if (do_evil) - set_up_the_evil (); - - if (do_icon_windows) - set_up_icon_windows (); - - gtk_main (); - - return 0; -} - -static GSList *evil_windows = NULL; - -static gint -evil_timeout (gpointer data) -{ - int i; - int n_windows; - int len; - int create_count; - int destroy_count; - - len = g_slist_length (evil_windows); - - if (len > 35) - { - create_count = 2; - destroy_count = 5; - } - else - { - create_count = 5; - destroy_count = 5; - } - - /* Create some windows */ - n_windows = g_random_int_range (0, create_count); - - i = 0; - while (i < n_windows) - { - GtkWidget *w; - GtkWidget *c; - int t; - GtkWidget *parent; - - w = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_widget_set_uposition (w, - g_random_int_range (0, - gdk_screen_width ()), - g_random_int_range (0, - gdk_screen_height ())); - - parent = NULL; - - /* set transient for random window (may create all kinds of weird cycles) */ - if (len > 0) - { - t = g_random_int_range (- (len / 3), len); - if (t >= 0) - { - parent = g_slist_nth_data (evil_windows, t); - - if (parent != NULL) - gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (parent)); - } - } - - if (parent != NULL) - c = gtk_button_new_with_label ("Evil Transient!"); - else - c = gtk_button_new_with_label ("Evil Window!"); - gtk_container_add (GTK_CONTAINER (w), c); - - gtk_widget_show_all (w); - - evil_windows = g_slist_prepend (evil_windows, w); - - ++i; - } - - /* Destroy some windows */ - if (len > destroy_count) - { - n_windows = g_random_int_range (0, destroy_count); - i = 0; - while (i < n_windows) - { - GtkWidget *w; - - w = g_slist_nth_data (evil_windows, - g_random_int_range (0, len)); - if (w) - { - --len; - evil_windows = g_slist_remove (evil_windows, w); - gtk_widget_destroy (w); - } - - ++i; - } - } - - return TRUE; -} - -static void -set_up_the_evil (void) -{ - g_timeout_add (400, evil_timeout, NULL); -} - -static void -set_up_icon_windows (void) -{ - int i; - int n_windows; - - /* Create some windows */ - n_windows = 9; - - i = 0; - while (i < n_windows) - { - GtkWidget *w; - GtkWidget *c; - GList *icons; - GdkPixbuf *pix; - - w = gtk_window_new (GTK_WINDOW_TOPLEVEL); - c = gtk_button_new_with_label ("Icon window"); - gtk_container_add (GTK_CONTAINER (w), c); - - icons = NULL; - - pix = gtk_widget_render_icon (w, - GTK_STOCK_SAVE, - GTK_ICON_SIZE_LARGE_TOOLBAR, - NULL); - - icons = g_list_append (icons, pix); - - if (i % 2) - { - pix = gtk_widget_render_icon (w, - GTK_STOCK_SAVE, - GTK_ICON_SIZE_DIALOG, - NULL); - icons = g_list_append (icons, pix); - } - - if (i % 3) - { - pix = gtk_widget_render_icon (w, - GTK_STOCK_SAVE, - GTK_ICON_SIZE_MENU, - NULL); - icons = g_list_append (icons, pix); - } - - gtk_window_set_icon_list (GTK_WINDOW (w), icons); - - g_list_foreach (icons, (GFunc) g_object_unref, NULL); - g_list_free (icons); - - gtk_widget_show_all (w); - - ++i; - } -} diff --git a/src/wm-tester/test-gravity.c b/src/wm-tester/test-gravity.c deleted file mode 100644 index 8e5b581c..00000000 --- a/src/wm-tester/test-gravity.c +++ /dev/null @@ -1,308 +0,0 @@ -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <stdio.h> -#include <string.h> - -static int gravities[10] = { - NorthWestGravity, - NorthGravity, - NorthEastGravity, - WestGravity, - CenterGravity, - EastGravity, - SouthWestGravity, - SouthGravity, - SouthEastGravity, - StaticGravity -}; - -typedef struct -{ - int x, y, width, height; -} Rectangle; - -static Window windows[10]; -static int doubled[10] = { 0, }; -static Rectangle window_rects[10]; - -#define WINDOW_WIDTH 100 -#define WINDOW_HEIGHT 100 - -static int x_offset[3] = { 0, - WINDOW_WIDTH/2, -WINDOW_WIDTH }; -static int y_offset[3] = { 0, - WINDOW_HEIGHT/2, -WINDOW_HEIGHT }; -static double screen_x_fraction[3] = { 0, 0.5, 1.0 }; -static double screen_y_fraction[3] = { 0, 0.5, 1.0 }; -static int screen_width; -static int screen_height; - -static const char* -window_gravity_to_string (int gravity) -{ - switch (gravity) - { - case NorthWestGravity: - return "NorthWestGravity"; - case NorthGravity: - return "NorthGravity"; - case NorthEastGravity: - return "NorthEastGravity"; - case WestGravity: - return "WestGravity"; - case CenterGravity: - return "CenterGravity"; - case EastGravity: - return "EastGravity"; - case SouthWestGravity: - return "SouthWestGravity"; - case SouthGravity: - return "SouthGravity"; - case SouthEastGravity: - return "SouthEastGravity"; - case StaticGravity: - return "StaticGravity"; - default: - return "NorthWestGravity"; - } -} - -static void -calculate_position (int i, int doubled, int *x, int *y) -{ - if (i == 9) - { - *x = 150; - *y = 150; - } - else - { - int xoff = x_offset[i % 3]; - int yoff = y_offset[i / 3]; - if (doubled) - { - xoff *= 2; - yoff *= 2; - } - - *x = screen_x_fraction[i % 3] * screen_width + xoff; - *y = screen_y_fraction[i / 3] * screen_height + yoff; - } -} - -static int -find_window (Window window) -{ - int i; - for (i=0; i<10; i++) - { - if (windows[i] == window) - return i; - } - - return -1; -} - -typedef struct { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long input_mode; - unsigned long status; -} MotifWmHints, MwmHints; - -#define MWM_HINTS_FUNCTIONS (1L << 0) -#define MWM_HINTS_DECORATIONS (1L << 1) -#define MWM_HINTS_INPUT_MODE (1L << 2) -#define MWM_HINTS_STATUS (1L << 3) - -int main (int argc, char **argv) -{ - Display *d; - Window w; - XSizeHints hints; - int i; - int screen; - XEvent ev; - int noframes; - - if (argc > 1 && strcmp (argv[1], "--noframes") == 0) - noframes = 1; - else - noframes = 0; - - d = XOpenDisplay (NULL); - - screen = DefaultScreen (d); - screen_width = DisplayWidth (d, screen); - screen_height = DisplayHeight (d, screen); - - for (i=0; i<10; i++) - { - int x, y; - - calculate_position (i, doubled[i], &x, &y); - - w = XCreateSimpleWindow (d, RootWindow (d, screen), - x, y, WINDOW_WIDTH, WINDOW_HEIGHT, 0, - WhitePixel (d, screen), WhitePixel (d, screen)); - - windows[i] = w; - window_rects[i].x = x; - window_rects[i].y = y; - window_rects[i].width = WINDOW_WIDTH; - window_rects[i].height = WINDOW_HEIGHT; - - XSelectInput (d, w, ButtonPressMask | ExposureMask | StructureNotifyMask); - - hints.flags = USPosition | PMinSize | PMaxSize | PWinGravity; - - hints.min_width = WINDOW_WIDTH / 2; - hints.min_height = WINDOW_HEIGHT / 2; - -#if 1 - /* we constrain max size below the "doubled" size so that - * the WM will have to deal with constraints - * at the same time it's dealing with configure request - */ - hints.max_width = WINDOW_WIDTH * 2 - WINDOW_WIDTH / 2; - hints.max_height = WINDOW_HEIGHT * 2 - WINDOW_HEIGHT / 2; -#else - hints.max_width = WINDOW_WIDTH * 2 + WINDOW_WIDTH / 2; - hints.max_height = WINDOW_HEIGHT * 2 + WINDOW_HEIGHT / 2; -#endif - hints.win_gravity = gravities[i]; - - XSetWMNormalHints (d, w, &hints); - - XStoreName (d, w, window_gravity_to_string (hints.win_gravity)); - - if (noframes) - { - MotifWmHints mwm; - Atom mwm_atom; - - mwm.decorations = 0; - mwm.flags = MWM_HINTS_DECORATIONS; - - mwm_atom = XInternAtom (d, "_MOTIF_WM_HINTS", False); - - XChangeProperty (d, w, mwm_atom, mwm_atom, - 32, PropModeReplace, - (unsigned char *)&mwm, - sizeof (MotifWmHints)/sizeof (long)); - } - - XMapWindow (d, w); - } - - while (1) - { - XNextEvent (d, &ev); - - if (ev.xany.type == ConfigureNotify) - { - i = find_window (ev.xconfigure.window); - - if (i >= 0) - { - Window ignored; - - window_rects[i].width = ev.xconfigure.width; - window_rects[i].height = ev.xconfigure.height; - - XClearArea (d, windows[i], 0, 0, - ev.xconfigure.width, - ev.xconfigure.height, - True); - - if (!ev.xconfigure.send_event) - XTranslateCoordinates (d, windows[i], DefaultRootWindow (d), - 0, 0, - &window_rects[i].x, &window_rects[i].y, - &ignored); - else - { - window_rects[i].x = ev.xconfigure.x; - window_rects[i].y = ev.xconfigure.y; - } - } - } - else if (ev.xany.type == Expose) - { - i = find_window (ev.xexpose.window); - - if (i >= 0) - { - GC gc; - XGCValues values; - char buf[256]; - - values.foreground = BlackPixel (d, screen); - - gc = XCreateGC (d, windows[i], - GCForeground, &values); - - sprintf (buf, - "%d,%d", - window_rects[i].x, - window_rects[i].y); - - XDrawString (d, windows[i], gc, 10, 15, - buf, strlen (buf)); - - sprintf (buf, - "%dx%d", - window_rects[i].width, - window_rects[i].height); - - XDrawString (d, windows[i], gc, 10, 35, - buf, strlen (buf)); - - XFreeGC (d, gc); - } - } - else if (ev.xany.type == ButtonPress) - { - i = find_window (ev.xbutton.window); - - if (i >= 0) - { - /* Button 1 = move, 2 = resize, 3 = both at once */ - - if (ev.xbutton.button == Button1) - { - int x, y; - - calculate_position (i, doubled[i], &x, &y); - XMoveWindow (d, windows[i], x, y); - } - else if (ev.xbutton.button == Button2) - { - if (doubled[i]) - XResizeWindow (d, windows[i], WINDOW_WIDTH, WINDOW_HEIGHT); - else - XResizeWindow (d, windows[i], WINDOW_WIDTH*2, WINDOW_HEIGHT*2); - - doubled[i] = !doubled[i]; - } - else if (ev.xbutton.button == Button3) - { - int x, y; - - calculate_position (i, !doubled[i], &x, &y); - - if (doubled[i]) - XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH, WINDOW_HEIGHT); - else - XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH*2, WINDOW_HEIGHT*2); - - doubled[i] = !doubled[i]; - } - } - } - } - - /* This program has an infinite loop above so a return statement would - * just cause compiler warnings. - */ -} - diff --git a/src/wm-tester/test-resizing.c b/src/wm-tester/test-resizing.c deleted file mode 100644 index f9481004..00000000 --- a/src/wm-tester/test-resizing.c +++ /dev/null @@ -1,257 +0,0 @@ -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <stdlib.h> -#include <glib.h> - -static void -calc_rects (XRectangle *rects, int width, int height) -{ - int w = (width - 21) / 3; - int h = (height - 21) / 3; - int i; - - i = 0; - while (i < 9) - { - rects[i].width = w; - rects[i].height = h; - ++i; - } - - /* NW */ - rects[0].x = 0; - rects[0].y = 0; - - /* N */ - rects[1].x = width / 2 - w / 2; - rects[1].y = 0; - - /* NE */ - rects[2].x = width - w; - rects[2].y = 0; - - /* E */ - rects[3].x = width - w; - rects[3].y = height / 2 - h / 2; - - /* SE */ - rects[4].x = width - w; - rects[4].y = height - h; - - /* S */ - rects[5].x = width / 2 - w / 2; - rects[5].y = height - h; - - /* SW */ - rects[6].x = 0; - rects[6].y = height - h; - - /* W */ - rects[7].x = 0; - rects[7].y = height / 2 - h / 2; - - /* Center */ - rects[8].x = width / 2 - w / 2; - rects[8].y = height / 2 - h / 2; -} - -static Bool -all_events (Display *display, - XEvent *event, - XPointer arg) -{ - return True; -} - -static void -get_size (Display *d, Drawable draw, - int *xp, int *yp, int *widthp, int *heightp) -{ - int x, y; - unsigned int width=0, height=0, border=0, depth=0; - Window root; - - XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth); - - if (xp) - *xp = x; - if (yp) - *yp = y; - if (widthp) - *widthp = width; - if (*heightp) - *heightp = height; -} - -int -main (int argc, char **argv) -{ - Display *d; - Window w, cw; - XSizeHints hints; - int screen; - XEvent ev; - int x, y, width, height; - Pixmap pix; - GC gc; - XGCValues gc_vals; - XSetWindowAttributes set_attrs; - XWindowChanges changes; - XRectangle rects[9]; - gboolean redraw_pending; - unsigned int mask; - - d = XOpenDisplay (NULL); - - screen = DefaultScreen (d); - - /* Print some debug spew to show how StaticGravity works */ - w = XCreateSimpleWindow (d, RootWindow (d, screen), - 0, 0, 100, 100, 0, - WhitePixel (d, screen), - WhitePixel (d, screen)); - cw = XCreateSimpleWindow (d, w, - 0, 0, 100, 100, 0, - WhitePixel (d, screen), - WhitePixel (d, screen)); - set_attrs.win_gravity = StaticGravity; - - XChangeWindowAttributes (d, cw, - CWWinGravity, - &set_attrs); - - get_size (d, w, &x, &y, &width, &height); - - g_print ("Parent is %d,%d %d x %d before configuring parent\n", - x, y, width, height); - - get_size (d, cw, &x, &y, &width, &height); - - g_print ("Child is %d,%d %d x %d before configuring parent\n", - x, y, width, height); - - changes.x = 10; - changes.y = 10; - changes.width = 110; - changes.height = 110; - /* last mask wins */ - mask = CWX | CWY; - mask = CWWidth | CWHeight; - mask = CWX | CWY | CWWidth | CWHeight; - - XConfigureWindow (d, w, mask, &changes); - XSync (d, False); - - get_size (d, w, &x, &y, &width, &height); - - g_print ("Parent is %d,%d %d x %d after configuring parent\n", - x, y, width, height); - - get_size (d, cw, &x, &y, &width, &height); - - g_print ("Child is %d,%d %d x %d after configuring parent\n", - x, y, width, height); - - XDestroyWindow (d, w); - - /* The window that gets displayed */ - - x = 20; - y = 20; - width = 100; - height = 100; - - calc_rects (rects, width, height); - - w = XCreateSimpleWindow (d, RootWindow (d, screen), - x, y, width, height, 0, - WhitePixel (d, screen), - WhitePixel (d, screen)); - - set_attrs.bit_gravity = StaticGravity; - - XChangeWindowAttributes (d, w, - CWBitGravity, - &set_attrs); - - XSelectInput (d, w, - ButtonPressMask | ExposureMask | StructureNotifyMask); - - hints.flags = PMinSize; - - hints.min_width = 100; - hints.min_height = 100; - - XSetWMNormalHints (d, w, &hints); - XMapWindow (d, w); - - redraw_pending = FALSE; - while (1) - { - XNextEvent (d, &ev); - - switch (ev.xany.type) - { - case ButtonPress: - if (ev.xbutton.button == 3) - { - g_print ("Exiting on button 3 press\n"); - exit (0); - } - break; - - case ConfigureNotify: - x = ev.xconfigure.x; - y = ev.xconfigure.y; - width = ev.xconfigure.width; - height = ev.xconfigure.height; - - redraw_pending = TRUE; - break; - - case Expose: - redraw_pending = TRUE; - break; - - default: - break; - } - - /* Primitive event compression */ - if (XCheckIfEvent (d, &ev, all_events, NULL)) - { - XPutBackEvent (d, &ev); - } - else if (redraw_pending) - { - calc_rects (rects, width, height); - - pix = XCreatePixmap (d, w, width, height, - DefaultDepth (d, screen)); - - gc_vals.foreground = WhitePixel (d, screen); - - gc = XCreateGC (d, pix, GCForeground, &gc_vals); - - XFillRectangle (d, pix, gc, 0, 0, width, height); - - /* Draw rectangles at each gravity point */ - gc_vals.foreground = BlackPixel (d, screen); - XChangeGC (d, gc, GCForeground, &gc_vals); - - XFillRectangles (d, pix, gc, rects, G_N_ELEMENTS (rects)); - - XCopyArea (d, pix, w, gc, 0, 0, width, height, 0, 0); - - XFreePixmap (d, pix); - XFreeGC (d, gc); - - redraw_pending = FALSE; - } - } - - /* This program has an infinite loop above so a return statement would - * just cause compiler warnings. - */ -} - diff --git a/src/wm-tester/test-size-hints.c b/src/wm-tester/test-size-hints.c deleted file mode 100644 index 72f1b486..00000000 --- a/src/wm-tester/test-size-hints.c +++ /dev/null @@ -1,136 +0,0 @@ -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <stdlib.h> -#include <glib.h> - -static Bool -all_events (Display *display, - XEvent *event, - XPointer arg) -{ - return True; -} - -#if 0 -static void -get_size (Display *d, Drawable draw, - int *xp, int *yp, int *widthp, int *heightp) -{ - int x, y; - unsigned int width, height, border, depth; - Window root; - - XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth); - - if (xp) - *xp = x; - if (yp) - *yp = y; - if (widthp) - *widthp = width; - if (*heightp) - *heightp = height; -} -#endif - -int -main (int argc, char **argv) -{ - Display *d; - Window zero_min_size; - XSizeHints hints; - int screen; - XEvent ev; - int x, y, width, height; - Pixmap pix; - GC gc; - XGCValues gc_vals; - gboolean redraw_pending; - - d = XOpenDisplay (NULL); - - screen = DefaultScreen (d); - - x = 0; - y = 0; - width = 100; - height = 100; - - zero_min_size = XCreateSimpleWindow (d, RootWindow (d, screen), - x, y, width, height, 0, - WhitePixel (d, screen), - WhitePixel (d, screen)); - - XSelectInput (d, zero_min_size, - ButtonPressMask | ExposureMask | StructureNotifyMask); - - hints.flags = PMinSize; - - hints.min_width = 0; - hints.min_height = 0; - - XSetWMNormalHints (d, zero_min_size, &hints); - XMapWindow (d, zero_min_size); - - redraw_pending = FALSE; - while (1) - { - XNextEvent (d, &ev); - - switch (ev.xany.type) - { - case ButtonPress: - if (ev.xbutton.button == 1) - { - g_print ("Exiting on button 1 press\n"); - exit (0); - } - break; - - case ConfigureNotify: - x = ev.xconfigure.x; - y = ev.xconfigure.y; - width = ev.xconfigure.width; - height = ev.xconfigure.height; - - redraw_pending = TRUE; - break; - - case Expose: - redraw_pending = TRUE; - break; - - default: - break; - } - - /* Primitive event compression */ - if (XCheckIfEvent (d, &ev, all_events, NULL)) - { - XPutBackEvent (d, &ev); - } - else if (redraw_pending) - { - pix = XCreatePixmap (d, zero_min_size, width, height, - DefaultDepth (d, screen)); - - gc_vals.foreground = WhitePixel (d, screen); - - gc = XCreateGC (d, pix, GCForeground, &gc_vals); - - XFillRectangle (d, pix, gc, 0, 0, width, height); - - XCopyArea (d, pix, zero_min_size, gc, 0, 0, width, height, 0, 0); - - XFreePixmap (d, pix); - XFreeGC (d, gc); - - redraw_pending = FALSE; - } - } - - /* This program has an infinite loop above so a return statement would - * just cause compiler warnings. - */ -} - |