diff --git a/ChangeLog b/ChangeLog index 80b5c0673..9fcbdb9a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2003-06-12 Havoc Pennington + + * src/display.c (event_callback): make raise-on-click explicitly + only happen in click to focus mode. + + * src/window.c (update_move): apply patch from Jurg Billeter to + allow you to "shake loose" maximized windows and move them between + Xinerama heads. #93586 + + * src/display.c: delete event_queue_callback + + * src/display.h (struct _MetaDisplay): get rid of + grab_current_window_pos and grab_current_root_[xy] as I could find + absolutely no code using them for anything. They were just sort of + randomly assigned to for no apparent reason. + + * src/display.c (event_callback): double-click timeout is per + screen, so get the screen and pass screen->ui to + meta_ui_get_double_click_timeout() + + * src/ui.c (meta_ui_get_double_click_timeout): take a MetaUI + argument so we get the right settings for each screen + (meta_ui_get_drag_threshold): new function + 2003-06-09 Rob Adams Revamp placement policy for windows that are maximized when they diff --git a/src/display.c b/src/display.c index a9e3f30ef..764d5ee99 100644 --- a/src/display.c +++ b/src/display.c @@ -77,8 +77,6 @@ static GSList *all_displays = NULL; static void meta_spew_event (MetaDisplay *display, XEvent *event); -static void event_queue_callback (XEvent *event, - gpointer data); static gboolean event_callback (XEvent *event, gpointer data); static Window event_get_modified_window (MetaDisplay *display, @@ -898,14 +896,6 @@ meta_display_is_double_click (MetaDisplay *display) static gboolean dump_events = TRUE; - -static void -event_queue_callback (XEvent *event, - gpointer data) -{ - event_callback (event, data); -} - static gboolean grab_op_is_mouse (MetaGrabOp op) { @@ -1119,6 +1109,28 @@ window_raise_with_delay_callback (void *data) return FALSE; } +static int +double_click_timeout_for_event (MetaDisplay *display, + XEvent *event) +{ + MetaScreen *screen; + + g_assert (event->type == ButtonPress || + event->type == ButtonRelease); + + screen = meta_display_screen_for_root (display, + event->xbutton.root); + if (screen == NULL) + { + /* Odd, we aren't managing this screen */ + meta_warning ("Received button event on root 0x%lx we aren't managing\n", + event->xbutton.root); + return 250; /* make up number */ + } + + return meta_ui_get_double_click_timeout (screen->ui); +} + static gboolean event_callback (XEvent *event, gpointer data) @@ -1154,7 +1166,9 @@ event_callback (XEvent *event, /* mark double click events, kind of a hack, oh well. */ if (((int)event->xbutton.button) == display->last_button_num && event->xbutton.window == display->last_button_xwindow && - event->xbutton.time < (display->last_button_time + meta_ui_get_double_click_timeout ())) + event->xbutton.time < (display->last_button_time + + double_click_timeout_for_event (display, + event))) { display->is_double_click = TRUE; meta_topic (META_DEBUG_EVENTS, @@ -1321,12 +1335,20 @@ event_callback (XEvent *event, * frames.c or special-cased if the click was on a * minimize/close button. */ - meta_window_raise (window); - - meta_topic (META_DEBUG_FOCUS, - "Focusing %s due to unmodified button %d press (display.c)\n", - window->desc, event->xbutton.button); - meta_window_focus (window, event->xbutton.time); + if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK) + { + meta_window_raise (window); + + meta_topic (META_DEBUG_FOCUS, + "Focusing %s due to unmodified button %d press (display.c)\n", + window->desc, event->xbutton.button); + meta_window_focus (window, event->xbutton.time); + } + else + { + meta_topic (META_DEBUG_FOCUS, + "Not raising/focusing window on click due to mouse/sloppy focus mode\n"); + } } /* you can move on alt-click but not on @@ -2823,8 +2845,6 @@ meta_display_begin_grab_op (MetaDisplay *display, display->grab_mask = modmask; display->grab_initial_root_x = root_x; display->grab_initial_root_y = root_y; - display->grab_current_root_x = root_x; - display->grab_current_root_y = root_y; display->grab_latest_motion_x = root_x; display->grab_latest_motion_y = root_y; display->grab_last_moveresize_time.tv_sec = 0; @@ -2840,7 +2860,6 @@ meta_display_begin_grab_op (MetaDisplay *display, meta_window_get_position (display->grab_window, &display->grab_initial_window_pos.x, &display->grab_initial_window_pos.y); - display->grab_current_window_pos = display->grab_initial_window_pos; #ifdef HAVE_XSYNC if (meta_grab_op_is_resizing (display->grab_op) && @@ -2930,6 +2949,9 @@ meta_display_end_grab_op (MetaDisplay *display, if (display->grab_op == META_GRAB_OP_NONE) return; + if (display->grab_window != NULL) + display->grab_window->shaken_loose = FALSE; + 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_ESCAPING_NORMAL || diff --git a/src/display.h b/src/display.h index 65f43b130..cea930036 100644 --- a/src/display.h +++ b/src/display.h @@ -237,15 +237,12 @@ struct _MetaDisplay int grab_button; int grab_initial_root_x; int grab_initial_root_y; - int grab_current_root_x; - int grab_current_root_y; int grab_latest_motion_x; int grab_latest_motion_y; gulong grab_mask; guint grab_have_pointer : 1; guint grab_have_keyboard : 1; MetaRectangle grab_initial_window_pos; - MetaRectangle grab_current_window_pos; MetaResizePopup *grab_resize_popup; GTimeVal grab_last_moveresize_time; Time grab_motion_notify_time; diff --git a/src/ui.c b/src/ui.c index 1a668dde9..eff54f27e 100644 --- a/src/ui.c +++ b/src/ui.c @@ -767,21 +767,29 @@ meta_stock_icons_init (void) } int -meta_ui_get_double_click_timeout (void) +meta_ui_get_double_click_timeout (MetaUI *ui) { GtkSettings *settings; - GObjectClass *klass; - int timeout = 0; + int timeout; - settings = gtk_settings_get_default (); - - klass = G_OBJECT_CLASS (GTK_SETTINGS_GET_CLASS (settings)); - if (g_object_class_find_property (klass, "gtk-double-click-time") == NULL) - { - return 250; - } + settings = gtk_widget_get_settings (GTK_WIDGET (ui->frames)); + timeout = 250; g_object_get (G_OBJECT (settings), "gtk-double-click-time", &timeout, NULL); return timeout; } + +int +meta_ui_get_drag_threshold (MetaUI *ui) +{ + GtkSettings *settings; + int threshold; + + settings = gtk_widget_get_settings (GTK_WIDGET (ui->frames)); + + threshold = 8; + g_object_get (G_OBJECT (settings), "gtk-dnd-drag-threshold", &threshold, NULL); + + return threshold; +} diff --git a/src/ui.h b/src/ui.h index 171c342d1..6ed690416 100644 --- a/src/ui.h +++ b/src/ui.h @@ -165,7 +165,8 @@ gboolean meta_ui_parse_modifier (const char *accel, gboolean meta_ui_window_is_widget (MetaUI *ui, Window xwindow); -int meta_ui_get_double_click_timeout (void); +int meta_ui_get_double_click_timeout (MetaUI *ui); +int meta_ui_get_drag_threshold (MetaUI *ui); #include "tabpopup.h" diff --git a/src/window.c b/src/window.c index 31af946ba..565c31dd5 100644 --- a/src/window.c +++ b/src/window.c @@ -440,6 +440,7 @@ meta_window_new (MetaDisplay *display, window->withdrawn = FALSE; window->initial_workspace_set = FALSE; window->calc_placement = FALSE; + window->shaken_loose = FALSE; window->unmaps_pending = 0; @@ -5693,15 +5694,95 @@ update_move (MetaWindow *window, { int dx, dy; int new_x, new_y; - + int shake_threshold; + window->display->grab_latest_motion_x = x; window->display->grab_latest_motion_y = y; - dx = x - window->display->grab_current_root_x; - dy = y - window->display->grab_current_root_y; + dx = x - window->display->grab_initial_root_x; + dy = y - window->display->grab_initial_root_y; - new_x = window->display->grab_current_window_pos.x + dx; - new_y = window->display->grab_current_window_pos.y + dy; + new_x = window->display->grab_initial_window_pos.x + dx; + new_y = window->display->grab_initial_window_pos.y + dy; + + /* shake loose (unmaximize) maximized window if dragged beyond the threshold + * in the Y direction. You can't pull a window loose via X motion. + */ + +#define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 6 + shake_threshold = meta_ui_get_drag_threshold (window->screen->ui) * + DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR; + + if (window->maximized && ABS (dy) >= shake_threshold) + { + /* Shake loose */ + + window->shaken_loose = TRUE; + + /* Unmaximize at wherever the window would have moved to if it + * hadn't been maximized. FIXME if you grab the right side of + * the titlebar then on unmaximize the pointer isn't on the + * titlebar which is kind of odd. + */ + window->saved_rect.x = new_x; + window->saved_rect.y = new_y; + + meta_window_unmaximize (window); + + return; + } + /* remaximize window on an other xinerama monitor if window has + * been shaken loose or it is still maximized (then move straight) + */ + else if (window->shaken_loose || window->maximized) + { + const MetaXineramaScreenInfo *wxinerama; + int monitor; + + wxinerama = meta_screen_get_xinerama_for_window (window->screen, window); + + for (monitor = 0; monitor < window->screen->n_xinerama_infos; monitor++) + { + /* FIXME this should check near the top of the work area probably, + * maybe only counting full-monitor-width panels in work area + * for this purpose. + */ + /* check if cursor is near the top of a xinerama monitor */ + if (x >= window->screen->xinerama_infos[monitor].x_origin && + x < (window->screen->xinerama_infos[monitor].x_origin + + window->screen->xinerama_infos[monitor].width) && + y >= window->screen->xinerama_infos[monitor].y_origin && + y < (window->screen->xinerama_infos[monitor].y_origin + shake_threshold)) + { + /* move the saved rect if window will become maximized on an + * other monitor so user isn't surprised on a later unmaximize + */ + if (wxinerama->number != monitor) + { + window->saved_rect.x = window->screen->xinerama_infos[monitor].x_origin; + window->saved_rect.y = window->screen->xinerama_infos[monitor].y_origin; + + if (window->frame) + { + window->saved_rect.x += window->frame->child_x; + window->saved_rect.y += window->frame->child_y; + } + + meta_window_unmaximize (window); + } + + window->shaken_loose = FALSE; + + meta_window_maximize (window); + + return; + } + } + } + + /* don't allow a maximized window to move */ + if (window->maximized) + return; if (mask & ShiftMask) { @@ -5725,11 +5806,11 @@ update_resize (MetaWindow *window, window->display->grab_latest_motion_x = x; window->display->grab_latest_motion_y = y; - dx = x - window->display->grab_current_root_x; - dy = y - window->display->grab_current_root_y; + dx = x - window->display->grab_initial_root_x; + dy = y - window->display->grab_initial_root_y; - new_w = window->display->grab_current_window_pos.width; - new_h = window->display->grab_current_window_pos.height; + new_w = window->display->grab_initial_window_pos.width; + new_h = window->display->grab_initial_window_pos.height; switch (window->display->grab_op) { @@ -6491,15 +6572,21 @@ meta_window_update_resize_grab_op (MetaWindow *window, int x, y, x_offset, y_offset; meta_window_get_position (window, &x, &y); - + warp_pointer (window, window->display->grab_op, &x_offset, &y_offset); - window->display->grab_current_root_x = x + x_offset; - window->display->grab_current_root_y = y + y_offset; - - if (window->display->grab_window) - window->display->grab_current_window_pos = window->rect; - + /* As we warped the pointer, we have to reset the apparent + * initial window state, since if the mouse moves we want + * to use those events to do the right thing. + */ + if (window->display->grab_window == window) + { + window->display->grab_initial_root_x = x + x_offset; + window->display->grab_initial_root_y = y + y_offset; + + window->display->grab_initial_window_pos = window->rect; + } + if (update_cursor) { meta_display_set_grab_op_cursor (window->display, diff --git a/src/window.h b/src/window.h index f9353d1ec..5477367a9 100644 --- a/src/window.h +++ b/src/window.h @@ -229,6 +229,9 @@ struct _MetaWindow /* icon props have changed */ guint need_reread_icon : 1; + /* if TRUE, window was maximized at start of current grab op */ + guint shaken_loose : 1; + #ifdef HAVE_XSYNC /* XSync update counter */ XSyncCounter update_counter; @@ -288,7 +291,11 @@ struct _MetaWindow MetaGroup *group; }; -#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->maximized && !(w)->fullscreen) +/* These differ from window->has_foo_func in that they consider + * the dynamic window state such as "maximized", not just the + * window's type + */ +#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen) #define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !(w)->maximized && !(w)->fullscreen && !(w)->shaded) #define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \ (((w)->size_hints.min_width < (w)->size_hints.max_width) || \