summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrhp <rhp>2001-06-23 05:49:35 +0000
committerrhp <rhp>2001-06-23 05:49:35 +0000
commitbf64e719a1fea9e99b737b11771a41272c2e881e (patch)
treef2536630b810b36d7905f78a4720523df8c7b328
parent7ecf21af703d22f2975d7926e71fb453176e4271 (diff)
downloadmutter-bf64e719a1fea9e99b737b11771a41272c2e881e.tar.gz
...
-rw-r--r--src/common.h23
-rw-r--r--src/core.c20
-rw-r--r--src/core.h7
-rw-r--r--src/display.c8
-rw-r--r--src/display.h2
-rw-r--r--src/frame.c16
-rw-r--r--src/frames.c22
-rw-r--r--src/frames.h3
-rw-r--r--src/keybindings.c156
-rw-r--r--src/keybindings.h4
-rw-r--r--src/menu.c229
-rw-r--r--src/menu.h33
-rw-r--r--src/screen.c16
-rw-r--r--src/session.h2
-rw-r--r--src/ui.c34
-rw-r--r--src/ui.h17
-rw-r--r--src/window.c244
-rw-r--r--src/window.h13
18 files changed, 621 insertions, 228 deletions
diff --git a/src/common.h b/src/common.h
index 8ac4ea890..10f6bd17e 100644
--- a/src/common.h
+++ b/src/common.h
@@ -24,6 +24,7 @@
/* Don't include GTK or core headers here */
#include <X11/Xlib.h>
+#include <glib.h>
typedef enum
{
@@ -39,4 +40,26 @@ typedef enum
META_FRAME_MAXIMIZED = 1 << 9
} MetaFrameFlags;
+typedef enum
+{
+ META_MENU_OP_DELETE = 1 << 0,
+ META_MENU_OP_MINIMIZE = 1 << 1,
+ META_MENU_OP_UNMAXIMIZE = 1 << 2,
+ META_MENU_OP_MAXIMIZE = 1 << 3,
+ META_MENU_OP_UNSHADE = 1 << 4,
+ META_MENU_OP_SHADE = 1 << 5,
+ META_MENU_OP_UNSTICK = 1 << 6,
+ META_MENU_OP_STICK = 1 << 7,
+ META_MENU_OP_WORKSPACES = 1 << 8
+} MetaMenuOp;
+
+typedef struct _MetaWindowMenu MetaWindowMenu;
+
+typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu,
+ Display *xdisplay,
+ Window client_xwindow,
+ MetaMenuOp op,
+ int workspace,
+ gpointer data);
+
#endif
diff --git a/src/core.c b/src/core.c
index 330dfefe2..c1b856af1 100644
--- a/src/core.c
+++ b/src/core.c
@@ -355,4 +355,24 @@ meta_core_get_frame_workspace (Display *xdisplay,
return meta_window_get_net_wm_desktop (window);
}
+void
+meta_core_show_window_menu (Display *xdisplay,
+ Window frame_xwindow,
+ int root_x,
+ int root_y,
+ int button,
+ Time timestamp)
+{
+ MetaDisplay *display;
+ MetaWindow *window;
+
+ display = meta_display_for_x_display (xdisplay);
+ window = meta_display_lookup_x_window (display, frame_xwindow);
+
+ if (window == NULL || window->frame == NULL)
+ meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
+
+ meta_window_show_menu (window, root_x, root_y, button, timestamp);
+}
+
diff --git a/src/core.h b/src/core.h
index bf6bcdcab..e6c3bcc67 100644
--- a/src/core.h
+++ b/src/core.h
@@ -91,6 +91,13 @@ int meta_core_get_frame_workspace (Display *xdisplay,
Window frame_xwindow);
+void meta_core_show_window_menu (Display *xdisplay,
+ Window frame_xwindow,
+ int root_x,
+ int root_y,
+ int button,
+ Time timestamp);
+
#endif
diff --git a/src/display.c b/src/display.c
index bea957918..652260835 100644
--- a/src/display.c
+++ b/src/display.c
@@ -125,7 +125,9 @@ meta_display_open (const char *name)
"_NET_WM_STATE_SKIP_TASKBAR",
"_NET_WM_STATE_SKIP_PAGER",
"_WIN_WORKSPACE",
- "_WIN_LAYER"
+ "_WIN_LAYER",
+ "_WIN_PROTOCOLS",
+ "_WIN_SUPPORTING_WM_CHECK"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@@ -200,6 +202,8 @@ meta_display_open (const char *name)
display->atom_net_wm_state_skip_pager = atoms[31];
display->atom_win_workspace = atoms[32];
display->atom_win_layer = atoms[33];
+ display->atom_win_protocols = atoms[34];
+ display->atom_win_supporting_wm_check = atoms[35];
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
* created in screen_new
@@ -268,7 +272,7 @@ meta_display_open (const char *name)
set_string_hint (display,
display->leader_window,
- display->atom_net_supporting_wm_check,
+ display->atom_net_wm_name,
"Metacity");
/* Now manage all existing windows */
diff --git a/src/display.h b/src/display.h
index 6f2b24df5..e5fa6d5f6 100644
--- a/src/display.h
+++ b/src/display.h
@@ -90,6 +90,8 @@ struct _MetaDisplay
Atom atom_net_wm_state_skip_pager;
Atom atom_win_workspace;
Atom atom_win_layer;
+ Atom atom_win_protocols;
+ Atom atom_win_supporting_wm_check;
/* This is the actual window from focus events,
* not the one we last set
diff --git a/src/frame.c b/src/frame.c
index 5f2b3f828..90df8c81a 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -27,7 +27,8 @@
ExposureMask | \
ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | PointerMotionHintMask | \
- EnterWindowMask | LeaveWindowMask)
+ EnterWindowMask | LeaveWindowMask | \
+ FocusChangeMask)
void
meta_window_ensure_frame (MetaWindow *window)
@@ -106,6 +107,9 @@ meta_window_ensure_frame (MetaWindow *window)
meta_ui_set_frame_title (window->screen->ui,
window->frame->xwindow,
window->title);
+
+ /* Move keybindings to frame instead of window */
+ meta_window_grab_keys (window);
}
void
@@ -117,7 +121,7 @@ meta_window_destroy_frame (MetaWindow *window)
return;
frame = window->frame;
-
+
meta_ui_remove_frame (window->screen->ui, frame->xwindow);
/* Unparent the client window; it may be destroyed,
@@ -142,6 +146,9 @@ meta_window_destroy_frame (MetaWindow *window)
window->frame = NULL;
+ /* Move keybindings to window instead of frame */
+ meta_window_grab_keys (window);
+
/* should we push an error trap? */
XDestroyWindow (window->display->xdisplay, frame->xwindow);
@@ -270,6 +277,8 @@ meta_frame_event (MetaFrame *frame,
switch (event->type)
{
case KeyPress:
+ meta_display_process_key_press (frame->window->display,
+ frame->window, event);
break;
case KeyRelease:
break;
@@ -290,8 +299,9 @@ meta_frame_event (MetaFrame *frame,
case LeaveNotify:
break;
case FocusIn:
- break;
case FocusOut:
+ meta_window_notify_focus (frame->window,
+ event);
break;
case KeymapNotify:
break;
diff --git a/src/frames.c b/src/frames.c
index 1b0f37e04..235406f9a 100644
--- a/src/frames.c
+++ b/src/frames.c
@@ -300,9 +300,6 @@ meta_frames_destroy (GtkObject *object)
MetaFrames *frames;
frames = META_FRAMES (object);
-
- if (frames->menu)
- gtk_widget_destroy (frames->menu);
winlist = NULL;
g_hash_table_foreach (frames->frames,
@@ -856,13 +853,7 @@ meta_frames_end_grab (MetaFrames *frames,
guint32 timestamp)
{
if (frames->grab_frame)
- {
- if (frames->grab_status == META_FRAME_STATUS_CLICKING_MENU)
- {
- if (frames->menu)
- gtk_widget_destroy (frames->menu);
- }
-
+ {
frames->grab_frame = NULL;
frames->grab_status = META_FRAME_STATUS_NORMAL;
gdk_pointer_ungrab (timestamp);
@@ -1030,11 +1021,12 @@ meta_frames_button_press_event (GtkWidget *widget,
if (status == META_FRAME_STATUS_CLICKING_MENU)
{
- meta_window_menu_show (frames, frame,
- event->x_root,
- event->y_root,
- event->button,
- event->time);
+ meta_core_show_window_menu (gdk_display,
+ frame->xwindow,
+ event->x_root,
+ event->y_root,
+ event->button,
+ event->time);
}
}
else if (control == META_FRAME_CONTROL_RESIZE_SE &&
diff --git a/src/frames.h b/src/frames.h
index d79c3057d..fe6bcc4af 100644
--- a/src/frames.h
+++ b/src/frames.h
@@ -89,8 +89,6 @@ struct _MetaFrames
int text_height;
GHashTable *frames;
-
- GtkWidget *menu;
/* The below is all for grabs */
MetaFrameStatus grab_status;
@@ -136,6 +134,7 @@ void meta_frames_get_pixmap_for_control (MetaFrames *frames,
MetaFrameControl control,
GdkPixmap **pixmap,
GdkBitmap **mask);
+
void meta_frames_notify_menu_hide (MetaFrames *frames);
#endif
diff --git a/src/keybindings.c b/src/keybindings.c
index 38ad32e10..009c3bc2d 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -22,6 +22,8 @@
#include "keybindings.h"
#include "workspace.h"
#include "errors.h"
+#include "ui.h"
+#include "frame.h"
#include <X11/keysym.h>
@@ -30,12 +32,18 @@
*/
typedef void (* MetaKeyHandler) (MetaDisplay *display,
+ MetaWindow *window,
XEvent *event,
gpointer data);
static void handle_activate_workspace (MetaDisplay *display,
- XEvent *event,
- gpointer data);
+ MetaWindow *window,
+ XEvent *event,
+ gpointer data);
+static void handle_activate_menu (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ gpointer data);
typedef struct _MetaKeyBinding MetaKeyBinding;
@@ -50,7 +58,7 @@ struct _MetaKeyBinding
#define INTERESTING_MODIFIERS (ShiftMask | ControlMask | Mod1Mask)
-static MetaKeyBinding bindings[] = {
+static MetaKeyBinding screen_bindings[] = {
{ XK_F1, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (0), 0 },
{ XK_F2, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (1), 0 },
{ XK_F3, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (2), 0 },
@@ -62,41 +70,57 @@ static MetaKeyBinding bindings[] = {
{ XK_3, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (2), 0 },
{ XK_4, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (3), 0 },
{ XK_5, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (4), 0 },
- { XK_6, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (5), 0 }
+ { XK_6, Mod1Mask, handle_activate_workspace, GINT_TO_POINTER (5), 0 },
+ { None, 0, NULL, NULL, 0 }
};
-void
-meta_display_init_keys (MetaDisplay *display)
+static MetaKeyBinding window_bindings[] = {
+ { XK_space, Mod1Mask, handle_activate_menu, NULL, 0 },
+ { None, 0, NULL, NULL, 0 }
+};
+
+static void
+init_bindings (MetaDisplay *display,
+ MetaKeyBinding *bindings)
{
int i;
i = 0;
- while (i < G_N_ELEMENTS (bindings))
+ while (bindings[i].keysym != None)
{
bindings[i].keycode = XKeysymToKeycode (display->xdisplay,
bindings[i].keysym);
++i;
}
-}
+}
void
-meta_screen_grab_keys (MetaScreen *screen)
+meta_display_init_keys (MetaDisplay *display)
+{
+ init_bindings (display, screen_bindings);
+ init_bindings (display, window_bindings);
+}
+
+static void
+grab_keys (MetaKeyBinding *bindings,
+ MetaDisplay *display,
+ Window xwindow)
{
int i;
i = 0;
- while (i < G_N_ELEMENTS (bindings))
+ while (bindings[i].keysym != None)
{
if (bindings[i].keycode != 0)
{
int result;
- meta_error_trap_push (screen->display);
- XGrabKey (screen->display->xdisplay, bindings[i].keycode,
- bindings[i].mask, screen->xroot, True,
+ meta_error_trap_push (display);
+ XGrabKey (display->xdisplay, bindings[i].keycode,
+ bindings[i].mask, xwindow, True,
GrabModeAsync, GrabModeAsync);
- result = meta_error_trap_pop (screen->display);
+ result = meta_error_trap_pop (display);
if (result != Success)
{
const char *name;
@@ -107,8 +131,6 @@ meta_screen_grab_keys (MetaScreen *screen)
if (result == BadAccess)
meta_warning (_("Some other program is already using the key %s as a binding\n"), name);
- else
- meta_bug ("Unexpected error setting up keybindings\n");
}
}
@@ -116,18 +138,22 @@ meta_screen_grab_keys (MetaScreen *screen)
}
}
-void
-meta_screen_ungrab_keys (MetaScreen *screen)
+static void
+ungrab_keys (MetaKeyBinding *bindings,
+ MetaDisplay *display,
+ Window xwindow)
{
int i;
i = 0;
- while (i < G_N_ELEMENTS (bindings))
+ while (bindings[i].keysym != None)
{
if (bindings[i].keycode != 0)
{
- XUngrabKey (screen->display->xdisplay, bindings[i].keycode,
- bindings[i].mask, screen->xroot);
+ meta_error_trap_push (display);
+ XUngrabKey (display->xdisplay, bindings[i].keycode,
+ bindings[i].mask, xwindow);
+ meta_error_trap_pop (display);
}
++i;
@@ -135,8 +161,59 @@ meta_screen_ungrab_keys (MetaScreen *screen)
}
void
-meta_display_process_key_press (MetaDisplay *display,
- XEvent *event)
+meta_screen_grab_keys (MetaScreen *screen)
+{
+ grab_keys (screen_bindings, screen->display, screen->xroot);
+}
+
+void
+meta_screen_ungrab_keys (MetaScreen *screen)
+{
+ ungrab_keys (screen_bindings, screen->display, screen->xroot);
+}
+
+void
+meta_window_grab_keys (MetaWindow *window)
+{
+ if (window->keys_grabbed)
+ {
+ if (window->frame && !window->grab_on_frame)
+ ungrab_keys (window_bindings, window->display,
+ window->xwindow);
+ else if (window->frame == NULL &&
+ window->grab_on_frame)
+ ; /* continue to regrab on client window */
+ else
+ return; /* already all good */
+ }
+
+ grab_keys (window_bindings, window->display,
+ window->frame ? window->frame->xwindow : window->xwindow);
+
+ window->keys_grabbed = TRUE;
+ window->grab_on_frame = window->frame != NULL;
+}
+
+void
+meta_window_ungrab_keys (MetaWindow *window)
+{
+ if (window->keys_grabbed)
+ {
+ if (window->grab_on_frame &&
+ window->frame != NULL)
+ ungrab_keys (window_bindings, window->display,
+ window->frame->xwindow);
+ else if (!window->grab_on_frame)
+ ungrab_keys (window_bindings, window->display,
+ window->xwindow);
+ }
+}
+
+static void
+process_event (MetaKeyBinding *bindings,
+ MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event)
{
KeySym keysym;
int i;
@@ -144,22 +221,32 @@ meta_display_process_key_press (MetaDisplay *display,
keysym = XKeycodeToKeysym (display->xdisplay, event->xkey.keycode, 0);
i = 0;
- while (i < G_N_ELEMENTS (bindings))
+ while (bindings[i].keysym != None)
{
if (bindings[i].keysym == keysym &&
((event->xkey.state & INTERESTING_MODIFIERS) ==
bindings[i].mask))
{
- (* bindings[i].handler) (display, event, bindings[i].data);
+ (* bindings[i].handler) (display, window, event, bindings[i].data);
break;
}
++i;
}
}
+
+void
+meta_display_process_key_press (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event)
+{
+ process_event (screen_bindings, display, window, event);
+ process_event (window_bindings, display, window, event);
+}
static void
handle_activate_workspace (MetaDisplay *display,
+ MetaWindow *window,
XEvent *event,
gpointer data)
{
@@ -180,3 +267,22 @@ handle_activate_workspace (MetaDisplay *display,
}
}
+static void
+handle_activate_menu (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ gpointer data)
+{
+ if (display->focus_window)
+ {
+ int x, y;
+
+ meta_window_get_position (display->focus_window,
+ &x, &y);
+
+ meta_window_show_menu (display->focus_window,
+ x, y,
+ 0,
+ event->xkey.time);
+ }
+}
diff --git a/src/keybindings.h b/src/keybindings.h
index 9f252f096..3fa610197 100644
--- a/src/keybindings.h
+++ b/src/keybindings.h
@@ -23,11 +23,15 @@
#define META_KEYBINDINGS_H
#include "display.h"
+#include "window.h"
void meta_display_init_keys (MetaDisplay *display);
void meta_screen_grab_keys (MetaScreen *screen);
void meta_screen_ungrab_keys (MetaScreen *screen);
+void meta_window_grab_keys (MetaWindow *window);
+void meta_window_ungrab_keys (MetaWindow *window);
void meta_display_process_key_press (MetaDisplay *display,
+ MetaWindow *window,
XEvent *event);
#endif
diff --git a/src/menu.c b/src/menu.c
index e6cb010a3..2fb67a936 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -27,19 +27,6 @@
typedef struct _MenuItem MenuItem;
typedef struct _MenuData MenuData;
-typedef enum
-{
- META_MENU_OP_DELETE = 1 << 0,
- META_MENU_OP_MINIMIZE = 1 << 1,
- META_MENU_OP_UNMAXIMIZE = 1 << 2,
- META_MENU_OP_MAXIMIZE = 1 << 3,
- META_MENU_OP_UNSHADE = 1 << 4,
- META_MENU_OP_SHADE = 1 << 5,
- META_MENU_OP_UNSTICK = 1 << 6,
- META_MENU_OP_STICK = 1 << 7,
- META_MENU_OP_WORKSPACES = 1 << 8
-} MetaMenuOp;
-
struct _MenuItem
{
MetaMenuOp op;
@@ -50,8 +37,7 @@ struct _MenuItem
struct _MenuData
{
- MetaFrames *frames;
- MetaUIFrame *frame;
+ MetaWindowMenu *menu;
MetaMenuOp op;
};
@@ -92,70 +78,64 @@ popup_position_func (GtkMenu *menu,
}
static void
-menu_closed (GtkMenu *menu,
+menu_closed (GtkMenu *widget,
gpointer data)
{
- MetaFrames *frames;
-
- frames = META_FRAMES (data);
-
- meta_frames_notify_menu_hide (frames);
+ MetaWindowMenu *menu;
+
+ menu = data;
- gtk_widget_destroy (frames->menu);
- frames->menu = NULL;
+ meta_frames_notify_menu_hide (menu->frames);
+ (* menu->func) (menu, gdk_display,
+ menu->client_xwindow,
+ 0, 0,
+ menu->data);
+
+ /* menu may now be freed */
}
-void
-meta_window_menu_show (MetaFrames *frames,
- MetaUIFrame *frame,
- int root_x,
- int root_y,
- int button,
- guint32 timestamp)
+static void
+activate_cb (GtkWidget *menuitem, gpointer data)
{
- int i;
- GdkPoint *pt;
- int n_workspaces;
- int current_workspace;
- MetaMenuOp ops;
- MetaMenuOp insensitive;
- MetaFrameFlags flags;
-
- flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
+ MenuData *md;
- ops = 0;
- insensitive = 0;
+ g_return_if_fail (GTK_IS_WIDGET (menuitem));
- if (flags & META_FRAME_ALLOWS_MAXIMIZE)
- {
- if (flags & META_FRAME_MAXIMIZED)
- ops |= META_MENU_OP_UNMAXIMIZE;
- else
- ops |= META_MENU_OP_MAXIMIZE;
- }
+ md = data;
- if (flags & META_FRAME_SHADED)
- ops |= META_MENU_OP_UNSHADE;
- else
- ops |= META_MENU_OP_SHADE;
+ meta_frames_notify_menu_hide (md->menu->frames);
+ (* md->menu->func) (md->menu, gdk_display,
+ md->menu->client_xwindow,
+ md->op,
+ GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem),
+ "workspace")),
+ md->menu->data);
- if (flags & META_FRAME_STUCK)
- ops |= META_MENU_OP_UNSTICK;
- else
- ops |= META_MENU_OP_STICK;
-
- ops |= (META_MENU_OP_DELETE | META_MENU_OP_WORKSPACES | META_MENU_OP_MINIMIZE);
+ /* menu may now be freed */
+}
- if (!(flags & META_FRAME_ALLOWS_MINIMIZE))
- insensitive |= META_MENU_OP_MINIMIZE;
-
- if (!(flags & META_FRAME_ALLOWS_DELETE))
- insensitive |= META_MENU_OP_DELETE;
-
- if (frames->menu)
- gtk_widget_destroy (frames->menu);
+MetaWindowMenu*
+meta_window_menu_new (MetaFrames *frames,
+ MetaMenuOp ops,
+ MetaMenuOp insensitive,
+ Window client_xwindow,
+ int active_workspace,
+ int n_workspaces,
+ MetaWindowMenuFunc func,
+ gpointer data)
+{
+ int i;
+ MetaWindowMenu *menu;
+
+ menu = g_new (MetaWindowMenu, 1);
+ menu->frames = frames;
+ menu->client_xwindow = client_xwindow;
+ menu->func = func;
+ menu->data = data;
+ menu->ops = ops;
+ menu->insensitive = insensitive;
- frames->menu = gtk_menu_new ();
+ menu->menu = gtk_menu_new ();
i = 0;
while (i < G_N_ELEMENTS (menuitems))
@@ -234,8 +214,7 @@ meta_window_menu_show (MetaFrames *frames,
md = g_new (MenuData, 1);
- md->frames = frames;
- md->frame = frame;
+ md->menu = menu;
md->op = menuitems[i].op;
gtk_signal_connect_full (GTK_OBJECT (mi),
@@ -246,7 +225,7 @@ meta_window_menu_show (MetaFrames *frames,
g_free, FALSE, FALSE);
}
- gtk_menu_shell_append (GTK_MENU_SHELL (frames->menu),
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu),
mi);
gtk_widget_show (mi);
@@ -256,12 +235,8 @@ meta_window_menu_show (MetaFrames *frames,
if (ops & META_MENU_OP_WORKSPACES)
{
- n_workspaces = meta_core_get_num_workspaces (DefaultScreenOfDisplay (gdk_display));
- current_workspace = meta_core_get_frame_workspace (gdk_display,
- frame->xwindow);
-
meta_warning ("Creating %d-workspace menu current %d\n",
- n_workspaces, current_workspace);
+ n_workspaces, active_workspace);
if (n_workspaces > 0)
{
@@ -273,7 +248,7 @@ meta_window_menu_show (MetaFrames *frames,
char *label;
MenuData *md;
- if (flags & META_FRAME_STUCK)
+ if (ops & META_MENU_OP_UNSTICK)
label = g_strdup_printf (_("Only on workspace _%d\n"),
i + 1);
else
@@ -284,15 +259,14 @@ meta_window_menu_show (MetaFrames *frames,
g_free (label);
- if (!(flags & META_FRAME_STUCK) &&
- (current_workspace == i ||
+ if (!(ops & META_MENU_OP_UNSTICK) &&
+ (active_workspace == i ||
insensitive & META_MENU_OP_WORKSPACES))
gtk_widget_set_sensitive (mi, FALSE);
md = g_new (MenuData, 1);
- md->frames = frames;
- md->frame = frame;
+ md->menu = menu;
md->op = META_MENU_OP_WORKSPACES;
g_object_set_data (G_OBJECT (mi),
@@ -306,7 +280,7 @@ meta_window_menu_show (MetaFrames *frames,
md,
g_free, FALSE, FALSE);
- gtk_menu_shell_append (GTK_MENU_SHELL (frames->menu),
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu),
mi);
gtk_widget_show (mi);
@@ -318,14 +292,26 @@ meta_window_menu_show (MetaFrames *frames,
else
meta_verbose ("not creating workspace menu\n");
- gtk_signal_connect (GTK_OBJECT (frames->menu),
+ gtk_signal_connect (GTK_OBJECT (menu->menu),
"selection_done",
GTK_SIGNAL_FUNC (menu_closed),
- frames);
+ menu);
+
+ return menu;
+}
+
+void
+meta_window_menu_popup (MetaWindowMenu *menu,
+ int root_x,
+ int root_y,
+ int button,
+ guint32 timestamp)
+{
+ GdkPoint *pt;
pt = g_new (GdkPoint, 1);
- g_object_set_data_full (G_OBJECT (frames->menu),
+ g_object_set_data_full (G_OBJECT (menu->menu),
"destroy-point",
pt,
g_free);
@@ -333,82 +319,19 @@ meta_window_menu_show (MetaFrames *frames,
pt->x = root_x;
pt->y = root_y;
- gtk_menu_popup (GTK_MENU (frames->menu),
+ gtk_menu_popup (GTK_MENU (menu->menu),
NULL, NULL,
popup_position_func, pt,
button,
timestamp);
- if (!GTK_MENU_SHELL (frames->menu)->have_xgrab)
+ if (!GTK_MENU_SHELL (menu->menu)->have_xgrab)
meta_warning ("GtkMenu failed to grab the pointer\n");
}
-static void
-activate_cb (GtkWidget *menuitem, gpointer data)
+void
+meta_window_menu_free (MetaWindowMenu *menu)
{
- MenuData *md;
-
- g_return_if_fail (GTK_IS_WIDGET (menuitem));
-
- md = data;
-
- switch (md->op)
- {
- case META_MENU_OP_DELETE:
- meta_core_delete (gdk_display,
- md->frame->xwindow,
- gtk_get_current_event_time ());
- break;
-
- case META_MENU_OP_MINIMIZE:
- meta_core_minimize (gdk_display,
- md->frame->xwindow);
- break;
-
- case META_MENU_OP_UNMAXIMIZE:
- meta_core_unmaximize (gdk_display,
- md->frame->xwindow);
- break;
-
- case META_MENU_OP_MAXIMIZE:
- meta_core_maximize (gdk_display,
- md->frame->xwindow);
- break;
-
- case META_MENU_OP_UNSHADE:
- meta_core_unshade (gdk_display,
- md->frame->xwindow);
- break;
-
- case META_MENU_OP_SHADE:
- meta_core_shade (gdk_display,
- md->frame->xwindow);
- break;
-
- case META_MENU_OP_WORKSPACES:
- {
- int workspace;
-
- workspace = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem),
- "workspace"));
-
- meta_core_change_workspace (gdk_display, md->frame->xwindow,
- workspace);
- }
- break;
-
- case META_MENU_OP_STICK:
- meta_core_stick (gdk_display,
- md->frame->xwindow);
- break;
-
- case META_MENU_OP_UNSTICK:
- meta_core_unstick (gdk_display,
- md->frame->xwindow);
- break;
-
- default:
- meta_warning (G_STRLOC": Unknown window op\n");
- break;
- }
+ gtk_widget_destroy (menu->menu);
+ g_free (menu);
}
diff --git a/src/menu.h b/src/menu.h
index 30a096fc2..7fb5deef5 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -25,14 +25,31 @@
#include <gtk/gtk.h>
#include "frames.h"
-void meta_window_menu_show (MetaFrames *frames,
- MetaUIFrame *frame,
- int root_x,
- int root_y,
- int button,
- guint32 timestamp);
-
-
+struct _MetaWindowMenu
+{
+ MetaFrames *frames;
+ Window client_xwindow;
+ GtkWidget *menu;
+ MetaWindowMenuFunc func;
+ gpointer data;
+ MetaMenuOp ops;
+ MetaMenuOp insensitive;
+};
+
+MetaWindowMenu* meta_window_menu_new (MetaFrames *frames,
+ MetaMenuOp ops,
+ MetaMenuOp insensitive,
+ Window client_xwindow,
+ int active_workspace,
+ int n_workspaces,
+ MetaWindowMenuFunc func,
+ gpointer data);
+void meta_window_menu_popup (MetaWindowMenu *menu,
+ int root_x,
+ int root_y,
+ int button,
+ guint32 timestamp);
+void meta_window_menu_free (MetaWindowMenu *menu);
#endif
diff --git a/src/screen.c b/src/screen.c
index a9c00b6e6..966c47d4a 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -50,6 +50,13 @@ set_wm_check_hint (MetaScreen *screen)
screen->display->atom_net_supporting_wm_check,
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
+
+ /* Legacy GNOME hint */
+ XChangeProperty (screen->display->xdisplay, screen->xroot,
+ screen->display->atom_win_supporting_wm_check,
+ XA_WINDOW,
+ 32, PropModeReplace, (guchar*) data, 1);
+
return Success;
}
@@ -57,6 +64,7 @@ static int
set_supported_hint (MetaScreen *screen)
{
#define N_SUPPORTED 21
+#define N_WIN_SUPPORTED 1
Atom atoms[N_SUPPORTED];
atoms[0] = screen->display->atom_net_wm_name;
@@ -86,6 +94,14 @@ set_supported_hint (MetaScreen *screen)
XA_ATOM,
32, PropModeReplace, (guchar*) atoms, N_SUPPORTED);
+ /* Set legacy GNOME hints */
+ atoms[0] = screen->display->atom_win_layer;
+
+ XChangeProperty (screen->display->xdisplay, screen->xroot,
+ screen->display->atom_win_protocols,
+ XA_ATOM,
+ 32, PropModeReplace, (guchar*) atoms, N_WIN_SUPPORTED);
+
return Success;
#undef N_SUPPORTED
}
diff --git a/src/session.h b/src/session.h
index 13021df61..6cca5d4d2 100644
--- a/src/session.h
+++ b/src/session.h
@@ -41,6 +41,8 @@ struct _MetaSessionInfo
MetaSessionInfo* meta_window_lookup_session_info (MetaWindow *window);
+void meta_session_init (const char *previous_id);
+
#endif
diff --git a/src/ui.c b/src/ui.c
index 791676683..ff8d312b4 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -22,6 +22,7 @@
#include "ui.h"
#include "frames.h"
#include "util.h"
+#include "menu.h"
struct _MetaUI
{
@@ -197,4 +198,37 @@ meta_ui_set_frame_title (MetaUI *ui,
meta_frames_set_title (ui->frames, xwindow, title);
}
+MetaWindowMenu*
+meta_ui_window_menu_new (MetaUI *ui,
+ Window client_xwindow,
+ MetaMenuOp ops,
+ MetaMenuOp insensitive,
+ int active_workspace,
+ int n_workspaces,
+ MetaWindowMenuFunc func,
+ gpointer data)
+{
+ return meta_window_menu_new (ui->frames,
+ ops, insensitive,
+ client_xwindow,
+ active_workspace,
+ n_workspaces,
+ func, data);
+}
+
+void
+meta_ui_window_menu_popup (MetaWindowMenu *menu,
+ int root_x,
+ int root_y,
+ int button,
+ guint32 timestamp)
+{
+ meta_window_menu_popup (menu, root_x, root_y, button, timestamp);
+}
+
+void
+meta_ui_window_menu_free (MetaWindowMenu *menu)
+{
+ meta_window_menu_free (menu);
+}
diff --git a/src/ui.h b/src/ui.h
index b30b2f3fa..9ec9bdeec 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -71,4 +71,21 @@ void meta_ui_set_frame_title (MetaUI *ui,
Window xwindow,
const char *title);
+MetaWindowMenu* meta_ui_window_menu_new (MetaUI *ui,
+ Window client_xwindow,
+ MetaMenuOp ops,
+ MetaMenuOp insensitive,
+ int active_workspace,
+ int n_workspaces,
+ MetaWindowMenuFunc func,
+ gpointer data);
+void meta_ui_window_menu_popup (MetaWindowMenu *menu,
+ int root_x,
+ int root_y,
+ int button,
+ guint32 timestamp);
+void meta_ui_window_menu_free (MetaWindowMenu *menu);
+
+
+
#endif
diff --git a/src/window.c b/src/window.c
index 92bd88a19..0fc1c9e31 100644
--- a/src/window.c
+++ b/src/window.c
@@ -25,6 +25,8 @@
#include "errors.h"
#include "workspace.h"
#include "stack.h"
+#include "keybindings.h"
+#include "ui.h"
#include <X11/Xatom.h>
@@ -210,6 +212,8 @@ meta_window_new (MetaDisplay *display, Window xwindow,
window->placed = window->mapped;
window->unmanaging = FALSE;
window->calc_showing_queued = FALSE;
+ window->keys_grabbed = FALSE;
+ window->grab_on_frame = FALSE;
window->unmaps_pending = 0;
@@ -259,16 +263,19 @@ meta_window_new (MetaDisplay *display, Window xwindow,
window->minimized = TRUE;
meta_verbose ("Window %s asked to start out minimized\n", window->desc);
}
-
+
/* FIXME we have a tendency to set this then immediately
* change it again.
*/
set_wm_state (window, window->iconic ? IconicState : NormalState);
set_net_wm_state (window);
-
+
+ /* keys grab on client window if no frame */
if (window->decorated)
meta_window_ensure_frame (window);
+ meta_window_grab_keys (window);
+
space =
meta_display_get_workspace_by_screen_index (window->display,
window->screen,
@@ -321,6 +328,9 @@ meta_window_free (MetaWindow *window)
meta_verbose ("Unmanaging 0x%lx\n", window->xwindow);
window->unmanaging = TRUE;
+
+ if (window->display->focus_window == window)
+ window->display->focus_window = NULL;
meta_window_unqueue_calc_showing (window);
@@ -343,12 +353,15 @@ meta_window_free (MetaWindow *window)
/* FIXME restore original size if window has maximized */
- set_wm_state (window, WithdrawnState);
-
- meta_display_unregister_x_window (window->display, window->xwindow);
+ set_wm_state (window, WithdrawnState);
+
+ if (window->frame)
+ meta_window_destroy_frame (window);
- meta_window_destroy_frame (window);
+ meta_window_ungrab_keys (window);
+ meta_display_unregister_x_window (window->display, window->xwindow);
+
/* Put back anything we messed up */
meta_error_trap_push (window->display);
if (window->border_width != 0)
@@ -698,9 +711,13 @@ meta_window_unmaximize (MetaWindow *window)
void
meta_window_shade (MetaWindow *window)
{
+ meta_verbose ("Shading %s\n", window->desc);
if (!window->shaded)
{
window->shaded = TRUE;
+
+ meta_window_focus (window, CurrentTime);
+
meta_window_queue_move_resize (window);
meta_window_queue_calc_showing (window);
@@ -711,6 +728,7 @@ meta_window_shade (MetaWindow *window)
void
meta_window_unshade (MetaWindow *window)
{
+ meta_verbose ("Unshading %s\n", window->desc);
if (window->shaded)
{
window->shaded = FALSE;
@@ -1153,24 +1171,41 @@ meta_window_focus (MetaWindow *window,
meta_verbose ("Setting input focus to window %s, input: %d take_focus: %d\n",
window->desc, window->input, window->take_focus);
- meta_error_trap_push (window->display);
-
- if (window->input)
+ if (window->shaded && window->frame)
{
- XSetInputFocus (window->display->xdisplay,
- window->xwindow,
- RevertToPointerRoot,
- timestamp);
+ /* This is so we can still use keyboard shortcuts
+ * and still draw the window as focused.
+ */
+ if (window->frame)
+ {
+ meta_verbose ("Focusing frame of %s\n", window->desc);
+ XSetInputFocus (window->display->xdisplay,
+ window->frame->xwindow,
+ RevertToPointerRoot,
+ CurrentTime);
+ }
}
-
- if (window->take_focus)
+ else
{
- meta_window_send_icccm_message (window,
- window->display->atom_wm_take_focus,
- timestamp);
+ meta_error_trap_push (window->display);
+
+ if (window->input)
+ {
+ XSetInputFocus (window->display->xdisplay,
+ window->xwindow,
+ RevertToPointerRoot,
+ timestamp);
+ }
+
+ if (window->take_focus)
+ {
+ meta_window_send_icccm_message (window,
+ window->display->atom_wm_take_focus,
+ timestamp);
+ }
+
+ meta_error_trap_pop (window->display);
}
-
- meta_error_trap_pop (window->display);
}
void
@@ -1504,6 +1539,34 @@ meta_window_client_message (MetaWindow *window,
return FALSE;
}
+gboolean
+meta_window_notify_focus (MetaWindow *window,
+ XEvent *event)
+{
+ /* note the event can be on either the window or the frame,
+ * we focus the frame for shaded windows
+ */
+
+ if (event->type == FocusIn)
+ {
+ if (window != window->display->focus_window)
+ window->display->focus_window = window;
+ window->has_focus = TRUE;
+ if (window->frame)
+ meta_frame_queue_draw (window->frame);
+ }
+ else if (event->type == FocusOut)
+ {
+ if (window == window->display->focus_window)
+ window->display->focus_window = NULL;
+ window->has_focus = FALSE;
+ if (window->frame)
+ meta_frame_queue_draw (window->frame);
+ }
+
+ return FALSE;
+}
+
static gboolean
process_property_notify (MetaWindow *window,
XPropertyEvent *event)
@@ -2797,3 +2860,144 @@ constrain_position (MetaWindow *window,
*new_x = x;
*new_y = y;
}
+
+static void
+menu_callback (MetaWindowMenu *menu,
+ Display *xdisplay,
+ Window client_xwindow,
+ MetaMenuOp op,
+ int workspace_index,
+ gpointer data)
+{
+ MetaDisplay *display;
+ MetaWindow *window;
+
+ display = meta_display_for_x_display (xdisplay);
+ window = meta_display_lookup_x_window (display, client_xwindow);
+
+ if (window != NULL) /* window can be NULL */
+ {
+ meta_verbose ("Menu op %d on %s\n", op, window->desc);
+
+ /* op can be 0 for none */
+ switch (op)
+ {
+ case META_MENU_OP_DELETE:
+ meta_window_delete (window, CurrentTime);
+ break;
+
+ case META_MENU_OP_MINIMIZE:
+ meta_window_minimize (window);
+ break;
+
+ case META_MENU_OP_UNMAXIMIZE:
+ meta_window_unmaximize (window);
+ break;
+
+ case META_MENU_OP_MAXIMIZE:
+ meta_window_maximize (window);
+ break;
+
+ case META_MENU_OP_UNSHADE:
+ meta_window_unshade (window);
+ break;
+
+ case META_MENU_OP_SHADE:
+ meta_window_shade (window);
+ break;
+
+ case META_MENU_OP_WORKSPACES:
+ {
+ MetaWorkspace *workspace;
+
+ workspace =
+ meta_display_get_workspace_by_screen_index (window->display,
+ window->screen,
+ workspace_index);
+
+ if (workspace)
+ meta_window_change_workspace (window,
+ workspace);
+ else
+ meta_warning ("Workspace %d doesn't exist\n", workspace_index);
+ }
+ break;
+
+ case META_MENU_OP_STICK:
+ meta_window_stick (window);
+ break;
+
+ case META_MENU_OP_UNSTICK:
+ meta_window_unstick (window);
+ break;
+
+ case 0:
+ /* nothing */
+ break;
+
+ default:
+ meta_warning (G_STRLOC": Unknown window op\n");
+ break;
+ }
+ }
+ else
+ {
+ meta_verbose ("Menu callback on nonexistent window\n");
+ }
+
+ meta_ui_window_menu_free (menu);
+}
+
+void
+meta_window_show_menu (MetaWindow *window,
+ int root_x,
+ int root_y,
+ int button,
+ Time timestamp)
+{
+ MetaMenuOp ops;
+ MetaMenuOp insensitive;
+ MetaWindowMenu *menu;
+
+ ops = 0;
+ insensitive = 0;
+
+ ops |= (META_MENU_OP_DELETE | META_MENU_OP_WORKSPACES | META_MENU_OP_MINIMIZE);
+
+ if (window->maximized)
+ ops |= META_MENU_OP_UNMAXIMIZE;
+ else
+ ops |= META_MENU_OP_MAXIMIZE;
+
+ if (!window->has_maximize_func)
+ insensitive |= META_MENU_OP_UNMAXIMIZE | META_MENU_OP_MAXIMIZE;
+
+ if (window->shaded)
+ ops |= META_MENU_OP_UNSHADE;
+ else
+ ops |= META_MENU_OP_SHADE;
+
+ if (window->on_all_workspaces)
+ ops |= META_MENU_OP_UNSTICK;
+ else
+ ops |= META_MENU_OP_STICK;
+
+ if (!window->has_minimize_func)
+ insensitive |= META_MENU_OP_MINIMIZE;
+
+ if (!window->has_close_func)
+ insensitive |= META_MENU_OP_DELETE;
+
+ menu =
+ meta_ui_window_menu_new (window->screen->ui,
+ window->xwindow,
+ ops,
+ insensitive,
+ meta_window_get_net_wm_desktop (window),
+ meta_screen_get_n_workspaces (window->screen),
+ menu_callback,
+ NULL);
+
+ meta_verbose ("Popping up window menu for %s\n", window->desc);
+ meta_ui_window_menu_popup (menu, root_x, root_y, button, timestamp);
+}
diff --git a/src/window.h b/src/window.h
index 98f50ece4..d6351d47d 100644
--- a/src/window.h
+++ b/src/window.h
@@ -139,6 +139,10 @@ struct _MetaWindow
/* Are we in the calc_showing queue? */
guint calc_showing_queued : 1;
+
+ /* Used by keybindings.c */
+ guint keys_grabbed : 1;
+ guint grab_on_frame : 1;
/* Number of UnmapNotify that are caused by us, if
* we get UnmapNotify with none pending then the client
@@ -227,8 +231,17 @@ gboolean meta_window_property_notify (MetaWindow *window,
XEvent *event);
gboolean meta_window_client_message (MetaWindow *window,
XEvent *event);
+gboolean meta_window_notify_focus (MetaWindow *window,
+ XEvent *event);
int meta_window_set_current_workspace_hint (MetaWindow *window);
unsigned long meta_window_get_net_wm_desktop (MetaWindow *window);
+
+void meta_window_show_menu (MetaWindow *window,
+ int root_x,
+ int root_y,
+ int button,
+ Time timestamp);
+
#endif