Apply big patch from blackc@speakeasy.net adding a popup window to the

2002-06-08  Havoc Pennington  <hp@pobox.com>

	Apply big patch from blackc@speakeasy.net adding a popup window
	to the Ctrl+Alt+arrows shortcuts. #83940

2002-06-08  Havoc Pennington  <hp@pobox.com>

	* src/screen.c (meta_screen_new): select key press/release on the
	display->no_focus_window, another attempted fix for not getting
	keybindings when no window is focused. Still doesn't seem to work
	though. I don't get what's going wrong.
	(meta_create_offscreen_window): new function, used instead of
	XCreateSimpleWindow so we get override redirect offscreen windows.
This commit is contained in:
Havoc Pennington 2002-06-09 03:44:16 +00:00 committed by Havoc Pennington
parent 459d8f9c9d
commit fb5a3a8998
13 changed files with 568 additions and 136 deletions

View File

@ -1,3 +1,17 @@
2002-06-08 Havoc Pennington <hp@pobox.com>
Apply big patch from blackc@speakeasy.net adding a popup window
to the Ctrl+Alt+arrows shortcuts. #83940
2002-06-08 Havoc Pennington <hp@pobox.com>
* src/screen.c (meta_screen_new): select key press/release on the
display->no_focus_window, another attempted fix for not getting
keybindings when no window is focused. Still doesn't seem to work
though. I don't get what's going wrong.
(meta_create_offscreen_window): new function, used instead of
XCreateSimpleWindow so we get override redirect offscreen windows.
2002-06-08 Havoc Pennington <hp@pobox.com> 2002-06-08 Havoc Pennington <hp@pobox.com>
* src/display.c (meta_display_open): set net_supporting_wm_check * src/display.c (meta_display_open): set net_supporting_wm_check

View File

@ -101,6 +101,11 @@ typedef enum
META_GRAB_OP_KEYBOARD_TABBING_NORMAL, META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
META_GRAB_OP_KEYBOARD_TABBING_DOCK, META_GRAB_OP_KEYBOARD_TABBING_DOCK,
META_GRAB_OP_KEYBOARD_WORKSPACE_UP,
META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN,
META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT,
META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT,
/* Frame button ops */ /* Frame button ops */
META_GRAB_OP_CLICKING_MINIMIZE, META_GRAB_OP_CLICKING_MINIMIZE,

View File

@ -766,6 +766,10 @@ grab_op_is_keyboard (MetaGrabOp op)
case META_GRAB_OP_KEYBOARD_RESIZING_NW: case META_GRAB_OP_KEYBOARD_RESIZING_NW:
case META_GRAB_OP_KEYBOARD_TABBING_NORMAL: case META_GRAB_OP_KEYBOARD_TABBING_NORMAL:
case META_GRAB_OP_KEYBOARD_TABBING_DOCK: case META_GRAB_OP_KEYBOARD_TABBING_DOCK:
case META_GRAB_OP_KEYBOARD_WORKSPACE_UP:
case META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN:
case META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT:
case META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT:
return TRUE; return TRUE;
break; break;
@ -2251,6 +2255,13 @@ meta_display_begin_grab_op (MetaDisplay *display,
META_TAB_LIST_DOCKS); META_TAB_LIST_DOCKS);
break; break;
case META_GRAB_OP_KEYBOARD_WORKSPACE_UP:
case META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN:
case META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT:
case META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT:
meta_workspace_ensure_tab_popup (display, window->screen);
break;
default: default:
break; break;
} }
@ -2268,7 +2279,11 @@ meta_display_end_grab_op (MetaDisplay *display,
return; return;
if (display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || if (display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_NORMAL ||
display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_DOCK) display->grab_op == META_GRAB_OP_KEYBOARD_TABBING_DOCK ||
display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT ||
display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT ||
display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_UP ||
display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN)
{ {
meta_ui_tab_popup_free (display->grab_window->screen->tab_popup); meta_ui_tab_popup_free (display->grab_window->screen->tab_popup);
display->grab_window->screen->tab_popup = NULL; display->grab_window->screen->tab_popup = NULL;

View File

@ -94,6 +94,10 @@ static void handle_move_to_workspace (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
XEvent *event, XEvent *event,
MetaKeyBinding *binding); MetaKeyBinding *binding);
static void handle_workspace_forward (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding);
static void handle_raise_or_lower (MetaDisplay *display, static void handle_raise_or_lower (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
XEvent *event, XEvent *event,
@ -115,6 +119,11 @@ static gboolean process_tab_grab (MetaDisplay *display,
XEvent *event, XEvent *event,
KeySym keysym); KeySym keysym);
static gboolean process_workspace_tab_grab (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
KeySym keysym);
static void regrab_screen_bindings (MetaDisplay *display); static void regrab_screen_bindings (MetaDisplay *display);
static void regrab_window_bindings (MetaDisplay *display); static void regrab_window_bindings (MetaDisplay *display);
@ -159,13 +168,13 @@ static const MetaKeyHandler screen_handlers[] = {
GINT_TO_POINTER (10) }, GINT_TO_POINTER (10) },
{ META_KEYBINDING_WORKSPACE_12, handle_activate_workspace, { META_KEYBINDING_WORKSPACE_12, handle_activate_workspace,
GINT_TO_POINTER (11) }, GINT_TO_POINTER (11) },
{ META_KEYBINDING_WORKSPACE_LEFT, handle_activate_workspace, { META_KEYBINDING_WORKSPACE_LEFT, handle_workspace_forward,
GINT_TO_POINTER (META_MOTION_LEFT) }, GINT_TO_POINTER (META_MOTION_LEFT) },
{ META_KEYBINDING_WORKSPACE_RIGHT, handle_activate_workspace, { META_KEYBINDING_WORKSPACE_RIGHT, handle_workspace_forward,
GINT_TO_POINTER (META_MOTION_RIGHT) }, GINT_TO_POINTER (META_MOTION_RIGHT) },
{ META_KEYBINDING_WORKSPACE_UP, handle_activate_workspace, { META_KEYBINDING_WORKSPACE_UP, handle_workspace_forward,
GINT_TO_POINTER (META_MOTION_UP) }, GINT_TO_POINTER (META_MOTION_UP) },
{ META_KEYBINDING_WORKSPACE_DOWN, handle_activate_workspace, { META_KEYBINDING_WORKSPACE_DOWN, handle_workspace_forward,
GINT_TO_POINTER (META_MOTION_DOWN) }, GINT_TO_POINTER (META_MOTION_DOWN) },
{ META_KEYBINDING_SWITCH_WINDOWS, handle_tab_forward, { META_KEYBINDING_SWITCH_WINDOWS, handle_tab_forward,
GINT_TO_POINTER (META_TAB_LIST_NORMAL) }, GINT_TO_POINTER (META_TAB_LIST_NORMAL) },
@ -593,10 +602,10 @@ meta_change_keygrab (MetaDisplay *display,
*/ */
meta_topic (META_DEBUG_KEYBINDINGS, meta_topic (META_DEBUG_KEYBINDINGS,
"%s keybinding %s mask 0x%x\n", "%s keybinding %s mask 0x%x on 0x%lx\n",
grab ? "Grabbing" : "Ungrabbing", grab ? "Grabbing" : "Ungrabbing",
keysym_name (keysym), keysym_name (keysym),
modmask); modmask, xwindow);
ignored_mask = 0; ignored_mask = 0;
while (ignored_mask < (int) display->ignored_modifier_mask) while (ignored_mask < (int) display->ignored_modifier_mask)
@ -1062,7 +1071,7 @@ meta_display_process_key_event (MetaDisplay *display,
return; return;
} }
if (display->grab_op == META_GRAB_OP_NONE) if (display->grab_op == META_GRAB_OP_NONE)
return; return;
@ -1088,6 +1097,15 @@ meta_display_process_key_event (MetaDisplay *display,
"Processing event for keyboard tabbing\n"); "Processing event for keyboard tabbing\n");
handled = process_tab_grab (display, window, event, keysym); handled = process_tab_grab (display, window, event, keysym);
break; break;
case META_GRAB_OP_KEYBOARD_WORKSPACE_UP:
case META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN:
case META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT:
case META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT:
meta_topic (META_DEBUG_KEYBINDINGS,
"Processing event for keyboard tabbing workspace\n");
handled = process_workspace_tab_grab (display, window, event, keysym);
break;
default: default:
break; break;
} }
@ -1213,6 +1231,7 @@ process_tab_grab (MetaDisplay *display,
KeySym keysym) KeySym keysym)
{ {
MetaScreen *screen; MetaScreen *screen;
MetaKeyBindingAction action;
window = NULL; /* be sure we don't use this, it's irrelevant */ window = NULL; /* be sure we don't use this, it's irrelevant */
@ -1229,7 +1248,7 @@ process_tab_grab (MetaDisplay *display,
MetaWindow *target_window; MetaWindow *target_window;
target_xwindow = target_xwindow =
meta_ui_tab_popup_get_selected (screen->tab_popup); (Window) meta_ui_tab_popup_get_selected (screen->tab_popup);
target_window = target_window =
meta_display_lookup_x_window (display, target_xwindow); meta_display_lookup_x_window (display, target_xwindow);
@ -1263,10 +1282,12 @@ process_tab_grab (MetaDisplay *display,
if (is_modifier (display, event->xkey.keycode)) if (is_modifier (display, event->xkey.keycode))
return TRUE; return TRUE;
switch (keysym) action = meta_prefs_get_keybinding_action(keysym);
switch (action)
{ {
case XK_ISO_Left_Tab: case META_KEYBINDING_ACTION_SWITCH_PANELS:
case XK_Tab: case META_KEYBINDING_ACTION_SWITCH_WINDOWS:
if (event->xkey.state & ShiftMask) if (event->xkey.state & ShiftMask)
meta_ui_tab_popup_backward (screen->tab_popup); meta_ui_tab_popup_backward (screen->tab_popup);
else else
@ -1339,7 +1360,7 @@ handle_activate_workspace (MetaDisplay *display,
MetaWorkspace *workspace; MetaWorkspace *workspace;
which = GPOINTER_TO_INT (binding->handler->data); which = GPOINTER_TO_INT (binding->handler->data);
workspace = NULL; workspace = NULL;
if (which < 0) if (which < 0)
{ {
@ -1369,6 +1390,112 @@ handle_activate_workspace (MetaDisplay *display,
} }
} }
static gboolean
process_workspace_tab_grab (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
KeySym keysym)
{
MetaScreen *screen;
MetaWorkspace *workspace;
window = NULL; /* be sure we don't use this, it's irrelevant */
screen = display->grab_window->screen;
g_return_val_if_fail (screen->tab_popup != NULL, FALSE);
if (event->type == KeyRelease &&
keycode_is_primary_modifier (display, event->xkey.keycode,
display->grab_mask))
{
/* We're done, move to the new workspace. */
MetaWorkspace *target_workspace;
target_workspace =
(MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->tab_popup);
meta_topic (META_DEBUG_KEYBINDINGS,
"Ending workspace tab operation, primary modifier released\n");
if (target_workspace)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Ending grab early so we can focus the target workspace\n");
meta_display_end_grab_op (display, event->xkey.time);
meta_topic (META_DEBUG_KEYBINDINGS,
"Activating target workspace\n");
switch_to_workspace (display, target_workspace);
return TRUE; /* we already ended the grab */
}
return FALSE; /* end grab */
}
/* don't care about other releases, but eat them, don't end grab */
if (event->type == KeyRelease)
return TRUE;
/* don't end grab on modifier key presses */
if (is_modifier (display, event->xkey.keycode))
return TRUE;
/* select the next workspace in the tabpopup */
workspace =
(MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->tab_popup);
if (workspace)
{
MetaWorkspace *target_workspace;
MetaKeyBindingAction action;
action = meta_prefs_get_keybinding_action(keysym);
switch (action)
{
case META_KEYBINDING_ACTION_WORKSPACE_UP:
target_workspace = meta_workspace_get_neighbor (workspace,
META_MOTION_UP);
break;
case META_KEYBINDING_ACTION_WORKSPACE_DOWN:
target_workspace = meta_workspace_get_neighbor (workspace,
META_MOTION_DOWN);
break;
case META_KEYBINDING_ACTION_WORKSPACE_LEFT:
target_workspace = meta_workspace_get_neighbor (workspace,
META_MOTION_LEFT);
break;
case META_KEYBINDING_ACTION_WORKSPACE_RIGHT:
target_workspace = meta_workspace_get_neighbor (workspace,
META_MOTION_RIGHT);
break;
default:
target_workspace = NULL;
break;
}
if (target_workspace)
{
meta_ui_tab_popup_select (screen->tab_popup,
(MetaTabEntryKey) target_workspace);
meta_topic (META_DEBUG_KEYBINDINGS,
"Tab key pressed, moving tab focus in popup\n");
return TRUE;
}
}
/* end grab */
meta_topic (META_DEBUG_KEYBINDINGS,
"Ending workspace tabbing, uninteresting key pressed\n");
return FALSE;
}
static void static void
handle_toggle_desktop (MetaDisplay *display, handle_toggle_desktop (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,
@ -1484,7 +1611,7 @@ handle_tab_forward (MetaDisplay *display,
0, 0)) 0, 0))
{ {
meta_ui_tab_popup_select (window->screen->tab_popup, meta_ui_tab_popup_select (window->screen->tab_popup,
window->xwindow); (MetaTabEntryKey) window->xwindow);
/* only after selecting proper window */ /* only after selecting proper window */
meta_ui_tab_popup_set_showing (window->screen->tab_popup, meta_ui_tab_popup_set_showing (window->screen->tab_popup,
TRUE); TRUE);
@ -1492,6 +1619,49 @@ handle_tab_forward (MetaDisplay *display,
} }
} }
static MetaWindow *
get_previous_focus_window (MetaDisplay *display,
MetaScreen *screen)
{
MetaWindow *window = NULL;
/* get previously-focused window, front of list is currently
* focused window
*/
if (display->mru_list &&
display->mru_list->next)
{
window = display->mru_list->next->data;
}
if (window &&
!meta_window_visible_on_workspace (window,
screen->active_workspace))
{
window = NULL;
}
if (window == NULL)
{
/* Pick first window in tab order */
window = meta_display_get_tab_next (screen->display,
META_TAB_LIST_NORMAL,
screen,
screen->active_workspace,
NULL,
TRUE);
}
if (window &&
!meta_window_visible_on_workspace (window,
screen->active_workspace))
{
window = NULL;
}
return window;
}
static void static void
handle_focus_previous (MetaDisplay *display, handle_focus_previous (MetaDisplay *display,
MetaWindow *event_window, MetaWindow *event_window,
@ -1510,36 +1680,8 @@ handle_focus_previous (MetaDisplay *display,
if (screen == NULL) if (screen == NULL)
return; return;
window = NULL; window = get_previous_focus_window (display, screen);
/* get previously-focused window, front of list is currently
* focused window
*/
if (display->mru_list &&
display->mru_list->next)
window = display->mru_list->next->data;
if (window &&
!meta_window_visible_on_workspace (window,
screen->active_workspace))
window = NULL;
if (window == NULL)
{
/* Pick first window in tab order */
window = meta_display_get_tab_next (screen->display,
META_TAB_LIST_NORMAL,
screen,
screen->active_workspace,
NULL,
TRUE);
}
if (window &&
!meta_window_visible_on_workspace (window,
screen->active_workspace))
window = NULL;
if (window) if (window)
{ {
meta_window_raise (window); meta_window_raise (window);
@ -1753,6 +1895,83 @@ handle_raise_or_lower (MetaDisplay *display,
} }
} }
static MetaGrabOp
op_from_motion_direction (MetaMotionDirection motion)
{
switch (motion)
{
case META_MOTION_UP:
return META_GRAB_OP_KEYBOARD_WORKSPACE_UP;
case META_MOTION_DOWN:
return META_GRAB_OP_KEYBOARD_WORKSPACE_DOWN;
case META_MOTION_LEFT:
return META_GRAB_OP_KEYBOARD_WORKSPACE_LEFT;
case META_MOTION_RIGHT:
return META_GRAB_OP_KEYBOARD_WORKSPACE_RIGHT;
}
g_assert_not_reached ();
return 0;
}
static void
handle_workspace_forward (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding)
{
int motion;
MetaScreen *screen;
motion = GPOINTER_TO_INT (binding->handler->data);
g_assert (motion < 0);
screen = meta_display_screen_for_root (display,
event->xkey.root);
if (screen == NULL)
return;
if (display->focus_window != NULL)
{
window = display->focus_window;
}
else if (window == NULL)
{
window = get_previous_focus_window (display, screen);
}
if (window)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Starting tab between workspaces, showing popup\n");
if (meta_display_begin_grab_op (display,
window,
op_from_motion_direction (motion),
FALSE,
0,
event->xkey.state & ~(display->ignored_modifier_mask),
event->xkey.time,
0, 0))
{
MetaWorkspace *next;
next = meta_workspace_get_neighbor(window->screen->active_workspace,
motion);
g_assert (next);
meta_ui_tab_popup_select (window->screen->tab_popup,
(MetaTabEntryKey) next);
/* only after selecting proper window */
meta_ui_tab_popup_set_showing (window->screen->tab_popup,
TRUE);
}
}
}
static void static void
handle_spew_mark (MetaDisplay *display, handle_spew_mark (MetaDisplay *display,
MetaWindow *window, MetaWindow *window,

View File

@ -1031,3 +1031,19 @@ meta_prefs_get_auto_raise_delay ()
{ {
return auto_raise_delay; return auto_raise_delay;
} }
MetaKeyBindingAction
meta_prefs_get_keybinding_action (unsigned int keysym)
{
int i;
for (i = (int) G_N_ELEMENTS (screen_bindings) - 1; i >= 0; --i)
{
if (screen_bindings[i].keysym == keysym)
{
return (MetaKeyBindingAction) i;
}
}
return META_KEYBINDING_ACTION_NONE;
}

View File

@ -113,6 +113,31 @@ void meta_prefs_set_num_workspaces (int n_workspaces);
#define META_KEYBINDING_MOVE_WORKSPACE_DOWN "move_to_workspace_down" #define META_KEYBINDING_MOVE_WORKSPACE_DOWN "move_to_workspace_down"
#define META_KEYBINDING_RAISE_OR_LOWER "raise_or_lower" #define META_KEYBINDING_RAISE_OR_LOWER "raise_or_lower"
typedef enum _MetaKeyBindingAction
{
META_KEYBINDING_ACTION_NONE = -1,
META_KEYBINDING_ACTION_WORKSPACE_1,
META_KEYBINDING_ACTION_WORKSPACE_2,
META_KEYBINDING_ACTION_WORKSPACE_3,
META_KEYBINDING_ACTION_WORKSPACE_4,
META_KEYBINDING_ACTION_WORKSPACE_5,
META_KEYBINDING_ACTION_WORKSPACE_6,
META_KEYBINDING_ACTION_WORKSPACE_7,
META_KEYBINDING_ACTION_WORKSPACE_8,
META_KEYBINDING_ACTION_WORKSPACE_9,
META_KEYBINDING_ACTION_WORKSPACE_10,
META_KEYBINDING_ACTION_WORKSPACE_11,
META_KEYBINDING_ACTION_WORKSPACE_12,
META_KEYBINDING_ACTION_WORKSPACE_LEFT,
META_KEYBINDING_ACTION_WORKSPACE_RIGHT,
META_KEYBINDING_ACTION_WORKSPACE_UP,
META_KEYBINDING_ACTION_WORKSPACE_DOWN,
META_KEYBINDING_ACTION_SWITCH_WINDOWS,
META_KEYBINDING_ACTION_SWITCH_PANELS,
META_KEYBINDING_ACTION_FOCUS_PREVIOUS,
META_KEYBINDING_ACTION_SHOW_DESKTOP
} MetaKeyBindingAction;
typedef struct typedef struct
{ {
const char *name; const char *name;
@ -124,6 +149,7 @@ void meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
int *n_bindings); int *n_bindings);
void meta_prefs_get_window_bindings (const MetaKeyPref **bindings, void meta_prefs_get_window_bindings (const MetaKeyPref **bindings,
int *n_bindings); int *n_bindings);
MetaKeyBindingAction meta_prefs_get_keybinding_action (unsigned int keysym);
#endif #endif

View File

@ -223,8 +223,7 @@ meta_screen_new (MetaDisplay *display,
current_wm_sn_owner = None; /* don't wait for it to die later on */ current_wm_sn_owner = None; /* don't wait for it to die later on */
} }
new_wm_sn_owner = XCreateSimpleWindow (xdisplay, xroot, new_wm_sn_owner = meta_create_offscreen_window (xdisplay, xroot);
-100, -100, 1, 1, 0, 0, 0);
{ {
/* Generate a timestamp */ /* Generate a timestamp */
@ -441,17 +440,16 @@ meta_screen_new (MetaDisplay *display,
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT); meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
if (display->leader_window == None) if (display->leader_window == None)
display->leader_window = XCreateSimpleWindow (display->xdisplay, display->leader_window = meta_create_offscreen_window (display->xdisplay,
screen->xroot, screen->xroot);
-100, -100, 1, 1, 0, 0, 0);
if (display->no_focus_window == None) if (display->no_focus_window == None)
{ {
display->no_focus_window = XCreateSimpleWindow (display->xdisplay, display->no_focus_window = meta_create_offscreen_window (display->xdisplay,
screen->xroot, screen->xroot);
-100, -100, 1, 1, 0, 0, 0);
XSelectInput (display->xdisplay, display->no_focus_window, XSelectInput (display->xdisplay, display->no_focus_window,
FocusChangeMask); FocusChangeMask | KeyPressMask | KeyReleaseMask);
XMapWindow (display->xdisplay, display->no_focus_window); XMapWindow (display->xdisplay, display->no_focus_window);
} }
@ -857,7 +855,7 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
len = g_slist_length (tab_list); len = g_slist_length (tab_list);
entries = g_new (MetaTabEntry, len + 1); entries = g_new (MetaTabEntry, len + 1);
entries[len].xwindow = None; entries[len].key = NULL;
entries[len].title = NULL; entries[len].title = NULL;
entries[len].icon = NULL; entries[len].icon = NULL;
@ -870,7 +868,7 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
window = tmp->data; window = tmp->data;
entries[i].xwindow = window->xwindow; entries[i].key = (MetaTabEntryKey) window->xwindow;
entries[i].title = window->title; entries[i].title = window->title;
entries[i].icon = window->icon; entries[i].icon = window->icon;
meta_window_get_outer_rect (window, &r); meta_window_get_outer_rect (window, &r);
@ -910,7 +908,11 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
tmp = tmp->next; tmp = tmp->next;
} }
screen->tab_popup = meta_ui_tab_popup_new (entries, screen->number); screen->tab_popup = meta_ui_tab_popup_new (entries,
screen->number,
len,
5, /* FIXME */
TRUE);
g_free (entries); g_free (entries);
g_slist_free (tab_list); g_slist_free (tab_list);
@ -1109,3 +1111,26 @@ meta_screen_update_workspace_layout (MetaScreen *screen)
screen->columns_of_workspaces, screen->columns_of_workspaces,
screen->vertical_workspaces); screen->vertical_workspaces);
} }
Window
meta_create_offscreen_window (Display *xdisplay,
Window parent)
{
XSetWindowAttributes attrs;
/* we want to be override redirect because sometimes we
* create a window on a screen we aren't managing.
* (but on a display we are managing at least one screen for)
*/
attrs.override_redirect = True;
return XCreateWindow (xdisplay,
parent,
-100, -100, 1, 1,
0,
CopyFromParent,
CopyFromParent,
CopyFromParent,
CWOverrideRedirect,
&attrs);
}

View File

@ -107,6 +107,9 @@ const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *s
void meta_screen_update_workspace_layout (MetaScreen *screen); void meta_screen_update_workspace_layout (MetaScreen *screen);
Window meta_create_offscreen_window (Display *xdisplay,
Window parent);
#endif #endif

View File

@ -1017,7 +1017,7 @@ meta_stack_get_default_focus_window (MetaStack *stack,
if (topmost_dock == NULL && if (topmost_dock == NULL &&
window->type == META_WINDOW_DOCK) window->type == META_WINDOW_DOCK)
topmost_dock = window; topmost_dock = window;
else else if (window->type != META_WINDOW_DOCK)
return window; return window;
} }

View File

@ -34,12 +34,12 @@ typedef struct _TabEntry TabEntry;
struct _TabEntry struct _TabEntry
{ {
Window xwindow; MetaTabEntryKey key;
char *title; char *title;
GdkPixbuf *icon; GdkPixbuf *icon;
GtkWidget *widget; GtkWidget *widget;
GdkRectangle rect; GdkRectangle rect;
GdkRectangle inner_rect; GdkRectangle inner_rect;
}; };
struct _MetaTabPopup struct _MetaTabPopup
@ -50,6 +50,7 @@ struct _MetaTabPopup
GList *entries; GList *entries;
TabEntry *current_selected_entry; TabEntry *current_selected_entry;
GtkWidget *outline_window; GtkWidget *outline_window;
gboolean outline;
}; };
static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf); static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf);
@ -67,7 +68,7 @@ outline_window_expose (GtkWidget *widget,
popup = data; popup = data;
if (popup->current_selected_entry == NULL) if (!popup->outline || popup->current_selected_entry == NULL)
return FALSE; return FALSE;
te = popup->current_selected_entry; te = popup->current_selected_entry;
@ -86,19 +87,21 @@ outline_window_expose (GtkWidget *widget,
FALSE, FALSE,
te->inner_rect.x - 1, te->inner_rect.y - 1, te->inner_rect.x - 1, te->inner_rect.y - 1,
te->inner_rect.width + 1, te->inner_rect.width + 1,
te->inner_rect.height + 1); te->inner_rect.height + 1);
return FALSE; return FALSE;
} }
MetaTabPopup* MetaTabPopup*
meta_ui_tab_popup_new (const MetaTabEntry *entries, meta_ui_tab_popup_new (const MetaTabEntry *entries,
int screen_number) int screen_number,
int entry_count,
int width,
gboolean outline)
{ {
MetaTabPopup *popup; MetaTabPopup *popup;
int i, left, right, top, bottom; int i, left, right, top, bottom;
GList *tab_entries; GList *tab_entries;
int width;
int height; int height;
GtkWidget *table; GtkWidget *table;
GtkWidget *vbox; GtkWidget *vbox;
@ -137,38 +140,39 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries,
popup->current = NULL; popup->current = NULL;
popup->entries = NULL; popup->entries = NULL;
popup->current_selected_entry = NULL; popup->current_selected_entry = NULL;
popup->outline = outline;
tab_entries = NULL; tab_entries = NULL;
i = 0; for (i = 0; i < entry_count; ++i)
while (entries[i].xwindow != None)
{ {
TabEntry *te; TabEntry *te;
te = g_new (TabEntry, 1); te = g_new (TabEntry, 1);
te->xwindow = entries[i].xwindow; te->key = entries[i].key;
te->title = g_strdup (entries[i].title); te->title = g_strdup (entries[i].title);
te->icon = entries[i].icon; te->icon = entries[i].icon;
g_object_ref (G_OBJECT (te->icon)); g_object_ref (G_OBJECT (te->icon));
te->widget = NULL; te->widget = NULL;
te->rect.x = entries[i].x; if (outline)
te->rect.y = entries[i].y; {
te->rect.width = entries[i].width; te->rect.x = entries[i].x;
te->rect.height = entries[i].height; te->rect.y = entries[i].y;
te->rect.width = entries[i].width;
te->rect.height = entries[i].height;
te->inner_rect.x = entries[i].inner_x;
te->inner_rect.y = entries[i].inner_y;
te->inner_rect.width = entries[i].inner_width;
te->inner_rect.height = entries[i].inner_height;
}
te->inner_rect.x = entries[i].inner_x;
te->inner_rect.y = entries[i].inner_y;
te->inner_rect.width = entries[i].inner_width;
te->inner_rect.height = entries[i].inner_height;
tab_entries = g_list_prepend (tab_entries, te); tab_entries = g_list_prepend (tab_entries, te);
++i;
} }
popup->entries = g_list_reverse (tab_entries); popup->entries = g_list_reverse (tab_entries);
width = 5; /* FIXME */ g_assert (width > 0);
height = i / width; height = i / width;
if (i % width) if (i % width)
height += 1; height += 1;
@ -316,36 +320,39 @@ display_entry (MetaTabPopup *popup,
gtk_label_set_text (GTK_LABEL (popup->label), te->title); gtk_label_set_text (GTK_LABEL (popup->label), te->title);
select_image (te->widget); select_image (te->widget);
/* Do stuff behind gtk's back */ if (popup->outline)
gdk_window_hide (popup->outline_window->window); {
meta_core_increment_event_serial (gdk_display); /* Do stuff behind gtk's back */
gdk_window_hide (popup->outline_window->window);
meta_core_increment_event_serial (gdk_display);
rect = te->rect; rect = te->rect;
rect.x = 0; rect.x = 0;
rect.y = 0; rect.y = 0;
gdk_window_move_resize (popup->outline_window->window, gdk_window_move_resize (popup->outline_window->window,
te->rect.x, te->rect.y, te->rect.x, te->rect.y,
te->rect.width, te->rect.height); te->rect.width, te->rect.height);
gdk_window_set_background (popup->outline_window->window, gdk_window_set_background (popup->outline_window->window,
&popup->outline_window->style->black); &popup->outline_window->style->black);
region = gdk_region_rectangle (&rect); region = gdk_region_rectangle (&rect);
inner_region = gdk_region_rectangle (&te->inner_rect); inner_region = gdk_region_rectangle (&te->inner_rect);
gdk_region_subtract (region, inner_region); gdk_region_subtract (region, inner_region);
gdk_region_destroy (inner_region); gdk_region_destroy (inner_region);
gdk_window_shape_combine_region (popup->outline_window->window, gdk_window_shape_combine_region (popup->outline_window->window,
region, region,
0, 0); 0, 0);
gdk_region_destroy (region); gdk_region_destroy (region);
/* This should piss off gtk a bit, but we don't want to raise /* This should piss off gtk a bit, but we don't want to raise
* above the tab popup * above the tab popup
*/ */
gdk_window_show_unraised (popup->outline_window->window); gdk_window_show_unraised (popup->outline_window->window);
}
/* Must be before we handle an expose for the outline window */ /* Must be before we handle an expose for the outline window */
popup->current_selected_entry = te; popup->current_selected_entry = te;
@ -389,7 +396,7 @@ meta_ui_tab_popup_backward (MetaTabPopup *popup)
} }
} }
Window MetaTabEntryKey
meta_ui_tab_popup_get_selected (MetaTabPopup *popup) meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
{ {
if (popup->current) if (popup->current)
@ -398,7 +405,7 @@ meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
te = popup->current->data; te = popup->current->data;
return te->xwindow; return te->key;
} }
else else
return None; return None;
@ -406,7 +413,7 @@ meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
void void
meta_ui_tab_popup_select (MetaTabPopup *popup, meta_ui_tab_popup_select (MetaTabPopup *popup,
Window xwindow) MetaTabEntryKey key)
{ {
GList *tmp; GList *tmp;
@ -417,7 +424,7 @@ meta_ui_tab_popup_select (MetaTabPopup *popup,
te = tmp->data; te = tmp->data;
if (te->xwindow == xwindow) if (te->key == key)
{ {
popup->current = tmp; popup->current = tmp;

View File

@ -30,26 +30,30 @@
typedef struct _MetaTabEntry MetaTabEntry; typedef struct _MetaTabEntry MetaTabEntry;
typedef struct _MetaTabPopup MetaTabPopup; typedef struct _MetaTabPopup MetaTabPopup;
typedef void *MetaTabEntryKey;
struct _MetaTabEntry struct _MetaTabEntry
{ {
Window xwindow; MetaTabEntryKey key;
const char *title; const char *title;
GdkPixbuf *icon; GdkPixbuf *icon;
int x, y, width, height; int x, y, width, height;
int inner_x, inner_y, inner_width, inner_height; int inner_x, inner_y, inner_width, inner_height;
}; };
MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries, MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries,
int screen_number); int screen_number,
void meta_ui_tab_popup_free (MetaTabPopup *popup); int entry_count,
void meta_ui_tab_popup_set_showing (MetaTabPopup *popup, int width,
gboolean showing); gboolean outline);
void meta_ui_tab_popup_forward (MetaTabPopup *popup); void meta_ui_tab_popup_free (MetaTabPopup *popup);
void meta_ui_tab_popup_backward (MetaTabPopup *popup); void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
Window meta_ui_tab_popup_get_selected (MetaTabPopup *popup); gboolean showing);
void meta_ui_tab_popup_select (MetaTabPopup *popup, void meta_ui_tab_popup_forward (MetaTabPopup *popup);
Window xwindow); void meta_ui_tab_popup_backward (MetaTabPopup *popup);
MetaTabEntryKey meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
void meta_ui_tab_popup_select (MetaTabPopup *popup,
MetaTabEntryKey key);
#endif #endif

View File

@ -19,6 +19,7 @@
* 02111-1307, USA. * 02111-1307, USA.
*/ */
#include <config.h>
#include "workspace.h" #include "workspace.h"
#include "errors.h" #include "errors.h"
#include <X11/Xatom.h> #include <X11/Xatom.h>
@ -512,16 +513,11 @@ meta_workspace_get_work_area (MetaWorkspace *workspace,
*area = workspace->work_area; *area = workspace->work_area;
} }
MetaWorkspace* static void
meta_workspace_get_neighbor (MetaWorkspace *workspace, calc_rows_and_cols (MetaScreen *screen, int num_workspaces, int *r, int *c)
MetaMotionDirection direction)
{ {
int i, num_workspaces, grid_area; int cols, rows;
int rows, cols;
i = meta_workspace_index (workspace);
num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
/* /*
* 3 rows, 4 columns, horizontal layout: * 3 rows, 4 columns, horizontal layout:
* +--+--+--+--+ * +--+--+--+--+
@ -543,8 +539,8 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
* *
*/ */
rows = workspace->screen->rows_of_workspaces; rows = screen->rows_of_workspaces;
cols = workspace->screen->columns_of_workspaces; cols = screen->columns_of_workspaces;
if (rows <= 0 && cols <= 0) if (rows <= 0 && cols <= 0)
cols = num_workspaces; cols = num_workspaces;
@ -559,6 +555,22 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
if (cols < 1) if (cols < 1)
cols = 1; cols = 1;
*r = rows;
*c = cols;
}
MetaWorkspace*
meta_workspace_get_neighbor (MetaWorkspace *workspace,
MetaMotionDirection direction)
{
int i, num_workspaces, grid_area;
int rows, cols;
i = meta_workspace_index (workspace);
num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
calc_rows_and_cols (workspace->screen, num_workspaces, &rows, &cols);
grid_area = rows * cols; grid_area = rows * cols;
meta_verbose ("Getting neighbor rows = %d cols = %d vert = %d " meta_verbose ("Getting neighbor rows = %d cols = %d vert = %d "
@ -640,3 +652,86 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
return meta_display_get_workspace_by_index (workspace->screen->display, return meta_display_get_workspace_by_index (workspace->screen->display,
i); i);
} }
void
meta_workspace_ensure_tab_popup (MetaDisplay *display,
MetaScreen *screen)
{
MetaTabEntry *entries;
GdkPixbuf *icon;
int len, rows, cols;
int i;
if (screen->tab_popup)
return;
icon = meta_ui_get_default_window_icon (NULL);
len = meta_screen_get_n_workspaces (screen);
entries = g_new (MetaTabEntry, len + 1);
entries[len].key = NULL;
entries[len].title = NULL;
entries[len].icon = NULL;
calc_rows_and_cols (screen, len, &rows, &cols);
if (screen->vertical_workspaces)
{
int j, k;
for (i = 0; i < rows; ++i)
{
for (j = 0; j < cols; ++j)
{
MetaWorkspace *workspace;
char *title;
k = i + (j * rows);
workspace = meta_display_get_workspace_by_index (display, k);
g_assert (workspace);
title = g_strdup_printf (_("Workspace %d"), k + 1);
entries[i].key = (MetaTabEntryKey) workspace;
entries[i].title = title;
entries[i].icon = icon;
}
}
}
else
{
for (i = 0; i < len; ++i)
{
MetaWorkspace *workspace;
char *title;
workspace = meta_display_get_workspace_by_index (display, i);
g_assert (workspace);
title = g_strdup_printf (_("Workspace %d"), i + 1);
entries[i].key = (MetaTabEntryKey) workspace;
entries[i].title = title;
entries[i].icon = icon;
}
}
screen->tab_popup = meta_ui_tab_popup_new (entries,
screen->number,
len,
cols,
FALSE);
for (i = 0; i < len; ++i)
g_free((void *) entries[i].title);
g_free (entries);
g_object_unref (G_OBJECT (icon));
/* don't show tab popup, since proper window isn't selected yet */
}

View File

@ -69,6 +69,9 @@ void meta_workspace_get_work_area (MetaWorkspace *workspace,
MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace, MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace,
MetaMotionDirection direction); MetaMotionDirection direction);
void meta_workspace_ensure_tab_popup (MetaDisplay *display,
MetaScreen *screen);
#endif #endif