Compare commits

...

2 Commits

Author SHA1 Message Date
Havoc Pennington
0ee26a5168 Add Alt + left/right arrow to move between workspaces.
2001-08-03  Havoc Pennington  <hp@pobox.com>

	* src/keybindings.c: Add Alt + left/right arrow to
	move between workspaces.

	* src/screen.c (set_wm_check_hint): put property pointing back to
	itself on the _WIN_SUPPORTING_WM_CHECK window.
2001-08-03 13:56:39 +00:00
Havoc Pennington
204cf63805 push error trap around configure of withdrawn window, fixes a crash caused
2001-08-03  Havoc Pennington  <hp@pobox.com>

	* src/display.c (event_callback): push error trap around configure
	of withdrawn window, fixes a crash caused by rapidly
	creating/destroying a window.

	* src/window.c (recalc_window_features): don't allow shading
	undecorated windows.

	* src/wm-tester/main.c: add a program to torture window managers.
2001-08-03 04:20:27 +00:00
11 changed files with 374 additions and 52 deletions

View File

@@ -0,0 +1,25 @@
2001-08-03 Havoc Pennington <hp@pobox.com>
* src/keybindings.c: Add Alt + left/right arrow to
move between workspaces.
* src/screen.c (set_wm_check_hint): put property pointing back to
itself on the _WIN_SUPPORTING_WM_CHECK window.
2001-08-03 Havoc Pennington <hp@pobox.com>
* src/display.c (event_callback): push error trap around configure
of withdrawn window, fixes a crash caused by rapidly
creating/destroying a window.
* src/window.c (recalc_window_features): don't allow shading
undecorated windows.
* src/wm-tester/main.c: add a program to torture window managers.
2001-08-01 Havoc Pennington <hp@pobox.com>
* src/window.c (recalc_window_features): if a window isn't
resizeable, turn off maximize function. If min size is equal to
max size, turn off resize function.

35
README
View File

@@ -42,6 +42,8 @@ METACITY FEATURES
Alt-Tab forward cycle window focus
Alt-Shift-Tab backward cycle focus
Alt-Escape focus previous window
Alt-Left Arrow previous workspace
Alt-Right Arrow next workspace
- Window keybindings:
Alt-space window menu
@@ -177,12 +179,6 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS
- There are probably other ICCCM-compliance issues.
- I know there's at least one race condition involving rapidly
created and destroyed windows that will crash Metacity. I think a
small test app that did a lot of rapid show/hide on a GtkWindow,
in combination with the METACITY_SYNC environment variable and
Metacity in a debugger, would turn this up quickly.
- Window placement is always cascade for now; I want to implement
"first fit, falling back to cascade if no fit."
(Configurable placement algorithms are stupid though, don't
@@ -201,15 +197,6 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS
window cycling that I would like to copy. (The little
popup window thing.)
- People seem to like shortcuts using arrow keys for moving
between workspaces. My only question here is that I'm not sure
what the spatial relationship between workspaces is.
(Are they in a grid, or a horizontal row, or what.)
I think we may need a window manager spec extension to
share this information between the WM and the pager.
We could add left/right arrow and pretend they're in
a row for the short term though.
- Should Metacity support flipping in right-to-left locales?
I don't know what window managers look like in a right-to-left
locale. I assume the window titles should be right-justified;
@@ -246,6 +233,24 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS
xstuff.c:xstuff_is_compliant_wm() in the panel to get started on
how the panel deals with this.)
- If you have "put panel below other windows" turned on
in panel Global Preferences, Miscellaneous tab, you need to change
this to "Put panel on top of other windows." That's because
Metacity uses semantic categories, not the legacy layer system
in the GNOME spec. It treats things in the legacy "dock" layer
as semantic type dock, but if you have the panel set to be
in another layer, Metacity will think it's a normal window.
You can diagnose this problem because Metacity will put panels in
the wrong place, and Alt+rightclick will let you perform operations
like minimize/maximize, and Alt+leftclick will let you move the panel.
If Metacity has detected that the panel is a panel, then none of
this will be enabled.
I put a patch in the CVS version of the panel to fix this by
setting the new non-legacy type hint, but a panel with that
patch hasn't been released yet.
FAQ
===

View File

@@ -2,7 +2,7 @@ AC_INIT(src/display.c)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(metacity, 2.3.1)
AM_INIT_AUTOMAKE(metacity, 2.3.2)
GETTEXT_PACKAGE=metacity
AC_SUBST(GETTEXT_PACKAGE)
@@ -71,6 +71,7 @@ AC_SUBST(HOST_ALIAS)
AC_OUTPUT([
Makefile
src/Makefile
src/wm-tester/Makefile
])

View File

@@ -1,4 +1,6 @@
SUBDIRS=wm-tester
INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\"
metacity_SOURCES= \

View File

@@ -825,8 +825,10 @@ event_callback (XEvent *event,
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);
}
else
{
@@ -1285,6 +1287,10 @@ meta_display_get_workspace_by_index (MetaDisplay *display,
int index)
{
GList *tmp;
/* should be robust, index is maybe from an app */
if (index < 0)
return NULL;
tmp = g_list_nth (display->workspaces, index);
@@ -1302,6 +1308,10 @@ meta_display_get_workspace_by_screen_index (MetaDisplay *display,
GList *tmp;
int i;
/* should be robust, index is maybe from an app */
if (index < 0)
return NULL;
i = 0;
tmp = display->workspaces;
while (tmp != NULL)

View File

@@ -57,6 +57,14 @@ static void handle_focus_previous (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
gpointer data);
static void handle_workspace_left (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
gpointer data);
static void handle_workspace_right (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
gpointer data);
typedef struct _MetaKeyBinding MetaKeyBinding;
@@ -89,6 +97,8 @@ static MetaKeyBinding screen_bindings[] = {
{ XK_ISO_Left_Tab, ShiftMask | Mod1Mask, KeyPress, handle_tab_backward, NULL, 0 },
{ XK_Tab, ShiftMask | Mod1Mask, KeyPress, handle_tab_backward, NULL, 0 },
{ XK_Escape, Mod1Mask, KeyPress, handle_focus_previous, NULL, 0 },
{ XK_Left, Mod1Mask, KeyPress, handle_workspace_left, NULL, 0 },
{ XK_Right, Mod1Mask, KeyPress, handle_workspace_right, NULL, 0 },
{ None, 0, 0, NULL, NULL, 0 }
};
@@ -499,6 +509,47 @@ meta_display_process_key_event (MetaDisplay *display,
}
}
static void
switch_to_workspace (MetaDisplay *display,
MetaWorkspace *workspace)
{
MetaWindow *move_window;
move_window = NULL;
if (display->grab_op == META_GRAB_OP_MOVING)
move_window = 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.
*/
if (move_window)
{
if (!meta_workspace_contains_window (workspace,
move_window))
meta_workspace_add_window (workspace, move_window);
}
}
meta_workspace_activate (workspace);
if (move_window)
{
/* Lamely rely on prepend */
g_assert (move_window->workspaces->data == workspace);
while (move_window->workspaces->next) /* while list size > 1 */
meta_workspace_remove_window (move_window->workspaces->next->data,
move_window);
}
}
static void
handle_activate_workspace (MetaDisplay *display,
MetaWindow *event_window,
@@ -514,41 +565,69 @@ handle_activate_workspace (MetaDisplay *display,
if (workspace)
{
MetaWindow *move_window;
switch_to_workspace (display, workspace);
}
else
{
/* We could offer to create it I suppose */
}
}
move_window = NULL;
if (display->grab_op == META_GRAB_OP_MOVING)
move_window = display->grab_window;
if (move_window != NULL)
{
if (move_window->on_all_workspaces)
move_window = NULL; /* don't move it after all */
static void
handle_workspace_left (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
gpointer data)
{
MetaWorkspace *workspace;
MetaScreen *screen;
int i;
screen = meta_display_screen_for_root (display,
event->xkey.root);
/* 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.
*/
if (move_window)
{
if (!meta_workspace_contains_window (workspace,
move_window))
meta_workspace_add_window (workspace, move_window);
}
}
meta_workspace_activate (workspace);
if (screen == NULL)
return;
i = meta_workspace_index (screen->active_workspace);
--i;
if (move_window)
{
/* Lamely rely on prepend */
g_assert (move_window->workspaces->data == workspace);
while (move_window->workspaces->next) /* while list size > 1 */
meta_workspace_remove_window (move_window->workspaces->next->data,
move_window);
}
workspace = meta_display_get_workspace_by_index (display, i);
if (workspace)
{
switch_to_workspace (display, workspace);
}
else
{
/* We could offer to create it I suppose */
}
}
static void
handle_workspace_right (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
gpointer data)
{
MetaWorkspace *workspace;
MetaScreen *screen;
int i;
screen = meta_display_screen_for_root (display,
event->xkey.root);
if (screen == NULL)
return;
i = meta_workspace_index (screen->active_workspace);
++i;
workspace = meta_display_get_workspace_by_index (display, i);
if (workspace)
{
switch_to_workspace (display, workspace);
}
else
{

View File

@@ -18,10 +18,18 @@ 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 -z "$ONLY_WM"; then
Xnest -ac :1 -scrns $SCREENS -geometry 640x480 -bw 15 &
usleep 500000
if test -n "$TEST_CLIENT"; then
DISPLAY=:1 $TEST_CLIENT &
fi
if test $CLIENTS != 0; then
for I in `seq 1 $CLIENTS`; do
DISPLAY=:1 xterm -geometry 25x15 &
@@ -40,5 +48,5 @@ if test -z "$ONLY_WM"; then
fi
if test -z "$ONLY_SETUP"; then
METACITY_DISPLAY=:1 exec unst libtool --mode=execute $DEBUG ./metacity $OPTIONS
METACITY_DEBUG_BUTTON_GRABS=1 METACITY_DISPLAY=:1 exec unst libtool --mode=execute $DEBUG ./metacity $OPTIONS
fi

View File

@@ -50,12 +50,22 @@ set_wm_check_hint (MetaScreen *screen)
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
/* Legacy GNOME hint */
XChangeProperty (screen->display->xdisplay, screen->xroot,
/* Legacy GNOME hint (uses cardinal, dunno why) */
/* legacy hint window should have property containing self */
XChangeProperty (screen->display->xdisplay, screen->display->leader_window,
screen->display->atom_win_supporting_wm_check,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
/* do this after setting up window fully, to avoid races
* with clients listening to property notify on root.
*/
XChangeProperty (screen->display->xdisplay, screen->xroot,
screen->display->atom_win_supporting_wm_check,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
return Success;
}

View File

@@ -2491,6 +2491,8 @@ update_size_hints (MetaWindow *window)
window->size_hints.flags |= PWinGravity;
}
recalc_window_features (window);
return meta_error_trap_pop (window->display);
}
@@ -2552,7 +2554,7 @@ update_title (MetaWindow *window)
&err);
if (err != NULL)
{
meta_warning ("WM_NAME property for %s contained stuff we are too dumb to figure out: %s\n", window->desc, err->message);
meta_warning ("WM_NAME property for %s contained stuff window manager is too dumb to figure out: %s\n", window->desc, err->message);
g_error_free (err);
}
@@ -3441,6 +3443,19 @@ recalc_window_features (MetaWindow *window)
window->has_maximize_func = FALSE;
}
/* 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;
/* don't allow maximize if we can't resize */
if (!window->has_resize_func)
window->has_maximize_func = FALSE;
/* no shading if not decorated */
if (!window->decorated)
window->has_shade_func = FALSE;
/* FIXME perhaps should ensure if we don't have a shade func,
* we aren't shaded, etc.
*/

View File

@@ -0,0 +1,9 @@
INCLUDES=@METACITY_CFLAGS@
wm_tester_SOURCES= \
main.c
bin_PROGRAMS=wm-tester
wm_tester_LDADD= @METACITY_LIBS@

158
src/wm-tester/main.c Normal file
View File

@@ -0,0 +1,158 @@
/* 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
usage (void)
{
g_print ("wm-tester [--evil]\n");
exit (0);
}
int
main (int argc, char **argv)
{
int i;
gboolean do_evil;
gtk_init (&argc, &argv);
do_evil = 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
usage ();
++i;
}
/* Be sure some option was provided */
if (! (do_evil))
return 1;
if (do_evil)
set_up_the_evil ();
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;
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
c = gtk_button_new_with_label ("Evil Window!");
gtk_container_add (GTK_CONTAINER (w), c);
gtk_widget_set_uposition (w,
g_random_int_range (0,
gdk_screen_width ()),
g_random_int_range (0,
gdk_screen_height ()));
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 (40, evil_timeout, NULL);
}