diff --git a/src/window.c b/src/window.c index cb079b97e..3136e060c 100644 --- a/src/window.c +++ b/src/window.c @@ -352,7 +352,8 @@ meta_window_new (MetaDisplay *display, Window xwindow, meta_window_ensure_frame (window); meta_window_grab_keys (window); - + meta_display_grab_window_buttons (window->display, window->xwindow); + /* For the workspace, first honor hints, * if that fails put transients with parents, * otherwise put window on active space @@ -506,7 +507,8 @@ meta_window_free (MetaWindow *window) meta_window_destroy_frame (window); meta_window_ungrab_keys (window); - + meta_display_ungrab_window_buttons (window->display, window->xwindow); + meta_display_unregister_x_window (window->display, window->xwindow); /* Put back anything we messed up */ @@ -1976,6 +1978,11 @@ meta_window_notify_focus (MetaWindow *window, /* note the event can be on either the window or the frame, * we focus the frame for shaded windows */ + + /* The event can be FocusIn, FocusOut, or UnmapNotify. + * On UnmapNotify we have to pretend it's focus out, + * because we won't get a focus out if it occurs, apparently. + */ /* We don't ever want to set prev_focus_window to NULL, * though it may be NULL due to e.g. only one window ever @@ -1991,8 +1998,10 @@ meta_window_notify_focus (MetaWindow *window, * and prev_focus_window gets confused from what the * user expects once a keybinding is used. */ - if (event->xfocus.mode == NotifyGrab || - event->xfocus.mode == NotifyUngrab) + if ((event->type == FocusIn || + event->type == FocusOut) && + (event->xfocus.mode == NotifyGrab || + event->xfocus.mode == NotifyUngrab)) { meta_verbose ("Ignoring focus event generated by a grab\n"); return TRUE; @@ -2016,11 +2025,12 @@ meta_window_notify_focus (MetaWindow *window, if (window->frame) meta_frame_queue_draw (window->frame); } - else if (event->type == FocusOut) + else if (event->type == FocusOut || + event->type == UnmapNotify) { if (window == window->display->focus_window) { - meta_verbose ("%s is now the previous focus window due to being focused out\n", + meta_verbose ("%s is now the previous focus window due to being focused out or unmapped\n", window->desc); window->display->prev_focus_window = window; @@ -3592,7 +3602,7 @@ menu_callback (MetaWindowMenu *menu, meta_display_begin_grab_op (window->display, window, META_GRAB_OP_KEYBOARD_MOVING, - FALSE, 0, 0, None, + FALSE, 0, 0, CurrentTime, 0, 0); break; @@ -3680,6 +3690,200 @@ meta_window_show_menu (MetaWindow *window, meta_ui_window_menu_popup (menu, root_x, root_y, button, timestamp); } +static void +window_query_root_pointer (MetaWindow *window, + int *x, int *y) +{ + Window root_return, child_return; + int root_x_return, root_y_return; + int win_x_return, win_y_return; + unsigned int mask_return; + + XQueryPointer (window->display->xdisplay, + window->xwindow, + &root_return, + &child_return, + &root_x_return, + &root_y_return, + &win_x_return, + &win_y_return, + &mask_return); + + if (x) + *x = root_x_return; + if (y) + *y = root_y_return; +} + +static void +update_move (MetaWindow *window, + int x, + int y) +{ + int dx, dy; + + dx = x - window->display->grab_root_x; + dy = y - window->display->grab_root_y; + + window->user_has_moved = TRUE; + meta_window_move (window, + window->display->grab_initial_window_pos.x + dx, + window->display->grab_initial_window_pos.y + dy); +} + +static void +update_resize (MetaWindow *window, + int x, int y) +{ + int dx, dy; + int new_w, new_h; + int gravity; + + dx = x - window->display->grab_root_x; + dy = y - window->display->grab_root_y; + + new_w = window->display->grab_initial_window_pos.width; + new_h = window->display->grab_initial_window_pos.height; + + switch (window->display->grab_op) + { + case META_GRAB_OP_RESIZING_SE: + case META_GRAB_OP_RESIZING_NE: + case META_GRAB_OP_RESIZING_E: + new_w += dx; + break; + + case META_GRAB_OP_RESIZING_NW: + case META_GRAB_OP_RESIZING_SW: + case META_GRAB_OP_RESIZING_W: + new_w -= dx; + break; + + default: + break; + } + + switch (window->display->grab_op) + { + case META_GRAB_OP_RESIZING_SE: + case META_GRAB_OP_RESIZING_S: + case META_GRAB_OP_RESIZING_SW: + new_h += dy; + break; + + case META_GRAB_OP_RESIZING_N: + case META_GRAB_OP_RESIZING_NE: + case META_GRAB_OP_RESIZING_NW: + new_h -= dy; + break; + default: + break; + } + + /* compute gravity of client during operation */ + gravity = -1; + switch (window->display->grab_op) + { + case META_GRAB_OP_RESIZING_SE: + gravity = NorthWestGravity; + break; + case META_GRAB_OP_RESIZING_S: + gravity = NorthGravity; + break; + case META_GRAB_OP_RESIZING_SW: + gravity = NorthEastGravity; + break; + case META_GRAB_OP_RESIZING_N: + gravity = SouthGravity; + break; + case META_GRAB_OP_RESIZING_NE: + gravity = SouthWestGravity; + break; + case META_GRAB_OP_RESIZING_NW: + gravity = SouthEastGravity; + break; + case META_GRAB_OP_RESIZING_E: + gravity = WestGravity; + break; + case META_GRAB_OP_RESIZING_W: + gravity = EastGravity; + break; + default: + g_assert_not_reached (); + break; + } + + window->user_has_resized = TRUE; + meta_window_resize_with_gravity (window, new_w, new_h, gravity); +} + +void +meta_window_handle_mouse_grab_op_event (MetaWindow *window, + XEvent *event) +{ + switch (event->type) + { + case ButtonRelease: + meta_display_end_grab_op (window->display, event->xbutton.time); + + switch (window->display->grab_op) + { + case META_GRAB_OP_MOVING: + update_move (window, event->xbutton.x_root, event->xbutton.y_root); + break; + + case META_GRAB_OP_RESIZING_E: + case META_GRAB_OP_RESIZING_W: + case META_GRAB_OP_RESIZING_S: + case META_GRAB_OP_RESIZING_N: + case META_GRAB_OP_RESIZING_SE: + case META_GRAB_OP_RESIZING_SW: + case META_GRAB_OP_RESIZING_NE: + case META_GRAB_OP_RESIZING_NW: + update_resize (window, event->xbutton.x_root, event->xbutton.y_root); + break; + + default: + break; + } + break; + + case MotionNotify: + switch (window->display->grab_op) + { + case META_GRAB_OP_MOVING: + { + int x, y; + window_query_root_pointer (window, &x, &y); + update_move (window, x, y); + } + break; + + case META_GRAB_OP_RESIZING_E: + case META_GRAB_OP_RESIZING_W: + case META_GRAB_OP_RESIZING_S: + case META_GRAB_OP_RESIZING_N: + case META_GRAB_OP_RESIZING_SE: + case META_GRAB_OP_RESIZING_SW: + case META_GRAB_OP_RESIZING_NE: + case META_GRAB_OP_RESIZING_NW: + { + int x, y; + window_query_root_pointer (window, &x, &y); + update_resize (window, x, y); + } + break; + + default: + break; + } + break; + + default: + break; + } +} + gboolean meta_window_shares_some_workspace (MetaWindow *window, MetaWindow *with)