This commit is contained in:
rhp 2001-06-24 06:47:54 +00:00
parent 1b3a58c951
commit 8025ecea02
7 changed files with 342 additions and 100 deletions

View File

@ -20,6 +20,8 @@ metacity_SOURCES= \
main.h \
menu.c \
menu.h \
place.c \
place.h \
screen.c \
screen.h \
session.c \

View File

@ -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 }
};

95
src/place.c Normal file
View File

@ -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;
}

39
src/place.h Normal file
View File

@ -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

View File

@ -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;
return meta_display_lookup_x_window (stack->screen->display,
g_array_index (stack->windows,
Window,
i));
}
workspace = window->screen->active_workspace;
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);
}

View File

@ -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);
@ -303,6 +306,19 @@ meta_window_new (MetaDisplay *display, Window xwindow,
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)

View File

@ -105,6 +105,9 @@ struct _MetaWindow
*/
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;
guint delete_window : 1;