summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrhp <rhp>2001-06-24 06:47:54 +0000
committerrhp <rhp>2001-06-24 06:47:54 +0000
commit8025ecea02c9723e3a72795e4d5913ccc1e74785 (patch)
tree7733e76ac536dee9d99a3810b68c9cab5e83bd69
parent1b3a58c951f08548d94420c68882b8dacbefda40 (diff)
downloadmetacity-8025ecea02c9723e3a72795e4d5913ccc1e74785.tar.gz
...
-rw-r--r--src/Makefile.am2
-rw-r--r--src/keybindings.c4
-rw-r--r--src/place.c95
-rw-r--r--src/place.h39
-rw-r--r--src/stack.c134
-rw-r--r--src/window.c165
-rw-r--r--src/window.h3
7 files changed, 342 insertions, 100 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2fe9129f..d86915a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,6 +20,8 @@ metacity_SOURCES= \
main.h \
menu.c \
menu.h \
+ place.c \
+ place.h \
screen.c \
screen.h \
session.c \
diff --git a/src/keybindings.c b/src/keybindings.c
index 09c6109b..bdaa563d 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -84,6 +84,10 @@ static MetaKeyBinding screen_bindings[] = {
{ XK_4, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (3), 0 },
{ XK_5, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (4), 0 },
{ XK_6, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (5), 0 },
+ { XK_Tab, Mod1Mask, KeyPress, handle_tab_forward, NULL, 0 },
+ { 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 },
{ None, 0, 0, NULL, NULL, 0 }
};
diff --git a/src/place.c b/src/place.c
new file mode 100644
index 00000000..6f623708
--- /dev/null
+++ b/src/place.c
@@ -0,0 +1,95 @@
+/* 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.
+ */
+
+#include "place.h"
+
+void
+meta_window_place (MetaWindow *window,
+ MetaFrameGeometry *fgeom,
+ int x,
+ int y,
+ int *new_x,
+ int *new_y)
+{
+ /* frame member variables should NEVER be used in here, only
+ * MetaFrameGeometry
+ */
+
+ meta_verbose ("Placing window %s\n", window->desc);
+
+ if (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;
+
+ y += fgeom->top_height;
+
+ meta_verbose ("Centered window %s over transient parent\n",
+ window->desc);
+
+ goto done;
+ }
+ }
+
+ if (window->type == META_WINDOW_DIALOG ||
+ window->type == META_WINDOW_MODAL_DIALOG)
+ {
+ /* Center on screen */
+ int w, h;
+
+ /* I think whole screen will look nicer than workarea */
+ w = WidthOfScreen (window->screen->xscreen);
+ h = HeightOfScreen (window->screen->xscreen);
+
+ x = (w - window->rect.width) / 2;
+ y = (y - window->rect.height) / 2;
+
+ meta_verbose ("Centered window %s on screen\n",
+ window->desc);
+
+ goto done;
+ }
+
+ /* "Origin" placement algorithm */
+ x = 0;
+ y = 0;
+
+ done:
+ *new_x = x;
+ *new_y = y;
+}
diff --git a/src/place.h b/src/place.h
new file mode 100644
index 00000000..6b79ecdc
--- /dev/null
+++ b/src/place.h
@@ -0,0 +1,39 @@
+/* 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.h"
+#include "frame.h"
+
+void meta_window_place (MetaWindow *window,
+ MetaFrameGeometry *fgeom,
+ int x,
+ int y,
+ int *new_x,
+ int *new_y);
+
+#endif
+
+
+
+
diff --git a/src/stack.c b/src/stack.c
index 632e7fcc..482a1e8a 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -23,6 +23,7 @@
#include "window.h"
#include "errors.h"
#include "frame.h"
+#include "workspace.h"
#include <X11/Xatom.h>
@@ -761,6 +762,101 @@ meta_stack_get_below (MetaStack *stack,
return find_prev_below_layer (stack, window->layer);
}
+#define IN_TAB_CHAIN(w) ((w)->layer != META_LAYER_DOCK && (w)->layer != META_LAYER_DESKTOP)
+#define GET_XWINDOW(stack, i) (g_array_index ((stack)->windows, \
+ Window, (i)))
+
+static MetaWindow*
+find_tab_forward (MetaStack *stack,
+ MetaWorkspace *workspace,
+ int start)
+{
+ int i;
+
+ /* start may be -1 to find any tab window at all */
+
+ i = start + 1;
+ while (i < stack->windows->len)
+ {
+ MetaWindow *window;
+
+ window = meta_display_lookup_x_window (stack->screen->display,
+ GET_XWINDOW (stack, i));
+
+ if (window && IN_TAB_CHAIN (window) &&
+ (workspace == NULL ||
+ meta_workspace_contains_window (workspace, window)))
+ return window;
+
+ ++i;
+ }
+
+ i = 0;
+ while (i < start)
+ {
+ MetaWindow *window;
+
+ window = meta_display_lookup_x_window (stack->screen->display,
+ GET_XWINDOW (stack, i));
+
+ if (window && IN_TAB_CHAIN (window) &&
+ (workspace == NULL ||
+ meta_workspace_contains_window (workspace, window)))
+ return window;
+
+ ++i;
+ }
+
+ /* no window other than the start window is in the tab chain */
+ return NULL;
+}
+
+static MetaWindow*
+find_tab_backward (MetaStack *stack,
+ MetaWorkspace *workspace,
+ int start)
+{
+ int i;
+
+ /* start may be stack->windows->len to find any tab window at all */
+
+ i = start - 1;
+ while (i >= 0)
+ {
+ MetaWindow *window;
+
+ window = meta_display_lookup_x_window (stack->screen->display,
+ GET_XWINDOW (stack, i));
+
+ if (window && IN_TAB_CHAIN (window) &&
+ (workspace == NULL ||
+ meta_workspace_contains_window (workspace, window)))
+ return window;
+
+ --i;
+ }
+
+ i = stack->windows->len - 1;
+ while (i > start)
+ {
+ MetaWindow *window;
+
+ window = meta_display_lookup_x_window (stack->screen->display,
+ GET_XWINDOW (stack, i));
+
+ if (window && IN_TAB_CHAIN (window) &&
+ (workspace == NULL ||
+ meta_workspace_contains_window (workspace, window)))
+ return window;
+
+ --i;
+ }
+
+ /* no window other than the start window is in the tab chain */
+ return NULL;
+}
+
+/* This ignores the dock/desktop layers */
MetaWindow*
meta_stack_get_tab_next (MetaStack *stack,
MetaWindow *window,
@@ -782,41 +878,27 @@ meta_stack_get_tab_next (MetaStack *stack,
if (w == window->xwindow)
{
- if (backward && i == 0)
- goto out;
- else if (!backward && i == (stack->windows->len - 1))
- goto out;
- else
- {
- if (backward)
- --i;
- else
- ++i;
+ MetaWorkspace *workspace;
+
+ workspace = window->screen->active_workspace;
- return meta_display_lookup_x_window (stack->screen->display,
- g_array_index (stack->windows,
- Window,
- i));
- }
+ if (backward)
+ return find_tab_backward (stack, workspace, i);
+ else
+ return find_tab_forward (stack, workspace, i);
}
++i;
- }
+ }
}
-
- out:
/* window may be NULL, or maybe the origin window was already the last/first
* window and we need to wrap around
*/
if (backward)
- return meta_display_lookup_x_window (stack->screen->display,
- g_array_index (stack->windows,
- Window,
- stack->windows->len - 1));
+ return find_tab_backward (stack, NULL,
+ stack->windows->len);
else
- return meta_display_lookup_x_window (stack->screen->display,
- g_array_index (stack->windows,
- Window,
- 0));
+ return find_tab_forward (stack, NULL, -1);
}
+
diff --git a/src/window.c b/src/window.c
index b243f0bd..8d706305 100644
--- a/src/window.c
+++ b/src/window.c
@@ -27,6 +27,7 @@
#include "stack.h"
#include "keybindings.h"
#include "ui.h"
+#include "place.h"
#include <X11/Xatom.h>
@@ -97,6 +98,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
XWindowAttributes attrs;
GSList *tmp;
MetaWorkspace *space;
+ gulong existing_wm_state;
meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
@@ -123,6 +125,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
return NULL;
}
+ existing_wm_state = WithdrawnState;
if (must_be_viewable && attrs.map_state != IsViewable)
{
/* Only manage if WM_STATE is IconicState or NormalState */
@@ -138,7 +141,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
return NULL;
}
- /* FIXME should honor WM_STATE probably */
+ existing_wm_state = state;
}
meta_error_trap_push (display);
@@ -237,6 +240,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
window->keys_grabbed = FALSE;
window->grab_on_frame = FALSE;
window->withdrawn = FALSE;
+ window->initial_workspace_set = FALSE;
window->unmaps_pending = 0;
@@ -277,8 +281,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
window->layer = META_LAYER_NORMAL;
window->stack_op = NULL;
- window->initial_workspace =
- meta_workspace_screen_index (window->screen->active_workspace);
+ window->initial_workspace = 0; /* not used */
meta_display_register_x_window (display, &window->xwindow, window);
update_size_hints (window);
@@ -302,6 +305,19 @@ meta_window_new (MetaDisplay *display, Window xwindow,
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;
+ }
/* FIXME we have a tendency to set this then immediately
* change it again.
@@ -314,14 +330,54 @@ meta_window_new (MetaDisplay *display, Window xwindow,
meta_window_grab_keys (window);
- space =
- meta_display_get_workspace_by_screen_index (window->display,
- window->screen,
- window->initial_workspace);
- if (space == NULL)
- space = window->screen->active_workspace;
+ /* For the workspace, first honor hints,
+ * if that fails put transients with parents,
+ * otherwise put window on active space
+ */
- meta_workspace_add_window (space, window);
+ if (window->initial_workspace_set)
+ {
+ space =
+ meta_display_get_workspace_by_screen_index (window->display,
+ window->screen,
+ window->initial_workspace);
+
+ if (space)
+ meta_workspace_add_window (space, window);
+ }
+
+ if (window->workspaces == 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)
+ {
+ GList *tmp;
+
+ if (parent->on_all_workspaces)
+ window->on_all_workspaces = TRUE;
+
+ tmp = parent->workspaces;
+ while (tmp != NULL)
+ {
+ meta_workspace_add_window (tmp->data, window);
+
+ tmp = tmp->next;
+ }
+ }
+ }
+
+ if (window->workspaces == NULL)
+ {
+ space = window->screen->active_workspace;
+
+ meta_workspace_add_window (space, window);
+ }
/* Only accept USPosition on normal windows because the app is full
* of shit claiming the user set -geometry for a dialog or dock
@@ -334,16 +390,23 @@ meta_window_new (MetaDisplay *display, Window xwindow,
meta_verbose ("Honoring USPosition for %s instead of using placement algorithm\n", window->desc);
}
- if (window->type != META_WINDOW_NORMAL)
+ /* Assume the app knows best how to place these. */
+ if (window->type == META_WINDOW_DESKTOP ||
+ window->type == META_WINDOW_DOCK ||
+ window->type == META_WINDOW_TOOLBAR ||
+ window->type == META_WINDOW_MENU)
{
window->placed = TRUE;
- meta_verbose ("Not placing non-normal-type window\n");
+ meta_verbose ("Not placing non-normal non-dialog window\n");
}
if (window->type == META_WINDOW_DESKTOP ||
window->type == META_WINDOW_DOCK)
{
- /* Change the default */
+ /* Change the default, but don't enforce this if
+ * the user focuses the dock/desktop and unsticks it
+ * using key shortcuts
+ */
window->on_all_workspaces = TRUE;
}
@@ -625,7 +688,10 @@ meta_window_show (MetaWindow *window)
meta_verbose ("Showing window %s, shaded: %d iconic: %d\n",
window->desc, window->shaded, window->iconic);
- /* don't ever do the initial position constraint thing again */
+ /* 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;
/* Shaded means the frame is mapped but the window is not */
@@ -2708,6 +2774,8 @@ update_initial_workspace (MetaWindow *window)
{
gulong val = 0;
+ window->initial_workspace_set = FALSE;
+
/* Fall back to old WM spec hint if net_wm_desktop is missing, this
* is just to be nice when restarting from old Sawfish basically,
* should nuke it eventually
@@ -2716,12 +2784,18 @@ update_initial_workspace (MetaWindow *window)
window->xwindow,
window->display->atom_net_wm_desktop,
&val))
- window->initial_workspace = val;
+ {
+ window->initial_workspace_set = TRUE;
+ window->initial_workspace = val;
+ }
else if (get_cardinal (window->display,
window->xwindow,
window->display->atom_win_workspace,
&val))
- window->initial_workspace = val;
+ {
+ window->initial_workspace_set = TRUE;
+ window->initial_workspace = val;
+ }
return Success;
}
@@ -3048,64 +3122,7 @@ constrain_position (MetaWindow *window,
*/
if (!window->placed)
- {
- gboolean found_transient = FALSE;
-
- meta_verbose ("Placing window %s\n", window->desc);
-
- /* "Origin" placement algorithm */
- x = 0;
- y = 0;
-
- if (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;
-
- y += fgeom->top_height;
-
- found_transient = TRUE;
-
- meta_verbose ("Centered window %s over transient parent\n",
- window->desc);
- }
- }
-
- if (!found_transient &&
- (window->type == META_WINDOW_DIALOG ||
- window->type == META_WINDOW_MODAL_DIALOG))
- {
- /* Center on screen */
- int w, h;
-
- /* I think whole screen will look nicer than workarea */
- w = WidthOfScreen (window->screen->xscreen);
- h = HeightOfScreen (window->screen->xscreen);
-
- x = (w - window->rect.width) / 2;
- y = (y - window->rect.height) / 2;
-
- meta_verbose ("Centered window %s on screen\n",
- window->desc);
- }
- }
+ meta_window_place (window, fgeom, x, y, &x, &y);
if (window->type != META_WINDOW_DESKTOP &&
window->type != META_WINDOW_DOCK)
diff --git a/src/window.h b/src/window.h
index 41df9fe2..42ce9533 100644
--- a/src/window.h
+++ b/src/window.h
@@ -104,6 +104,9 @@ struct _MetaWindow
* 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;
/* These are the two flags from WM_PROTOCOLS */
guint take_focus : 1;