From 3243daee4483eb4f6ef4bb4d1a57af619af4e0a1 Mon Sep 17 00:00:00 2001 From: raveit65 Date: Dec 13 2013 20:51:43 +0000 Subject: initial import --- diff --git a/.gitignore b/.gitignore index e69de29..29f5e2a 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +/marco-1.7.0.git0403454e.tar.xz diff --git a/marco.spec b/marco.spec new file mode 100644 index 0000000..2569c5f --- /dev/null +++ b/marco.spec @@ -0,0 +1,315 @@ +%global _internal_version 0403454e + +Name: marco +Version: 1.7.0 +#Release: 1%%{?dist} +Release: 0.3.git%{_internal_version}%{?dist} +Summary: MATE Desktop window manager +License: LGPLv2+ and GPLv2+ +URL: http://mate-desktop.org +#Source0: http://pub.mate-desktop.org/releases/1.6/%%{name}-%%{version}.tar.xz + +# To generate tarball +# wget http://git.mate-desktop.org/%%{name}/snapshot/%%{name}-{_internal_version}.tar.xz -O %%{name}-%%{version}.git%%{_internal_version}.tar.xz +Source0: http://raveit65.fedorapeople.org/Mate/git-upstream/%{name}-%{version}.git%{_internal_version}.tar.xz + +# needed for fixing initial-setup issue, rhbz (#962009) +Source1: mini-window.png +Source2: stock_delete.png +Source3: stock_maximize.png +Source4: stock_minimize.png +Source5: window.png + +# needed for fixing initial-setup issue, rhbz (#962009) +Patch0: marco_add-pixbuf-inline-icons.patch +Patch1: marco_implement-side-by-side-tiling.patch +Patch2: marco_window-snapping-top-screen.patch + +BuildRequires: desktop-file-utils +BuildRequires: gtk2-devel +BuildRequires: libcanberra-devel +BuildRequires: libgtop2-devel +BuildRequires: libSM-devel +BuildRequireS: libsoup-devel +BuildRequires: libXdamage-devel +BuildRequires: mate-common +BuildRequires: mate-dialogs +BuildRequires: startup-notification-devel +BuildRequires: yelp-tools + +# http://bugzilla.redhat.com/873342 +# https://bugzilla.redhat.com/962009 +Provides: firstboot(windowmanager) = marco + +Provides: mate-window-manager%{?_isa} = %{version}-%{release} +Obsoletes: mate-window-manager%{?_isa} < %{version}-%{release} + +%description +MATE Desktop window manager + +%package devel +Summary: Development files for mate-window-manager +Requires: %{name}%{?_isa} = %{version}-%{release} +Provides: mate-window-manager-devel%{?_isa} = %{version}-%{release} +Obsoletes: mate-window-manager-devel%{?_isa} < %{version}-%{release} + +%description devel +Development files for marco + +%prep +#%%setup -q +%setup -q -n %{name}-%{_internal_version} +# needed for missing `po/Makefile.in.in' +NOCONFIGURE=1 ./autogen.sh +cp %{SOURCE1} src/mini-window.png +cp %{SOURCE2} src/stock_delete.png +cp %{SOURCE3} src/stock_maximize.png +cp %{SOURCE4} src/stock_minimize.png +cp %{SOURCE5} src/window.png + +%patch0 -p1 -b .inline-icons +%patch1 -p1 -b .tiling +%patch2 -p1 -b .snapping-top-screen + +autoreconf -if + +%build +%configure --disable-static \ + --disable-schemas-compile \ + --with-gtk=2.0 \ + --with-x + +# fix rpmlint unused-direct-shlib-dependency warning +sed -i -e 's! -shared ! -Wl,--as-needed\0!g' libtool + +make %{?_smp_mflags} V=1 + + +%install +make install DESTDIR=%{buildroot} + +find %{buildroot} -name '*.la' -exec rm -vf {} ';' + +desktop-file-install \ + --delete-original \ + --dir=%{buildroot}%{_datadir}/applications \ +%{buildroot}%{_datadir}/applications/marco.desktop + +# remove needless gsettings convert file +rm -f %{buildroot}%{_datadir}/MateConf/gsettings/marco.convert + +%find_lang %{name} --with-gnome --all-name + + +%post -p /sbin/ldconfig + +%postun +/sbin/ldconfig +if [ $1 -eq 0 ] ; then + /usr/bin/glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : +fi + +%posttrans + /usr/bin/glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : + + +%files -f %{name}.lang +%doc AUTHORS COPYING README ChangeLog +%{_bindir}/marco +%{_bindir}/marco-message +%{_datadir}/applications/marco.desktop +%{_datadir}/themes/ClearlooksRe +%{_datadir}/themes/Dopple-Left +%{_datadir}/themes/Dopple +%{_datadir}/themes/DustBlue +%{_datadir}/themes/Spidey-Left +%{_datadir}/themes/Spidey +%{_datadir}/themes/Splint-Left +%{_datadir}/themes/Splint +%{_datadir}/themes/WinMe +%{_datadir}/themes/eOS +%dir %{_datadir}/marco +%dir %{_datadir}/marco/icons +%{_datadir}/marco/icons/marco-window-demo.png +%{_datadir}/mate-control-center/keybindings/50-marco*.xml +%{_datadir}/mate/wm-properties +%{_datadir}/glib-2.0/schemas/org.mate.marco.gschema.xml +%{_libdir}/libmarco-private.so.0* +%{_mandir}/man1/* + +%files devel +%{_bindir}/marco-theme-viewer +%{_bindir}/marco-window-demo +%{_includedir}/marco-1 +%{_libdir}/libmarco-private.so +%{_libdir}/pkgconfig/libmarco-private.pc +%{_mandir}/man1/marco-theme-viewer.1.* +%{_mandir}/man1/marco-window-demo.1.* + + +%changelog +* Wed Dec 11 2013 Wolfgang Ulbrich - 1.7.0-0.3.git0403454e +- using 8 digets in git version to update mate-window-manager + +* Wed Dec 11 2013 Wolfgang Ulbrich - 1.7.0-0.2.git0403454 +- rename mate-window-manager to marco + +* Fri Dec 06 2013 Dan Mashal - 1.7.0-1.1.git0403454 +- Update to 1.7.0 git snapshot + +* Wed Nov 13 2013 Wolfgang Ulbrich - 1.6.2-6 +- start with side-by-side-tiling and windows-snapping-top-screen support for f20 + +* Fri Sep 27 2013 Wolfgang Ulbrich - 1.6.2-5 +- fix initial-setup issue, rhbz (#962009) + +* Sat Aug 03 2013 Fedora Release Engineering - 1.6.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Sat Jun 15 2013 Wolfgang Ulbrich - 1.6.2-3 +- remove gsettings convert file + +* Tue Jun 11 2013 Dan Mashal - 1.6.2-2 +- Add libgtop2-devel to BR's + +* Sat Jun 08 2013 Dan Mashal - 1.6.2-1 +- Update to latest upstream release +- Update datadir to mate-window-manager instead of marco + +* Sat Jun 08 2013 Dan Mashal - 1.6.1-2 +- Fix initial-setup, hopefully. + +* Wed Apr 03 2013 Dan Mashal - 1.6.1-1 +- Bug fix release. See changelog. + +* Wed Apr 03 2013 Dan Mashal - 1.6.0-1 +- Update to latest 1.6.0 stable release. + +* Mon Mar 25 2013 Dan Mashal - 1.5.5-1 +- Update to latest upstream release +- Own dirs that we are supposed to owp + +* Fri Feb 22 2013 Dan Mashal - 1.5.4-1 +- Update to latest upstream release + +* Mon Feb 18 2013 Dan Mashal - 1.5.3-4 +- Add latest upstream commits + +* Tue Jan 29 2013 Dan Mashal - 1.5.3-3 +- Add some configure flags + +* Fri Jan 18 2013 Dan Mashal - 1.5.3-2 +- Sort BR's +- Remove unneeded obsoletes tag + +* Mon Jan 14 2013 Dan Mashal - 1.5.3-1 +- Update to latest upstream release + +* Fri Jan 11 2013 Dan Mashal - 1.5.2-11 +- Convert back to old BR format +- Drop unneeded BRs +- Own directories that are supposed to be owned (marco-1) +- Fix missing "X-Mate" category. +- Add gsettings data convert file for users upgrading from 1.4 +- Fix update of gsettings enum preferences + +* Mon Dec 10 2012 Dan Mashal - 1.5.2-10 +- Rebuild for ARM + +* Sun Nov 25 2012 Dan Mashal - 1.5.2-9 +- Remove hard requires on mwm and mate-themes. + +* Sun Nov 25 2012 Dan Mashal - 1.5.2-8 +- Add xdamage as it is required for build + +* Wed Nov 14 2012 Leigh Scott - 1.5.2-7 +- move development files to devel +- remove the config.h defines from %%build section + +* Tue Nov 13 2012 Dan Mashal - 1.5.2-6 +- Update configure flags, add disable scrollkeeper mainly + +* Tue Nov 13 2012 Leigh Scott - 1.5.2-5 +- add patch to fix startup rendering effect with composite enabled + +* Tue Nov 06 2012 Rex Dieter 1.5.2-4 +- Provides: firstboot(windowmanager) (#873342) + +* Mon Nov 05 2012 Rex Dieter 1.5.2-3 +- drop Provides: firstboot(windowmanager) until bug #873342 is fixed + +* Sat Nov 03 2012 Leigh Scott - 1.5.2-2 +- Provides firstboot(windowmanager) mate-window-manager + +* Mon Oct 29 2012 Leigh Scott - 1.5.2-1 +- update to 1.5.2 release +- add schema scriptlets and remove mateconf scriptlets +- add requires gsettings-desktop-schemas +- add build requires gsettings-desktop-schemas-devel and dconf-devel +- change build requires style + +* Wed Oct 17 2012 Leigh Scott - 1.4.1-12 +- Fix crash if you have lots of workspaces + +* Tue Oct 16 2012 Leigh Scott - 1.4.1-11 +- filter provides +- fix build requires +- fix reqires +- define some defaults +- Add patch to allow breaking out from maximization during mouse resize + (gnome bz 622517) + +* Wed Sep 26 2012 Rex Dieter - 1.4.1-10 +- fix ldconfig scriptlets +- use desktop-file-validate again +- own %%{_datadir}/mate/wm-properties/ + +* Tue Sep 25 2012 Dan Mashal 1.4.1-9 +- Remove mateconf obsolete scriplet + +* Mon Sep 24 2012 Dan Mashal 1.4.1-8 +- rerefix mate-conf scriptlets. Add export line to REALLY not install schemas with make install. +- comment out desktop-file-validate. + +* Mon Sep 17 2012 Rex Dieter 1.4.1-7 +- fix/simplify dir ownership +- omit not-needed/broken Obsoletes +- (re)fix scriptlets :) + +* Sat Sep 15 2012 Dan Mashal 1.4.1-6 +- Move post and postun scriptlets to proper location + +* Sat Sep 15 2012 Dan Mashal 1.4.1-5 +- Remove onlyshowin since it is not needed any more with updated desktop-file-utils + +* Sat Sep 15 2012 Dan Mashal 1.4.1-4 +- Update source to note git version. + +* Sun Sep 09 2012 Dan Mashal 1.4.1-3 +- Fix broken dependencies, update to latest github version which contains fixes for desktop-file-utils + +* Mon Sep 03 2012 Dan Mashal 1.4.1-2 +- Add environment variable to install section and further obsoletes to prevent dependency breakage + +* Sun Sep 02 2012 Dan Mashal 1.4.1-1 +- Upgrade to new upstream version. + +* Mon Aug 27 2012 Rex Dieter 1.4.0-5 +- drop unneeded python-related build deps +- %%configure --disable-schemas-install +- fix/simplify some parent-dir ownership + +* Mon Aug 27 2012 Rex Dieter 1.4.0-4 +- main pkg Requires: %%name-libs +- drop needless icon scriptlets +- s|MATE|X-MATE| .desktop Categories on < f18 only +- License: GPLv2+ + +* Sun Aug 26 2012 Dan Mashal 1.4.0-3 +- Own theme directories that are being installed, switch from po_package to namefor lang files, bump release version + +* Sun Aug 26 2012 Dan Mashal 1.4.0-2 +- Add mateconf scriptlets + +* Sun Aug 12 2012 Dan Mashal 1.4.0-1 +- Initial build diff --git a/marco_add-pixbuf-inline-icons.patch b/marco_add-pixbuf-inline-icons.patch new file mode 100644 index 0000000..81d411b --- /dev/null +++ b/marco_add-pixbuf-inline-icons.patch @@ -0,0 +1,146 @@ +diff -uprN mate-window-manager-1.6.2-orig/src/Makefile.am mate-window-manager-1.6.2/src/Makefile.am +--- mate-window-manager-1.6.2-orig/src/Makefile.am 2013-06-09 00:38:35.000000000 +0200 ++++ mate-window-manager-1.6.2/src/Makefile.am 2013-09-27 21:21:10.617271967 +0200 +@@ -185,14 +185,27 @@ xml_in_files = \ + 50-marco-global-key.xml.in + xml_DATA = $(xml_in_files:.xml.in=.xml) + +-BUILT_SOURCES = ++@INTLTOOL_SCHEMAS_RULE@ ++ ++IMAGES=stock_maximize.png stock_minimize.png stock_delete.png window.png mini-window.png ++VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \ ++ stock_minimize_data $(srcdir)/stock_minimize.png \ ++ stock_delete_data $(srcdir)/stock_delete.png \ ++ mini_window_data $(srcdir)/mini-window.png \ ++ window_data $(srcdir)/window.png ++ ++BUILT_SOURCES = inlinepixbufs.h + CLEANFILES = \ ++ inlinepixbufs.h \ + marco.desktop \ + marco-wm.desktop \ + 50-marco-desktop-key.xml \ + 50-marco-global-key.xml \ + 50-marco-window-key.xml + ++inlinepixbufs.h: $(IMAGES) ++ $(AM_V_GEN)$(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h ++ + pkgconfigdir = $(libdir)/pkgconfig + + pkgconfig_DATA = libmarco-private.pc +diff -uprN mate-window-manager-1.6.2-orig/src/ui/ui.c mate-window-manager-1.6.2/src/ui/ui.c +--- mate-window-manager-1.6.2-orig/src/ui/ui.c 2013-06-09 00:38:35.000000000 +0200 ++++ mate-window-manager-1.6.2/src/ui/ui.c 2013-09-27 21:47:23.789571527 +0200 +@@ -28,9 +28,12 @@ + #include "core.h" + #include "theme.h" + ++#include "inlinepixbufs.h" ++ + #include + #include + ++static void meta_stock_icons_init (void); + static void meta_ui_accelerator_parse(const char* accel, guint* keysym, guint* keycode, GdkModifierType* keymask); + + struct _MetaUI { +@@ -51,6 +54,7 @@ void meta_ui_init(int* argc, char*** arg + if (!gtk_init_check (argc, argv)) + { + meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL)); ++ meta_stock_icons_init (); + } + } + +@@ -547,6 +551,7 @@ meta_image_window_set (MetaImageWindow * + int x, + int y) + { ++ GdkWindow *window; + cairo_t *cr; + + /* We use a back pixmap to avoid having to handle exposes, because +@@ -568,7 +573,8 @@ meta_image_window_set (MetaImageWindow * + cairo_paint (cr); + cairo_destroy (cr); + +- gdk_window_set_back_pixmap (iw->window->window, ++ window = gtk_widget_get_window (iw->window); ++ gdk_window_set_back_pixmap (window, + iw->pixmap, + FALSE); + +@@ -732,11 +738,9 @@ meta_ui_get_default_window_icon (MetaUI + 0, + NULL); + else +- default_icon = gtk_icon_theme_load_icon (theme, +- "gtk-missing-image", +- META_ICON_WIDTH, +- 0, +- NULL); ++ default_icon = gdk_pixbuf_new_from_inline (-1, window_data, ++ FALSE, ++ NULL); + + g_assert (default_icon); + } +@@ -767,11 +771,9 @@ meta_ui_get_default_mini_icon (MetaUI *u + 0, + NULL); + else +- default_icon = gtk_icon_theme_load_icon (theme, +- "gtk-missing-image", +- META_MINI_ICON_WIDTH, +- 0, +- NULL); ++ default_icon = gdk_pixbuf_new_from_inline (-1, window_data, ++ FALSE, ++ NULL); + + g_assert (default_icon); + } +@@ -1058,6 +1060,41 @@ typedef struct { + const guint8* icon_data; + } MetaStockIcon; + ++static void ++meta_stock_icons_init (void) ++{ ++ GtkIconFactory *factory; ++ int i; ++ ++ MetaStockIcon items[] = ++ { ++ { MARCO_STOCK_DELETE, stock_delete_data }, ++ { MARCO_STOCK_MINIMIZE, stock_minimize_data }, ++ { MARCO_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) + { + int threshold = 8; diff --git a/marco_implement-side-by-side-tiling.patch b/marco_implement-side-by-side-tiling.patch new file mode 100644 index 0000000..7dccc81 --- /dev/null +++ b/marco_implement-side-by-side-tiling.patch @@ -0,0 +1,1061 @@ +From a87157176ca6e01c8c4047999ee584f00b63c11e Mon Sep 17 00:00:00 2001 +From: Stefano Karapetsas +Date: Fri, 31 May 2013 14:22:39 +0000 +Subject: Implement side-by-side tiling + +Patch by Florian Müllner for Metacity +https://bugzilla.gnome.org/show_bug.cgi?id=607694 + +When dragging a window over a screen edge and dropping it there, +maximize it vertically and scale it horizontally to cover the +corresponding half of the current monitor. + +Whenever a "hot area" which triggers this behavior is entered, an +indication of window's target size is displayed after a short delay +to avoid distraction when moving a window between monitors. +--- +diff --git a/src/Makefile.am b/src/Makefile.am +index a7b0123..9326361 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -98,6 +98,8 @@ marco_SOURCES = \ + include/resizepopup.h \ + ui/tabpopup.c \ + include/tabpopup.h \ ++ ui/tile-preview.c \ ++ include/tile-preview.h \ + ui/theme-parser.c \ + ui/theme-parser.h \ + ui/theme.c \ +diff --git a/src/core/constraints.c b/src/core/constraints.c +index 16d9b10..a79f858 100644 +--- a/src/core/constraints.c ++++ b/src/core/constraints.c +@@ -98,6 +98,7 @@ typedef enum + PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1, + PRIORITY_SIZE_HINTS_INCREMENTS = 1, + PRIORITY_MAXIMIZATION = 2, ++ PRIORITY_TILING = 2, + PRIORITY_FULLSCREEN = 2, + PRIORITY_SIZE_HINTS_LIMITS = 3, + PRIORITY_TITLEBAR_VISIBLE = 4, +@@ -145,6 +146,10 @@ static gboolean constrain_maximization (MetaWindow *window, + ConstraintInfo *info, + ConstraintPriority priority, + gboolean check_only); ++static gboolean constrain_tiling (MetaWindow *window, ++ ConstraintInfo *info, ++ ConstraintPriority priority, ++ gboolean check_only); + static gboolean constrain_fullscreen (MetaWindow *window, + ConstraintInfo *info, + ConstraintPriority priority, +@@ -211,6 +216,7 @@ typedef struct { + + static const Constraint all_constraints[] = { + {constrain_maximization, "constrain_maximization"}, ++ {constrain_tiling, "constrain_tiling"}, + {constrain_fullscreen, "constrain_fullscreen"}, + {constrain_size_increments, "constrain_size_increments"}, + {constrain_size_limits, "constrain_size_limits"}, +@@ -731,7 +737,8 @@ constrain_maximization (MetaWindow *window, + return TRUE; + + /* Determine whether constraint applies; exit if it doesn't */ +- if (!window->maximized_horizontally && !window->maximized_vertically) ++ if ((!window->maximized_horizontally && !window->maximized_vertically) || ++ META_WINDOW_TILED (window)) + return TRUE; + + /* Calculate target_size = maximized size of (window + frame) */ +@@ -800,6 +807,58 @@ constrain_maximization (MetaWindow *window, + } + + static gboolean ++constrain_tiling (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_TILING) ++ return TRUE; ++ ++ /* Determine whether constraint applies; exit if it doesn't */ ++ if (!META_WINDOW_TILED (window)) ++ return TRUE; ++ ++ /* Calculate target_size - as the tile previews need this as well, we ++ * use an external function for the actual calculation ++ */ ++ meta_window_get_current_tile_area (window, &target_size); ++ unextend_by_frame (&target_size, info->fgeom); ++ ++ /* Check min size constraints; max size constraints are ignored as for ++ * maximized windows. ++ */ ++ get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size); ++ hminbad = target_size.width < min_size.width; ++ vminbad = target_size.height < min_size.height; ++ 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 && vert_equal; ++ if (check_only || constraint_already_satisfied) ++ return constraint_already_satisfied; ++ ++ /*** Enforce constraint ***/ ++ info->current.x = target_size.x; ++ info->current.width = target_size.width; ++ info->current.y = target_size.y; ++ info->current.height = target_size.height; ++ ++ return TRUE; ++} ++ ++static gboolean + constrain_fullscreen (MetaWindow *window, + ConstraintInfo *info, + ConstraintPriority priority, +@@ -850,7 +909,7 @@ constrain_size_increments (MetaWindow *window, + + /* Determine whether constraint applies; exit if it doesn't */ + if (META_WINDOW_MAXIMIZED (window) || window->fullscreen || +- info->action_type == ACTION_MOVE) ++ META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE) + return TRUE; + + /* Determine whether constraint is already satisfied; exit if it is */ +@@ -981,7 +1040,7 @@ constrain_aspect_ratio (MetaWindow *window, + constraints_are_inconsistent = minr > maxr; + if (constraints_are_inconsistent || + META_WINDOW_MAXIMIZED (window) || window->fullscreen || +- info->action_type == ACTION_MOVE) ++ META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE) + return TRUE; + + /* Determine whether constraint is already satisfied; exit if it is. We +diff --git a/src/core/core.c b/src/core/core.c +index 76e5548..c8fa02b 100644 +--- a/src/core/core.c ++++ b/src/core/core.c +@@ -28,6 +28,7 @@ + #include "frame-private.h" + #include "workspace.h" + #include "prefs.h" ++#include "errors.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. +@@ -297,6 +298,35 @@ meta_core_user_lower_and_unfocus (Display *xdisplay, + } + + void ++meta_core_lower_beneath_focus_window (Display *xdisplay, ++ Window xwindow, ++ guint32 timestamp) ++{ ++ XWindowChanges changes; ++ MetaDisplay *display; ++ MetaScreen *screen; ++ MetaWindow *focus_window; ++ ++ display = meta_display_for_x_display (xdisplay); ++ screen = meta_display_screen_for_xwindow (display, xwindow); ++ focus_window = meta_stack_get_top (screen->stack); ++ ++ if (focus_window == NULL) ++ return; ++ ++ changes.stack_mode = Below; ++ changes.sibling = focus_window->frame ? focus_window->frame->xwindow ++ : focus_window->xwindow; ++ ++ meta_error_trap_push (display); ++ XConfigureWindow (xdisplay, ++ xwindow, ++ CWSibling | CWStackMode, ++ &changes); ++ meta_error_trap_pop (display, FALSE); ++} ++ ++void + meta_core_user_focus (Display *xdisplay, + Window frame_xwindow, + guint32 timestamp) +diff --git a/src/core/prefs.c b/src/core/prefs.c +index 116a9bb..5f46b55 100644 +--- a/src/core/prefs.c ++++ b/src/core/prefs.c +@@ -117,6 +117,7 @@ static gboolean compositing_fast_alt_tab = FALSE; + static gboolean resize_with_right_button = FALSE; + static gboolean center_new_windows = FALSE; + static gboolean force_fullscreen = TRUE; ++static gboolean side_by_side_tiling = FALSE; + + static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH; + static MetaButtonLayout button_layout; +@@ -401,6 +402,12 @@ static MetaBoolPreference preferences_bool[] = + ¢er_new_windows, + FALSE, + }, ++ { "side-by-side-tiling", ++ KEY_GENERAL_SCHEMA, ++ META_PREF_SIDE_BY_SIDE_TILING, ++ &side_by_side_tiling, ++ FALSE, ++ }, + { NULL, NULL, 0, NULL, FALSE }, + }; + +@@ -1545,6 +1552,9 @@ meta_preference_to_string (MetaPreference pref) + + case META_PREF_FORCE_FULLSCREEN: + return "FORCE_FULLSCREEN"; ++ ++ case META_PREF_SIDE_BY_SIDE_TILING: ++ return "SIDE_BY_SIDE_TILING"; + } + + return "(unknown)"; +@@ -2202,6 +2212,12 @@ meta_prefs_get_center_new_windows (void) + return center_new_windows; + } + ++gboolean ++meta_prefs_get_side_by_side_tiling () ++{ ++ return side_by_side_tiling; ++} ++ + guint + meta_prefs_get_mouse_button_resize (void) + { +diff --git a/src/core/screen-private.h b/src/core/screen-private.h +index 77ea457..8eb02d0 100644 +--- a/src/core/screen-private.h ++++ b/src/core/screen-private.h +@@ -79,6 +79,9 @@ struct _MetaScreen + MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */ + MetaUI *ui; + MetaTabPopup *tab_popup; ++ MetaTilePreview *tile_preview; ++ ++ guint tile_preview_timeout_id; + + MetaWorkspace *active_workspace; + +@@ -160,6 +163,8 @@ void meta_screen_ensure_tab_popup (MetaScreen *scree + MetaTabList list_type, + MetaTabShowType show_type); + void meta_screen_ensure_workspace_popup (MetaScreen *screen); ++void meta_screen_tile_preview_update (MetaScreen *screen, ++ gboolean delay); + + MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen, + MetaWindow *not_this_one); +diff --git a/src/core/screen.c b/src/core/screen.c +index e8fce40..eefe58f 100644 +--- a/src/core/screen.c ++++ b/src/core/screen.c +@@ -582,7 +582,10 @@ meta_screen_new (MetaDisplay *display, + screen->xscreen); + + screen->tab_popup = NULL; +- ++ screen->tile_preview = NULL; ++ ++ screen->tile_preview_timeout_id = 0; ++ + screen->stack = meta_stack_new (screen); + + meta_prefs_add_listener (prefs_changed_callback, screen); +@@ -691,7 +694,13 @@ meta_screen_free (MetaScreen *screen, + + if (screen->xinerama_infos) + g_free (screen->xinerama_infos); +- ++ ++ if (screen->tile_preview_timeout_id) ++ g_source_remove (screen->tile_preview_timeout_id); ++ ++ if (screen->tile_preview) ++ meta_tile_preview_free (screen->tile_preview); ++ + g_free (screen->screen_name); + g_free (screen); + +@@ -1451,6 +1460,59 @@ meta_screen_ensure_workspace_popup (MetaScreen *screen) + /* don't show tab popup, since proper space isn't selected yet */ + } + ++static gboolean ++meta_screen_tile_preview_update_timeout (gpointer data) ++{ ++ MetaScreen *screen = data; ++ MetaWindow *window = screen->display->grab_window; ++ gboolean composited = screen->display->compositor != NULL; ++ ++ screen->tile_preview_timeout_id = 0; ++ ++ if (!screen->tile_preview) ++ screen->tile_preview = meta_tile_preview_new (screen->number, ++ composited); ++ ++ if (window ++ && !META_WINDOW_TILED (window) ++ && window->tile_mode != META_TILE_NONE) ++ { ++ MetaRectangle tile_rect; ++ ++ meta_window_get_current_tile_area (window, &tile_rect); ++ meta_tile_preview_show (screen->tile_preview, &tile_rect); ++ } ++ else ++ meta_tile_preview_hide (screen->tile_preview); ++ ++ return FALSE; ++} ++ ++#define TILE_PREVIEW_TIMEOUT_MS 200 ++ ++void ++meta_screen_tile_preview_update (MetaScreen *screen, ++ gboolean delay) ++{ ++ if (delay) ++ { ++ if (screen->tile_preview_timeout_id > 0) ++ return; ++ ++ screen->tile_preview_timeout_id = ++ g_timeout_add (TILE_PREVIEW_TIMEOUT_MS, ++ meta_screen_tile_preview_update_timeout, ++ screen); ++ } ++ else ++ { ++ if (screen->tile_preview_timeout_id > 0) ++ g_source_remove (screen->tile_preview_timeout_id); ++ ++ meta_screen_tile_preview_update_timeout ((gpointer)screen); ++ } ++} ++ + MetaWindow* + meta_screen_get_mouse_window (MetaScreen *screen, + MetaWindow *not_this_one) +diff --git a/src/core/window-private.h b/src/core/window-private.h +index 447a2c4..02c518e 100644 +--- a/src/core/window-private.h ++++ b/src/core/window-private.h +@@ -83,6 +83,12 @@ typedef enum { + + #define NUMBER_OF_QUEUES 3 + ++typedef enum { ++ META_TILE_NONE, ++ META_TILE_LEFT, ++ META_TILE_RIGHT ++} MetaTileMode; ++ + struct _MetaWindow + { + MetaDisplay *display; +@@ -138,6 +144,11 @@ struct _MetaWindow + guint maximize_vertically_after_placement : 1; + guint minimize_after_placement : 1; + ++ /* The current or requested tile mode. If maximized_vertically is true, ++ * this is the current mode. If not, it is the mode which will be ++ * requested after the window grab is released */ ++ guint tile_mode : 2; ++ + /* Whether we're shaded */ + guint shaded : 1; + +@@ -383,8 +394,11 @@ struct _MetaWindow + (w)->maximized_vertically) + #define META_WINDOW_MAXIMIZED_VERTICALLY(w) ((w)->maximized_vertically) + #define META_WINDOW_MAXIMIZED_HORIZONTALLY(w) ((w)->maximized_horizontally) ++#define META_WINDOW_TILED(w) ((w)->maximized_vertically && \ ++ !(w)->maximized_horizontally && \ ++ (w)->tile_mode != META_TILE_NONE) + #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_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !META_WINDOW_TILED(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))) +@@ -575,6 +589,8 @@ void meta_window_get_work_area_for_xinerama (MetaWindow *window, + void meta_window_get_work_area_all_xineramas (MetaWindow *window, + MetaRectangle *area); + ++void meta_window_get_current_tile_area (MetaWindow *window, ++ MetaRectangle *tile_area); + + gboolean meta_window_same_application (MetaWindow *window, + MetaWindow *other_window); +diff --git a/src/core/window.c b/src/core/window.c +index d997bae..7a7f6be 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -470,6 +470,7 @@ meta_window_new_with_attrs (MetaDisplay *display, + window->require_on_single_xinerama = TRUE; + window->require_titlebar_visible = TRUE; + window->on_all_workspaces = FALSE; ++ window->tile_mode = META_TILE_NONE; + window->shaded = FALSE; + window->initially_iconic = FALSE; + window->minimized = FALSE; +@@ -2489,7 +2490,7 @@ ensure_size_hints_satisfied (MetaRectangle *rect, + static void + meta_window_save_rect (MetaWindow *window) + { +- if (!(META_WINDOW_MAXIMIZED (window) || window->fullscreen)) ++ if (!(META_WINDOW_MAXIMIZED (window) || META_WINDOW_TILED (window) || window->fullscreen)) + { + /* save size/pos as appropriate args for move_resize */ + if (!window->maximized_horizontally) +@@ -2531,7 +2532,7 @@ force_save_user_window_placement (MetaWindow *window) + static void + save_user_window_placement (MetaWindow *window) + { +- if (!(META_WINDOW_MAXIMIZED (window) || window->fullscreen)) ++ if (!(META_WINDOW_MAXIMIZED (window) || META_WINDOW_TILED (window) || window->fullscreen)) + { + MetaRectangle user_rect; + +@@ -2596,6 +2597,7 @@ void + meta_window_maximize (MetaWindow *window, + MetaMaximizeFlags directions) + { ++ MetaRectangle *saved_rect = NULL; + /* At least one of the two directions ought to be set */ + gboolean maximize_horizontally, maximize_vertically; + maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; +@@ -2631,9 +2633,16 @@ meta_window_maximize (MetaWindow *window, + return; + } + ++ if (window->tile_mode != META_TILE_NONE) ++ { ++ saved_rect = &window->saved_rect; ++ ++ window->maximized_vertically = FALSE; ++ } ++ + meta_window_maximize_internal (window, + directions, +- NULL); ++ saved_rect); + + /* move_resize with new maximization constraints + */ +@@ -2673,12 +2682,64 @@ unmaximize_window_before_freeing (MetaWindow *window) + } + } + ++static void ++meta_window_tile (MetaWindow *window) ++{ ++ /* Don't do anything if no tiling is requested */ ++ if (window->tile_mode == META_TILE_NONE) ++ return; ++ ++ meta_window_maximize_internal (window, META_MAXIMIZE_VERTICAL, NULL); ++ meta_screen_tile_preview_update (window->screen, FALSE); ++ ++ /* move_resize with new tiling constraints ++ */ ++ meta_window_queue (window, META_QUEUE_MOVE_RESIZE); ++} ++ ++static gboolean ++meta_window_can_tile (MetaWindow *window) ++{ ++ const MetaXineramaScreenInfo *monitor; ++ MetaRectangle tile_area; ++ ++ if (!META_WINDOW_ALLOWS_RESIZE (window)) ++ return FALSE; ++ ++ monitor = meta_screen_get_current_xinerama (window->screen); ++ meta_window_get_work_area_for_xinerama (window, monitor->number, &tile_area); ++ ++ tile_area.width /= 2; ++ ++ if (window->frame) ++ { ++ MetaFrameGeometry fgeom; ++ ++ meta_frame_calc_geometry (window->frame, &fgeom); ++ ++ tile_area.width -= (fgeom.left_width + fgeom.right_width); ++ tile_area.height -= (fgeom.top_height + fgeom.bottom_height); ++ } ++ ++ return tile_area.width >= window->size_hints.min_width && ++ tile_area.height >= window->size_hints.min_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; ++ ++ /* Restore tiling if necessary */ ++ if (window->tile_mode != META_TILE_NONE) ++ { ++ window->maximized_horizontally = FALSE; ++ meta_window_tile (window); ++ return; ++ } ++ + unmaximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; + unmaximize_vertically = directions & META_MAXIMIZE_VERTICAL; + g_assert (unmaximize_horizontally || unmaximize_vertically); +@@ -2723,17 +2784,6 @@ meta_window_unmaximize (MetaWindow *window, + */ + 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, +@@ -2745,6 +2795,19 @@ meta_window_unmaximize (MetaWindow *window, + */ + force_save_user_window_placement (window); + ++ /* 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. We have to do ++ * it after the actual operation, as the window may have been moved ++ * by constraints. ++ */ ++ if (meta_grab_op_is_moving (window->display->grab_op) && ++ window->display->grab_window == window) ++ { ++ window->display->grab_anchor_window_pos = window->user_rect; ++ } ++ + if (window->display->grab_wireframe_active) + { + window->display->grab_wireframe_rect = target_rect; +@@ -6898,20 +6961,58 @@ update_move (MetaWindow *window, + 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. ++ /* Originally for detaching maximized windows, but we use this ++ * for the zones at the sides of the monitor where trigger tiling ++ * because it's about the right size + */ + + #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) ++ ++ if (meta_prefs_get_side_by_side_tiling () && ++ meta_window_can_tile (window)) ++ { ++ const MetaXineramaScreenInfo *monitor; ++ MetaRectangle work_area; ++ ++ /* For tiling we are interested in the work area of the monitor where ++ * the pointer is located. ++ * Also see comment in meta_window_get_current_tile_area() ++ */ ++ monitor = meta_screen_get_current_xinerama (window->screen); ++ meta_window_get_work_area_for_xinerama (window, ++ monitor->number, ++ &work_area); ++ ++ if (y >= monitor->rect.y && ++ y < (monitor->rect.y + monitor->rect.height)) ++ { ++ /* check if cursor is near an edge of the work area */ ++ if (x >= monitor->rect.x && x < (work_area.x + shake_threshold)) ++ window->tile_mode = META_TILE_LEFT; ++ else if (x >= work_area.x + work_area.width - shake_threshold && ++ x < (monitor->rect.x + monitor->rect.width)) ++ window->tile_mode = META_TILE_RIGHT; ++ else ++ window->tile_mode = META_TILE_NONE; ++ } ++ } ++ ++ /* shake loose (unmaximize) maximized or tiled window if dragged beyond ++ * the threshold in the Y direction. Tiled windows can also be pulled ++ * loose via X motion. ++ */ ++ ++ if ((META_WINDOW_MAXIMIZED (window) && ABS (dy) >= shake_threshold) || ++ (META_WINDOW_TILED (window) && (MAX (ABS (dx), ABS (dy)) >= shake_threshold))) + { + double prop; + + /* Shake loose */ +- window->shaken_loose = TRUE; ++ window->shaken_loose = META_WINDOW_MAXIMIZED (window); ++ window->tile_mode = META_TILE_NONE; + + /* move the unmaximized window to the cursor */ + prop = +@@ -6995,13 +7096,20 @@ update_move (MetaWindow *window, + } + } + ++ /* Delay showing the tile preview slightly to make it more unlikely to ++ * trigger it unwittingly, e.g. when shaking loose the window or moving ++ * it to another monitor. ++ */ ++ meta_screen_tile_preview_update (window->screen, ++ window->tile_mode != META_TILE_NONE); ++ + 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) ++ /* Don't allow movement in the maximized directions or while tiled */ ++ if (window->maximized_horizontally || META_WINDOW_TILED (window)) + new_x = old.x; + if (window->maximized_vertically) + new_y = old.y; +@@ -7417,7 +7525,9 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, + { + if (meta_grab_op_is_moving (window->display->grab_op)) + { +- if (event->xbutton.root == window->screen->xroot) ++ if (window->tile_mode != META_TILE_NONE) ++ meta_window_tile (window); ++ else if (event->xbutton.root == window->screen->xroot) + update_move (window, event->xbutton.state & ShiftMask, + event->xbutton.x_root, event->xbutton.y_root); + } +@@ -7575,6 +7685,29 @@ meta_window_get_work_area_all_xineramas (MetaWindow *window, + window->desc, area->x, area->y, area->width, area->height); + } + ++void ++meta_window_get_current_tile_area (MetaWindow *window, ++ MetaRectangle *tile_area) ++{ ++ const MetaXineramaScreenInfo *monitor; ++ ++ g_return_if_fail (window->tile_mode != META_TILE_NONE); ++ ++ /* The definition of "current" of meta_window_get_work_area_current_xinerama() ++ * and meta_screen_get_current_xinerama() is slightly different: the former ++ * refers to the monitor which contains the largest part of the window, the ++ * latter to the one where the pointer is located. ++ */ ++ monitor = meta_screen_get_current_xinerama (window->screen); ++ meta_window_get_work_area_for_xinerama (window, monitor->number, tile_area); ++ ++ if (window->tile_mode == META_TILE_LEFT || ++ window->tile_mode == META_TILE_RIGHT) ++ tile_area->width /= 2; ++ ++ if (window->tile_mode == META_TILE_RIGHT) ++ tile_area->x += tile_area->width; ++} + + gboolean + meta_window_same_application (MetaWindow *window, +diff --git a/src/include/core.h b/src/include/core.h +index 66db2f8..14c1c15 100644 +--- a/src/include/core.h ++++ b/src/include/core.h +@@ -116,6 +116,10 @@ void meta_core_user_focus (Display *xdisplay, + Window frame_xwindow, + guint32 timestamp); + ++void meta_core_lower_beneath_focus_window (Display *xdisplay, ++ Window xwindow, ++ guint32 timestamp); ++ + void meta_core_minimize (Display *xdisplay, + Window frame_xwindow); + void meta_core_toggle_maximize (Display *xdisplay, +diff --git a/src/include/prefs.h b/src/include/prefs.h +index 2b7cfe4..4856d58 100644 +--- a/src/include/prefs.h ++++ b/src/include/prefs.h +@@ -63,6 +63,7 @@ typedef enum + META_PREF_COMPOSITING_FAST_ALT_TAB, + META_PREF_RESIZE_WITH_RIGHT_BUTTON, + META_PREF_CENTER_NEW_WINDOWS, ++ META_PREF_SIDE_BY_SIDE_TILING, + META_PREF_FORCE_FULLSCREEN + } MetaPreference; + +@@ -95,6 +96,7 @@ MetaWrapStyle meta_prefs_get_wrap_style (void); + gboolean meta_prefs_get_reduced_resources (void); + gboolean meta_prefs_get_mate_accessibility (void); + gboolean meta_prefs_get_mate_animations (void); ++gboolean meta_prefs_get_side_by_side_tiling (void); + + const char* meta_prefs_get_command (int i); + +diff --git a/src/include/tile-preview.h b/src/include/tile-preview.h +new file mode 100644 +index 0000000..b0ca3b0 +--- a/dev/null ++++ b/src/include/tile-preview.h +@@ -0,0 +1,37 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++ ++/* Meta tile preview */ ++ ++/* ++ * Copyright (C) 2010 Florian Müllner ++ * ++ * 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_TILE_PREVIEW_H ++#define META_TILE_PREVIEW_H ++ ++#include "boxes.h" ++ ++typedef struct _MetaTilePreview MetaTilePreview; ++ ++MetaTilePreview *meta_tile_preview_new (int screen_number, ++ gboolean composited); ++void meta_tile_preview_free (MetaTilePreview *preview); ++void meta_tile_preview_show (MetaTilePreview *preview, ++ MetaRectangle *rect); ++void meta_tile_preview_hide (MetaTilePreview *preview); ++ ++#endif /* META_TILE_PREVIEW_H */ +\ No newline at end of file +diff --git a/src/include/ui.h b/src/include/ui.h +index a886649..2352519 100644 +--- a/src/include/ui.h ++++ b/src/include/ui.h +@@ -205,5 +205,6 @@ MetaUIDirection meta_ui_get_direction (void); + GdkPixbuf *meta_ui_get_pixbuf_from_pixmap (Pixmap pmap); + + #include "tabpopup.h" ++#include "tile-preview.h" + + #endif +diff --git a/src/org.mate.marco.gschema.xml b/src/org.mate.marco.gschema.xml +index 464deb3..23b10de 100644 +--- a/src/org.mate.marco.gschema.xml ++++ b/src/org.mate.marco.gschema.xml +@@ -166,6 +166,11 @@ + Determine if new windows are created on the center of the screen + By default, marco open new windows on the top left of the screen. If this option is enabled, new windows are open on the center of the screen, instead. + ++ ++ false ++ Whether to enable side-by-side tiling ++ If enabled, dropping windows on screen edges maximizes them vertically and resizes them horizontally to cover half of the available area. Drag-dropping to the top maximizes the window. ++ + + + +diff --git a/src/ui/tile-preview.c b/src/ui/tile-preview.c +new file mode 100644 +index 0000000..e782e6a +--- a/dev/null ++++ b/src/ui/tile-preview.c +@@ -0,0 +1,251 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++ ++/* Mutter tile-preview marks the area a window will *ehm* snap to */ ++ ++/* ++ * Copyright (C) 2010 Florian Müllner ++ * ++ * 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 ++ ++#include ++#include ++ ++#include "tile-preview.h" ++#include "core.h" ++ ++#define OUTLINE_WIDTH 5 /* frame width in non-composite case */ ++ ++ ++struct _MetaTilePreview { ++ GtkWidget *preview_window; ++ ++ GdkColor *preview_color; ++ guchar preview_alpha; ++ ++ MetaRectangle tile_rect; ++ ++ gboolean has_alpha: 1; ++}; ++ ++static gboolean ++meta_tile_preview_expose (GtkWidget *widget, ++ GdkEventExpose *event, ++ gpointer user_data) ++{ ++ MetaTilePreview *preview = user_data; ++ GdkWindow *window; ++ cairo_t *cr; ++ ++ window = gtk_widget_get_window (widget); ++ cr = gdk_cairo_create (window); ++ ++ cairo_set_line_width (cr, 1.0); ++ ++ if (preview->has_alpha) ++ { ++ ++ /* Fill the preview area with a transparent color */ ++ cairo_set_source_rgba (cr, ++ (double)preview->preview_color->red / 0xFFFF, ++ (double)preview->preview_color->green / 0xFFFF, ++ (double)preview->preview_color->blue / 0xFFFF, ++ (double)preview->preview_alpha / 0xFF); ++ ++ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); ++ cairo_paint (cr); ++ ++ /* Use the opaque color for the border */ ++ gdk_cairo_set_source_color (cr, preview->preview_color); ++ } ++ else ++ { ++ GtkStyle *style = gtk_widget_get_style (preview->preview_window); ++ ++ gdk_cairo_set_source_color (cr, &style->white); ++ ++ cairo_rectangle (cr, ++ OUTLINE_WIDTH - 0.5, OUTLINE_WIDTH - 0.5, ++ preview->tile_rect.width - 2 * (OUTLINE_WIDTH - 1) - 1, ++ preview->tile_rect.height - 2 * (OUTLINE_WIDTH - 1) - 1); ++ cairo_stroke (cr); ++ } ++ ++ cairo_rectangle (cr, ++ 0.5, 0.5, ++ preview->tile_rect.width - 1, ++ preview->tile_rect.height - 1); ++ cairo_stroke (cr); ++ ++ cairo_destroy (cr); ++ ++ return FALSE; ++} ++ ++static void ++on_preview_window_style_set (GtkWidget *widget, ++ GtkStyle *previous, ++ gpointer user_data) ++{ ++ MetaTilePreview *preview = user_data; ++ GtkStyle *style; ++ ++ style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget), ++ "GtkWindow.GtkIconView", ++ "GtkWindow.GtkIconView", ++ GTK_TYPE_ICON_VIEW); ++ ++ if (style != NULL) ++ g_object_ref (style); ++ else ++ style = gtk_style_new (); ++ ++ gtk_style_get (style, GTK_TYPE_ICON_VIEW, ++ "selection-box-color", &preview->preview_color, ++ "selection-box-alpha", &preview->preview_alpha, ++ NULL); ++ if (!preview->preview_color) ++ { ++ GdkColor selection = style->base[GTK_STATE_SELECTED]; ++ preview->preview_color = gdk_color_copy (&selection); ++ } ++ ++ g_object_unref (style); ++} ++ ++MetaTilePreview * ++meta_tile_preview_new (int screen_number, ++ gboolean composited) ++{ ++ MetaTilePreview *preview; ++ GdkColormap *rgba_colormap; ++ GdkScreen *screen; ++ ++ screen = gdk_display_get_screen (gdk_display_get_default (), screen_number); ++ rgba_colormap = gdk_screen_get_rgba_colormap (screen); ++ ++ preview = g_new (MetaTilePreview, 1); ++ ++ preview->preview_window = gtk_window_new (GTK_WINDOW_POPUP); ++ ++ gtk_window_set_screen (GTK_WINDOW (preview->preview_window), screen); ++ gtk_widget_set_app_paintable (preview->preview_window, TRUE); ++ ++ preview->preview_color = NULL; ++ preview->preview_alpha = 0xFF; ++ ++ preview->tile_rect.x = preview->tile_rect.y = 0; ++ preview->tile_rect.width = preview->tile_rect.height = 0; ++ ++ preview->has_alpha = rgba_colormap && composited; ++ ++ if (preview->has_alpha) ++ { ++ gtk_widget_set_colormap (preview->preview_window, rgba_colormap); ++ ++ g_signal_connect (preview->preview_window, "style-set", ++ G_CALLBACK (on_preview_window_style_set), preview); ++ } ++ ++ gtk_widget_realize (preview->preview_window); ++ gdk_window_set_back_pixmap (gtk_widget_get_window (preview->preview_window), ++ NULL, FALSE); ++ ++ g_signal_connect (preview->preview_window, "expose-event", ++ G_CALLBACK (meta_tile_preview_expose), preview); ++ ++ return preview; ++} ++ ++void ++meta_tile_preview_free (MetaTilePreview *preview) ++{ ++ gtk_widget_destroy (preview->preview_window); ++ ++ if (preview->preview_color) ++ gdk_color_free (preview->preview_color); ++ ++ g_free (preview); ++} ++ ++void ++meta_tile_preview_show (MetaTilePreview *preview, ++ MetaRectangle *tile_rect) ++{ ++ GdkWindow *window; ++ GdkRectangle old_rect; ++ ++ if (gtk_widget_get_visible (preview->preview_window) ++ && preview->tile_rect.x == tile_rect->x ++ && preview->tile_rect.y == tile_rect->y ++ && preview->tile_rect.width == tile_rect->width ++ && preview->tile_rect.height == tile_rect->height) ++ return; /* nothing to do */ ++ ++ gtk_widget_show (preview->preview_window); ++ window = gtk_widget_get_window (preview->preview_window); ++ meta_core_lower_beneath_focus_window (gdk_display, ++ GDK_WINDOW_XWINDOW (window), ++ gtk_get_current_event_time ()); ++ ++ old_rect.x = old_rect.y = 0; ++ old_rect.width = preview->tile_rect.width; ++ old_rect.height = preview->tile_rect.height; ++ ++ gdk_window_invalidate_rect (window, &old_rect, FALSE); ++ ++ preview->tile_rect = *tile_rect; ++ ++ gdk_window_move_resize (window, ++ preview->tile_rect.x, preview->tile_rect.y, ++ preview->tile_rect.width, preview->tile_rect.height); ++ ++ if (!preview->has_alpha) ++ { ++ GdkRectangle outer_rect, inner_rect; ++ GdkRegion *outer_region, *inner_region; ++ GdkColor black; ++ ++ black = gtk_widget_get_style (preview->preview_window)->black; ++ gdk_window_set_background (window, &black); ++ ++ outer_rect.x = outer_rect.y = 0; ++ outer_rect.width = preview->tile_rect.width; ++ outer_rect.height = preview->tile_rect.height; ++ ++ inner_rect.x = OUTLINE_WIDTH; ++ inner_rect.y = OUTLINE_WIDTH; ++ inner_rect.width = outer_rect.width - 2 * OUTLINE_WIDTH; ++ inner_rect.height = outer_rect.height - 2 * OUTLINE_WIDTH; ++ ++ outer_region = gdk_region_rectangle (&outer_rect); ++ inner_region = gdk_region_rectangle (&inner_rect); ++ ++ gdk_region_subtract (outer_region, inner_region); ++ gdk_region_destroy (inner_region); ++ ++ gdk_window_shape_combine_region (window, outer_region, 0, 0); ++ gdk_region_destroy (outer_region); ++ } ++} ++ ++void ++meta_tile_preview_hide (MetaTilePreview *preview) ++{ ++ gtk_widget_hide (preview->preview_window); ++} +\ No newline at end of file +-- +cgit + diff --git a/marco_window-snapping-top-screen.patch b/marco_window-snapping-top-screen.patch new file mode 100644 index 0000000..335dadf --- /dev/null +++ b/marco_window-snapping-top-screen.patch @@ -0,0 +1,46 @@ +diff --git a/src/core/window-private.h b/src/core/window-private.h +index 02c518e..f88f8a4 100644 +--- a/src/core/window-private.h ++++ b/src/core/window-private.h +@@ -86,7 +86,8 @@ typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window, + typedef enum { + META_TILE_NONE, + META_TILE_LEFT, +- META_TILE_RIGHT ++ META_TILE_RIGHT, ++ META_TILE_MAXIMIZE + } MetaTileMode; + + struct _MetaWindow +diff --git a/src/core/window.c b/src/core/window.c +index 7a7f6be..cd54e5b 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -6966,7 +6966,7 @@ static void meta_window_apply_session_info (MetaWindow *window, + * because it's about the right size + */ + +-#define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 6 ++#define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 2 + shake_threshold = meta_ui_get_drag_threshold (window->screen->ui) * + DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR; + +@@ -6995,6 +6995,8 @@ static void meta_window_apply_session_info (MetaWindow *window, + else if (x >= work_area.x + work_area.width - shake_threshold && + x < (monitor->rect.x + monitor->rect.width)) + window->tile_mode = META_TILE_RIGHT; ++ else if ((y >= monitor->rect.y) && (y < work_area.y + shake_threshold)) ++ window->tile_mode = META_TILE_MAXIMIZE; + else + window->tile_mode = META_TILE_NONE; + } +@@ -7527,6 +7529,8 @@ static void meta_window_apply_session_info (MetaWindow *window, + { + if (window->tile_mode != META_TILE_NONE) + meta_window_tile (window); ++ else if (window->tile_mode == META_TILE_MAXIMIZE) ++ meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); + else if (event->xbutton.root == window->screen->xroot) + update_move (window, event->xbutton.state & ShiftMask, + event->xbutton.x_root, event->xbutton.y_root); + diff --git a/mini-window.png b/mini-window.png new file mode 100644 index 0000000..ce66be1 Binary files /dev/null and b/mini-window.png differ diff --git a/sources b/sources index e69de29..ff7dee8 100644 --- a/sources +++ b/sources @@ -0,0 +1 @@ +46d8e5fe3bc2c9cb066d9346aeb4c607 marco-1.7.0.git0403454e.tar.xz diff --git a/stock_delete.png b/stock_delete.png new file mode 100644 index 0000000..429401c Binary files /dev/null and b/stock_delete.png differ diff --git a/stock_maximize.png b/stock_maximize.png new file mode 100644 index 0000000..6f10840 Binary files /dev/null and b/stock_maximize.png differ diff --git a/stock_minimize.png b/stock_minimize.png new file mode 100644 index 0000000..a22e3c4 Binary files /dev/null and b/stock_minimize.png differ diff --git a/window.png b/window.png new file mode 100644 index 0000000..cfbcf38 Binary files /dev/null and b/window.png differ