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>
* 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_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 */
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_TABBING_NORMAL:
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;
break;
@ -2251,6 +2255,13 @@ meta_display_begin_grab_op (MetaDisplay *display,
META_TAB_LIST_DOCKS);
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:
break;
}
@ -2268,7 +2279,11 @@ meta_display_end_grab_op (MetaDisplay *display,
return;
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);
display->grab_window->screen->tab_popup = NULL;

View File

@ -94,6 +94,10 @@ static void handle_move_to_workspace (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding);
static void handle_workspace_forward (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding);
static void handle_raise_or_lower (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
@ -115,6 +119,11 @@ static gboolean process_tab_grab (MetaDisplay *display,
XEvent *event,
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_window_bindings (MetaDisplay *display);
@ -159,13 +168,13 @@ static const MetaKeyHandler screen_handlers[] = {
GINT_TO_POINTER (10) },
{ META_KEYBINDING_WORKSPACE_12, handle_activate_workspace,
GINT_TO_POINTER (11) },
{ META_KEYBINDING_WORKSPACE_LEFT, handle_activate_workspace,
{ META_KEYBINDING_WORKSPACE_LEFT, handle_workspace_forward,
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) },
{ META_KEYBINDING_WORKSPACE_UP, handle_activate_workspace,
{ META_KEYBINDING_WORKSPACE_UP, handle_workspace_forward,
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) },
{ META_KEYBINDING_SWITCH_WINDOWS, handle_tab_forward,
GINT_TO_POINTER (META_TAB_LIST_NORMAL) },
@ -593,10 +602,10 @@ meta_change_keygrab (MetaDisplay *display,
*/
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",
keysym_name (keysym),
modmask);
modmask, xwindow);
ignored_mask = 0;
while (ignored_mask < (int) display->ignored_modifier_mask)
@ -1062,7 +1071,7 @@ meta_display_process_key_event (MetaDisplay *display,
return;
}
if (display->grab_op == META_GRAB_OP_NONE)
return;
@ -1088,6 +1097,15 @@ meta_display_process_key_event (MetaDisplay *display,
"Processing event for keyboard tabbing\n");
handled = process_tab_grab (display, window, event, keysym);
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:
break;
}
@ -1213,6 +1231,7 @@ process_tab_grab (MetaDisplay *display,
KeySym keysym)
{
MetaScreen *screen;
MetaKeyBindingAction action;
window = NULL; /* be sure we don't use this, it's irrelevant */
@ -1229,7 +1248,7 @@ process_tab_grab (MetaDisplay *display,
MetaWindow *target_window;
target_xwindow =
meta_ui_tab_popup_get_selected (screen->tab_popup);
(Window) meta_ui_tab_popup_get_selected (screen->tab_popup);
target_window =
meta_display_lookup_x_window (display, target_xwindow);
@ -1263,10 +1282,12 @@ process_tab_grab (MetaDisplay *display,
if (is_modifier (display, event->xkey.keycode))
return TRUE;
switch (keysym)
action = meta_prefs_get_keybinding_action(keysym);
switch (action)
{
case XK_ISO_Left_Tab:
case XK_Tab:
case META_KEYBINDING_ACTION_SWITCH_PANELS:
case META_KEYBINDING_ACTION_SWITCH_WINDOWS:
if (event->xkey.state & ShiftMask)
meta_ui_tab_popup_backward (screen->tab_popup);
else
@ -1339,7 +1360,7 @@ handle_activate_workspace (MetaDisplay *display,
MetaWorkspace *workspace;
which = GPOINTER_TO_INT (binding->handler->data);
workspace = NULL;
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
handle_toggle_desktop (MetaDisplay *display,
MetaWindow *window,
@ -1484,7 +1611,7 @@ handle_tab_forward (MetaDisplay *display,
0, 0))
{
meta_ui_tab_popup_select (window->screen->tab_popup,
window->xwindow);
(MetaTabEntryKey) window->xwindow);
/* only after selecting proper window */
meta_ui_tab_popup_set_showing (window->screen->tab_popup,
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
handle_focus_previous (MetaDisplay *display,
MetaWindow *event_window,
@ -1510,36 +1680,8 @@ handle_focus_previous (MetaDisplay *display,
if (screen == NULL)
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)
{
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
handle_spew_mark (MetaDisplay *display,
MetaWindow *window,

View File

@ -1031,3 +1031,19 @@ meta_prefs_get_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_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
{
const char *name;
@ -124,6 +149,7 @@ void meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
int *n_bindings);
void meta_prefs_get_window_bindings (const MetaKeyPref **bindings,
int *n_bindings);
MetaKeyBindingAction meta_prefs_get_keybinding_action (unsigned int keysym);
#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 */
}
new_wm_sn_owner = XCreateSimpleWindow (xdisplay, xroot,
-100, -100, 1, 1, 0, 0, 0);
new_wm_sn_owner = meta_create_offscreen_window (xdisplay, xroot);
{
/* Generate a timestamp */
@ -441,17 +440,16 @@ meta_screen_new (MetaDisplay *display,
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
if (display->leader_window == None)
display->leader_window = XCreateSimpleWindow (display->xdisplay,
screen->xroot,
-100, -100, 1, 1, 0, 0, 0);
display->leader_window = meta_create_offscreen_window (display->xdisplay,
screen->xroot);
if (display->no_focus_window == None)
{
display->no_focus_window = XCreateSimpleWindow (display->xdisplay,
screen->xroot,
-100, -100, 1, 1, 0, 0, 0);
display->no_focus_window = meta_create_offscreen_window (display->xdisplay,
screen->xroot);
XSelectInput (display->xdisplay, display->no_focus_window,
FocusChangeMask);
FocusChangeMask | KeyPressMask | KeyReleaseMask);
XMapWindow (display->xdisplay, display->no_focus_window);
}
@ -857,7 +855,7 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
len = g_slist_length (tab_list);
entries = g_new (MetaTabEntry, len + 1);
entries[len].xwindow = None;
entries[len].key = NULL;
entries[len].title = NULL;
entries[len].icon = NULL;
@ -870,7 +868,7 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
window = tmp->data;
entries[i].xwindow = window->xwindow;
entries[i].key = (MetaTabEntryKey) window->xwindow;
entries[i].title = window->title;
entries[i].icon = window->icon;
meta_window_get_outer_rect (window, &r);
@ -910,7 +908,11 @@ meta_screen_ensure_tab_popup (MetaScreen *screen,
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_slist_free (tab_list);
@ -1109,3 +1111,26 @@ meta_screen_update_workspace_layout (MetaScreen *screen)
screen->columns_of_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);
Window meta_create_offscreen_window (Display *xdisplay,
Window parent);
#endif

View File

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

View File

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

View File

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

View File

@ -19,6 +19,7 @@
* 02111-1307, USA.
*/
#include <config.h>
#include "workspace.h"
#include "errors.h"
#include <X11/Xatom.h>
@ -512,16 +513,11 @@ meta_workspace_get_work_area (MetaWorkspace *workspace,
*area = workspace->work_area;
}
MetaWorkspace*
meta_workspace_get_neighbor (MetaWorkspace *workspace,
MetaMotionDirection direction)
static void
calc_rows_and_cols (MetaScreen *screen, int num_workspaces, int *r, int *c)
{
int i, num_workspaces, grid_area;
int rows, cols;
i = meta_workspace_index (workspace);
num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
int cols, rows;
/*
* 3 rows, 4 columns, horizontal layout:
* +--+--+--+--+
@ -543,8 +539,8 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
*
*/
rows = workspace->screen->rows_of_workspaces;
cols = workspace->screen->columns_of_workspaces;
rows = screen->rows_of_workspaces;
cols = screen->columns_of_workspaces;
if (rows <= 0 && cols <= 0)
cols = num_workspaces;
@ -559,6 +555,22 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
if (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;
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,
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,
MetaMotionDirection direction);
void meta_workspace_ensure_tab_popup (MetaDisplay *display,
MetaScreen *screen);
#endif