mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
...
This commit is contained in:
parent
1b3a58c951
commit
8025ecea02
@ -20,6 +20,8 @@ metacity_SOURCES= \
|
||||
main.h \
|
||||
menu.c \
|
||||
menu.h \
|
||||
place.c \
|
||||
place.h \
|
||||
screen.c \
|
||||
screen.h \
|
||||
session.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 }
|
||||
};
|
||||
|
||||
|
95
src/place.c
Normal file
95
src/place.c
Normal 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
39
src/place.h
Normal 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
|
||||
|
||||
|
||||
|
||||
|
134
src/stack.c
134
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);
|
||||
}
|
||||
|
||||
|
165
src/window.c
165
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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user