Commit 71d3333d authored by rhp's avatar rhp
Browse files

...

parent 8a2841a8
......@@ -53,7 +53,9 @@ typedef enum
META_MENU_OP_SHADE = 1 << 5,
META_MENU_OP_UNSTICK = 1 << 6,
META_MENU_OP_STICK = 1 << 7,
META_MENU_OP_WORKSPACES = 1 << 8
META_MENU_OP_WORKSPACES = 1 << 8,
META_MENU_OP_MOVE = 1 << 9,
META_MENU_OP_RESIZE = 1 << 10
} MetaMenuOp;
typedef struct _MetaWindowMenu MetaWindowMenu;
......@@ -65,4 +67,28 @@ typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu,
int workspace,
gpointer data);
typedef enum
{
META_GRAB_OP_NONE,
META_GRAB_OP_MOVING,
META_GRAB_OP_RESIZING_SE,
META_GRAB_OP_RESIZING_S,
META_GRAB_OP_RESIZING_SW,
META_GRAB_OP_RESIZING_N,
META_GRAB_OP_RESIZING_NE,
META_GRAB_OP_RESIZING_NW,
META_GRAB_OP_RESIZING_W,
META_GRAB_OP_RESIZING_E,
META_GRAB_OP_KEYBOARD_MOVING,
META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN,
META_GRAB_OP_KEYBOARD_RESIZING_S,
META_GRAB_OP_KEYBOARD_RESIZING_N,
META_GRAB_OP_KEYBOARD_RESIZING_W,
META_GRAB_OP_KEYBOARD_RESIZING_E
} MetaGrabOp;
#endif
......@@ -131,6 +131,23 @@ meta_core_user_raise (Display *xdisplay,
meta_window_raise (window);
}
void
meta_core_user_focus (Display *xdisplay,
Window frame_xwindow,
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_focus (window, timestamp);
}
void
meta_core_get_position (Display *xdisplay,
Window frame_xwindow,
......
......@@ -53,6 +53,10 @@ void meta_core_user_resize (Display *xdisplay,
void meta_core_user_raise (Display *xdisplay,
Window frame_xwindow);
void meta_core_user_focus (Display *xdisplay,
Window frame_xwindow,
Time timestamp);
/* get position of client, same coord space expected by move */
void meta_core_get_position (Display *xdisplay,
Window frame_xwindow,
......
......@@ -277,6 +277,9 @@ meta_display_open (const char *name)
display->last_button_num = 0;
display->is_double_click = FALSE;
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
set_string_hint (display,
display->leader_window,
display->atom_net_wm_name,
......@@ -558,6 +561,7 @@ event_callback (XEvent *event,
MetaWindow *window;
MetaDisplay *display;
Window modified;
gboolean frame_was_receiver;
display = data;
......@@ -590,31 +594,35 @@ event_callback (XEvent *event,
window = meta_display_lookup_x_window (display, modified);
else
window = NULL;
frame_was_receiver = FALSE;
if (window &&
window->frame &&
modified == window->frame->xwindow)
{
meta_frame_event (window->frame, event);
return FALSE;
}
frame_was_receiver = TRUE;
switch (event->type)
{
case KeyPress:
case KeyRelease:
meta_display_process_key_event (display, window, event);
if (window)
meta_display_process_key_event (display, window, event);
break;
case ButtonPress:
if (display->grab_op != META_GRAB_OP_NONE)
{
meta_verbose ("Ending grab op %d on window %s due to button press\n",
display->grab_op,
display->grab_window->desc);
meta_display_end_grab_op (display,
event->xbutton.time);
}
break;
case ButtonRelease:
break;
case MotionNotify:
break;
case EnterNotify:
/* We handle it here if an undecorated window
* is involved, otherwise we handle it in frame.c
*/
/* do this even if window->has_focus to avoid races */
if (window)
meta_window_focus (window, event->xcrossing.time);
......@@ -640,10 +648,23 @@ event_callback (XEvent *event,
break;
case DestroyNotify:
if (window)
meta_window_free (window); /* Unmanage destroyed window */
{
if (frame_was_receiver)
{
meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n",
window->frame->xwindow);
meta_error_trap_push (display);
meta_window_destroy_frame (window->frame->window);
meta_error_trap_pop (display);
}
else
{
meta_window_free (window); /* Unmanage destroyed window */
}
}
break;
case UnmapNotify:
if (window)
if (!frame_was_receiver && window)
{
if (window->unmaps_pending == 0)
{
......@@ -664,8 +685,12 @@ event_callback (XEvent *event,
break;
case MapRequest:
if (window == NULL)
window = meta_window_new (display, event->xmaprequest.window, FALSE);
else if (window)
{
window = meta_window_new (display, event->xmaprequest.window,
FALSE);
}
/* if frame was receiver it's some malicious send event or something */
else if (!frame_was_receiver && window)
{
if (window->minimized)
meta_window_unminimize (window);
......@@ -704,7 +729,8 @@ event_callback (XEvent *event,
}
else
{
meta_window_configure_request (window, event);
if (!frame_was_receiver)
meta_window_configure_request (window, event);
}
break;
case GravityNotify:
......@@ -716,7 +742,7 @@ event_callback (XEvent *event,
case CirculateRequest:
break;
case PropertyNotify:
if (window)
if (window && !frame_was_receiver)
meta_window_property_notify (window, event);
break;
case SelectionClear:
......@@ -730,7 +756,8 @@ event_callback (XEvent *event,
case ClientMessage:
if (window)
{
meta_window_client_message (window, event);
if (!frame_was_receiver)
meta_window_client_message (window, event);
}
else
{
......@@ -919,7 +946,7 @@ meta_spew_event (MetaDisplay *display,
switch (event->type)
{
case KeyPress:
name = "KeyPress";
name = "KeyPress";
break;
case KeyRelease:
name = "KeyRelease";
......@@ -1180,3 +1207,112 @@ meta_display_get_workspace_by_screen_index (MetaDisplay *display,
return NULL;
}
gboolean
meta_display_begin_grab_op (MetaDisplay *display,
MetaWindow *window,
MetaGrabOp op,
gboolean pointer_already_grabbed,
int button,
gulong modmask,
Cursor cursor,
Time timestamp,
int root_x,
int root_y)
{
Window grabwindow;
meta_verbose ("Doing grab op %d on window %s button %d pointer already grabbed: %d\n",
op, window->desc, button, pointer_already_grabbed);
grabwindow = window->frame ? window->frame->xwindow : window->xwindow;
if (display->grab_op != META_GRAB_OP_NONE)
{
meta_warning ("Attempt to perform window operation %d on window %s when operation %d on %s already in effect\n",
op, window->desc, display->grab_op, display->grab_window->desc);
return FALSE;
}
if (pointer_already_grabbed)
{
display->grab_have_pointer = TRUE;
}
else
{
meta_error_trap_push (display);
if (XGrabPointer (display->xdisplay,
grabwindow,
False,
PointerMotionMask | PointerMotionHintMask |
ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask,
GrabModeAsync, GrabModeAsync,
None,
cursor,
timestamp) == GrabSuccess)
display->grab_have_pointer = TRUE;
meta_error_trap_pop (display);
}
if (!display->grab_have_pointer)
{
meta_verbose ("XGrabPointer() failed\n");
return FALSE;
}
switch (op)
{
case META_GRAB_OP_KEYBOARD_MOVING:
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
case META_GRAB_OP_KEYBOARD_RESIZING_S:
case META_GRAB_OP_KEYBOARD_RESIZING_N:
case META_GRAB_OP_KEYBOARD_RESIZING_W:
case META_GRAB_OP_KEYBOARD_RESIZING_E:
if (meta_window_grab_all_keys (window))
display->grab_have_keyboard = TRUE;
if (!display->grab_have_keyboard)
{
meta_verbose ("XGrabKeyboard() failed\n");
return FALSE;
}
break;
default:
/* non-keyboard grab ops */
break;
}
display->grab_op = op;
display->grab_window = window;
display->grab_button = button;
display->grab_root_x = root_x;
display->grab_root_y = root_y;
meta_verbose ("Grab op %d on window %s successful\n",
display->grab_op, display->grab_window->desc);
g_assert (display->grab_window != NULL);
g_assert (display->grab_op != META_GRAB_OP_NONE);
return TRUE;
}
void
meta_display_end_grab_op (MetaDisplay *display,
Time timestamp)
{
if (display->grab_op == META_GRAB_OP_NONE)
return;
if (display->grab_have_pointer)
XUngrabPointer (display->xdisplay, timestamp);
if (display->grab_have_keyboard)
meta_window_ungrab_all_keys (display->grab_window);
display->grab_window = NULL;
display->grab_op = META_GRAB_OP_NONE;
}
......@@ -25,6 +25,7 @@
#include <glib.h>
#include <X11/Xlib.h>
#include "eventqueue.h"
#include "common.h"
/* this doesn't really belong here, oh well. */
typedef struct _MetaRectangle MetaRectangle;
......@@ -118,6 +119,16 @@ struct _MetaDisplay
Window last_button_xwindow;
int last_button_num;
guint is_double_click : 1;
/* current window operation */
MetaGrabOp grab_op;
MetaWindow *grab_window;
int grab_button;
int grab_root_x;
int grab_root_y;
gulong grab_mask;
guint grab_have_pointer : 1;
guint grab_have_keyboard : 1;
};
gboolean meta_display_open (const char *name);
......@@ -151,5 +162,19 @@ MetaWorkspace* meta_display_get_workspace_by_index (MetaDisplay *displa
MetaWorkspace* meta_display_get_workspace_by_screen_index (MetaDisplay *display,
MetaScreen *screen,
int index);
gboolean meta_display_begin_grab_op (MetaDisplay *display,
MetaWindow *window,
MetaGrabOp op,
gboolean pointer_already_grabbed,
int button,
gulong modmask,
Cursor cursor,
Time timestamp,
int root_x,
int root_y);
void meta_display_end_grab_op (MetaDisplay *display,
Time timestamp);
#endif
......@@ -284,100 +284,3 @@ meta_frame_queue_draw (MetaFrame *frame)
meta_ui_queue_frame_draw (frame->window->screen->ui,
frame->xwindow);
}
gboolean
meta_frame_event (MetaFrame *frame,
XEvent *event)
{
switch (event->type)
{
case KeyPress:
case KeyRelease:
meta_display_process_key_event (frame->window->display,
frame->window, event);
break;
case ButtonPress:
break;
case ButtonRelease:
break;
case MotionNotify:
break;
case EnterNotify:
/* We handle it here if a decorated window
* is involved, otherwise we handle it in display.c
*/
/* do this even if window->has_focus to avoid races */
meta_window_focus (frame->window,
event->xcrossing.time);
break;
case LeaveNotify:
break;
case FocusIn:
case FocusOut:
meta_window_notify_focus (frame->window,
event);
break;
case KeymapNotify:
break;
case Expose:
break;
case GraphicsExpose:
break;
case NoExpose:
break;
case VisibilityNotify:
break;
case CreateNotify:
break;
case DestroyNotify:
{
MetaDisplay *display;
meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug\n", frame->xwindow);
display = frame->window->display;
meta_error_trap_push (display);
meta_window_destroy_frame (frame->window);
meta_error_trap_pop (display);
return TRUE;
}
break;
case UnmapNotify:
break;
case MapNotify:
break;
case MapRequest:
break;
case ReparentNotify:
break;
case ConfigureNotify:
break;
case ConfigureRequest:
break;
case GravityNotify:
break;
case ResizeRequest:
break;
case CirculateNotify:
break;
case CirculateRequest:
break;
case PropertyNotify:
break;
case SelectionClear:
break;
case SelectionRequest:
break;
case SelectionNotify:
break;
case ColormapNotify:
break;
case ClientMessage:
break;
case MappingNotify:
break;
default:
break;
}
return FALSE;
}
......@@ -60,8 +60,6 @@ struct _MetaFrame
void meta_window_ensure_frame (MetaWindow *window);
void meta_window_destroy_frame (MetaWindow *window);
void meta_frame_queue_draw (MetaFrame *frame);
gboolean meta_frame_event (MetaFrame *frame,
XEvent *event);
MetaFrameFlags meta_frame_get_flags (MetaFrame *frame);
......
......@@ -1358,7 +1358,11 @@ meta_frames_button_press_event (GtkWidget *widget,
return FALSE; /* already up to something */
if (event->button == 1)
meta_core_user_raise (gdk_display, frame->xwindow);
{
meta_core_user_raise (gdk_display, frame->xwindow);
meta_core_user_focus (gdk_display, frame->xwindow,
event->time);
}
if (event->button == 1 &&
(control == META_FRAME_CONTROL_MAXIMIZE ||
......
......@@ -196,6 +196,9 @@ meta_screen_ungrab_keys (MetaScreen *screen)
void
meta_window_grab_keys (MetaWindow *window)
{
if (window->all_keys_grabbed)
return;
if (window->keys_grabbed)
{
if (window->frame && !window->grab_on_frame)
......@@ -235,16 +238,107 @@ meta_window_ungrab_keys (MetaWindow *window)
}
}
gboolean
meta_window_grab_all_keys (MetaWindow *window)
{
int result;
Window grabwindow;
if (window->all_keys_grabbed)
return FALSE;
if (window->keys_grabbed)
meta_window_ungrab_keys (window);
/* Make sure the window is focused, otherwise the grab
* won't do a lot of good.
*/
meta_window_focus (window, CurrentTime);
grabwindow = window->frame ? window->frame->xwindow : window->xwindow;
meta_error_trap_push (window->display);
XGrabKey (window->display->xdisplay, AnyKey, AnyModifier,
grabwindow, True,
GrabModeAsync, GrabModeAsync);
result = meta_error_trap_pop (window->display);
if (result != Success)
{
meta_verbose ("Global key grab failed for window %s\n", window->desc);
return FALSE;
}
else
{
window->keys_grabbed = FALSE;
window->all_keys_grabbed = TRUE;
window->grab_on_frame = window->frame != NULL;
return TRUE;
}
}
void
meta_window_ungrab_all_keys (MetaWindow *window)
{
if (window->all_keys_grabbed)
{
Window grabwindow;
grabwindow = (window->frame && window->grab_on_frame) ?
window->frame->xwindow : window->xwindow;
meta_error_trap_push (window->display);
XUngrabKey (window->display->xdisplay,
AnyKey, AnyModifier,
grabwindow);
meta_error_trap_pop (window->display);
window->grab_on_frame = FALSE;
window->all_keys_grabbed = FALSE;
window->keys_grabbed = FALSE;
/* Re-establish our standard bindings */
meta_window_grab_keys (window);
}
}
static gboolean
is_modifier (MetaDisplay *display,
unsigned int keycode)
{
int i;
int map_size;
XModifierKeymap *mod_keymap;
gboolean retval = FALSE;
/* FIXME this is ass-slow, cache the modmap */
mod_keymap = XGetModifierMapping (display->xdisplay);
map_size = 8 * mod_keymap->max_keypermod;
i = 0;
while (i < map_size) {
if (keycode == mod_keymap->modifiermap[i]) {
retval = TRUE;
break;
}
++i;
}
XFreeModifiermap (mod_keymap);
return retval;
}
static void
process_event (MetaKeyBinding *bindings,
MetaDisplay *display,
MetaWindow *window,
XEvent *event)
XEvent *event,
KeySym keysym)
{
KeySym keysym;
int i;
keysym = XKeycodeToKeysym (display->xdisplay, event->xkey.keycode, 0);
i = 0;
while (bindings[i].keysym != None)
......@@ -267,8 +361,102 @@ meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XEvent *event)
{
process_event (screen_bindings, display, window, event);
process_event (window_bindings, display, window, event);
KeySym keysym;
gboolean handled;