diff --git a/ChangeLog b/ChangeLog index 21dd2c117..70588ad9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2002-05-23 Havoc Pennington + + Crack from Erwann + + * src/metacity.schemas: add autoraise crackrock + + * src/display.c (event_callback): autoraise window if autoraise is + enabled + + * src/prefs.c: autoraise crack + 2002-05-21 Havoc Pennington * src/window.c (constrain_position): fix positioning in fullscreen diff --git a/src/display.c b/src/display.c index a2f18e378..739a54500 100644 --- a/src/display.c +++ b/src/display.c @@ -37,7 +37,8 @@ #define USE_GDK_DISPLAY -typedef struct { +typedef struct +{ MetaDisplay *display; Window xwindow; Time timestamp; @@ -47,6 +48,12 @@ typedef struct { guint ping_timeout_id; } MetaPingData; +typedef struct +{ + MetaDisplay *display; + Window xwindow; +} MetaAutoRaiseData; + static GSList *all_displays = NULL; static void meta_spew_event (MetaDisplay *display, @@ -243,6 +250,7 @@ meta_display_open (const char *name) display->workspaces = NULL; display->pending_pings = NULL; + display->autoraise_timeout_id = 0; display->focus_window = NULL; display->mru_list = NULL; @@ -524,6 +532,12 @@ meta_display_close (MetaDisplay *display) g_slist_free (winlist); meta_display_ungrab (display); + if (display->autoraise_timeout_id != 0) + { + g_source_remove (display->autoraise_timeout_id); + display->autoraise_timeout_id = 0; + } + #ifdef USE_GDK_DISPLAY /* Stop caring about events */ meta_ui_remove_event_func (display->xdisplay, @@ -796,6 +810,61 @@ reset_ignores (MetaDisplay *display) display->ungrab_should_not_cause_focus_window = None; } +#define POINT_IN_RECT(xcoord, ycoord, rect) \ + ((xcoord) >= (rect).x && \ + (xcoord) < ((rect).x + (rect).width) && \ + (ycoord) >= (rect).y && \ + (ycoord) < ((rect).y + (rect).height)) + +static gboolean +window_raise_with_delay_callback (void *data) +{ + MetaWindow *window; + MetaAutoRaiseData *auto_raise; + + auto_raise = data; + + meta_topic (META_DEBUG_FOCUS, + "In autoraise callback for window 0x%lx\n", + auto_raise->xwindow); + + auto_raise->display->autoraise_timeout_id = 0; + + window = meta_display_lookup_x_window (auto_raise->display, + auto_raise->xwindow); + + if (window == NULL) + return FALSE; + + /* If we aren't already on top, check whether the pointer is inside + * the window and raise the window if so. + */ + if (meta_stack_get_top (window->screen->stack) != window) + { + int x, y, root_x, root_y; + Window root, child; + unsigned int mask; + gboolean same_screen; + + meta_error_trap_push (window->display); + same_screen = XQueryPointer (window->display->xdisplay, + window->xwindow, + &root, &child, + &root_x, &root_y, &x, &y, &mask); + meta_error_trap_pop (window->display); + + if ((window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) || + (window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect))) + meta_window_raise (window); + else + meta_topic (META_DEBUG_FOCUS, + "Pointer not inside window, not raising %s\n", + window->desc); + } + + return FALSE; +} + static gboolean event_callback (XEvent *event, gpointer data) @@ -1033,10 +1102,40 @@ event_callback (XEvent *event, meta_topic (META_DEBUG_FOCUS, "Focusing %s due to enter notify with serial %lu\n", window->desc, event->xany.serial); - meta_window_focus (window, event->xcrossing.time); - /* stop ignoring stuff */ - reset_ignores (display); + meta_window_focus (window, event->xcrossing.time); + + /* stop ignoring stuff */ + reset_ignores (display); + + if (meta_prefs_get_auto_raise ()) + { + MetaAutoRaiseData *auto_raise_data; + + meta_topic (META_DEBUG_FOCUS, + "Queuing an autoraise timeout for %s with delay %d\n", + window->desc, + meta_prefs_get_auto_raise_delay ()); + + auto_raise_data = g_new (MetaAutoRaiseData, 1); + auto_raise_data->display = window->display; + auto_raise_data->xwindow = window->xwindow; + + if (display->autoraise_timeout_id != 0) + g_source_remove (display->autoraise_timeout_id); + + display->autoraise_timeout_id = + g_timeout_add_full (G_PRIORITY_DEFAULT, + meta_prefs_get_auto_raise_delay (), + window_raise_with_delay_callback, + auto_raise_data, + g_free); + } + else + { + meta_topic (META_DEBUG_FOCUS, + "Auto raise is disabled\n"); + } } break; case META_FOCUS_MODE_CLICK: @@ -2823,3 +2922,4 @@ meta_resize_gravity_from_grab_op (MetaGrabOp op) return gravity; } + diff --git a/src/display.h b/src/display.h index 54a1fe130..7b6ac68a0 100644 --- a/src/display.h +++ b/src/display.h @@ -179,6 +179,9 @@ struct _MetaDisplay /* Pings which we're waiting for a reply from */ GSList *pending_pings; + + /* Pending autoraise */ + guint autoraise_timeout_id; /* current window operation */ MetaGrabOp grab_op; diff --git a/src/metacity.schemas b/src/metacity.schemas index a54137a32..04660ee52 100644 --- a/src/metacity.schemas +++ b/src/metacity.schemas @@ -22,6 +22,37 @@ + + /schemas/apps/metacity/general/auto_raise + /apps/metacity/general/auto_raise + metacity + bool + false + + Automatically raises the focused window + + If true, and the focus mode is either "sloppy" or "mouse" + then the focused window will be automatically raised after a + delay (the delay is specified by the auto_raise_delay key). + + + + + + /schemas/apps/metacity/general/auto_raise_delay + /apps/metacity/general/auto_raise_delay + metacity + int + 500 + + Delay in milliseconds for the auto raise option + + The time delay before raising a window if auto_raise is + set to true. The delay is given in thousandths of a second. + + + + /schemas/apps/metacity/general/theme /apps/metacity/general/theme diff --git a/src/prefs.c b/src/prefs.c index c9f753c6d..49071eb22 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -30,6 +30,8 @@ * notify listener and of course in the .schemas file */ #define KEY_FOCUS_MODE "/apps/metacity/general/focus_mode" +#define KEY_AUTO_RAISE "/apps/metacity/general/auto_raise" +#define KEY_AUTO_RAISE_DELAY "/apps/metacity/general/auto_raise_delay" #define KEY_THEME "/apps/metacity/general/theme" #define KEY_USE_DESKTOP_FONT "/apps/metacity/general/titlebar_uses_desktop_font" #define KEY_TITLEBAR_FONT "/apps/metacity/general/titlebar_font" @@ -53,6 +55,8 @@ static char* current_theme = NULL; static int num_workspaces = 4; static gboolean application_based = FALSE; static gboolean disable_workarounds = FALSE; +static gboolean auto_raise = FALSE; +static gboolean auto_raise_delay = 500; static gboolean update_use_desktop_font (gboolean value); static gboolean update_titlebar_font (const char *value); @@ -62,6 +66,8 @@ static gboolean update_theme (const char *value); static gboolean update_num_workspaces (int value); static gboolean update_application_based (gboolean value); static gboolean update_disable_workarounds (gboolean value); +static gboolean update_auto_raise (gboolean value); +static gboolean update_auto_raise_delay (int value); static gboolean update_window_binding (const char *name, const char *value); static gboolean update_screen_binding (const char *name, @@ -231,6 +237,17 @@ meta_prefs_init (void) update_focus_mode (str_val); g_free (str_val); + bool_val = gconf_client_get_bool (default_client, KEY_AUTO_RAISE, + &err); + cleanup_error (&err); + update_auto_raise (bool_val); + + int_val = gconf_client_get_int (default_client, KEY_AUTO_RAISE_DELAY, + &err); + cleanup_error (&err); + update_auto_raise_delay (int_val); + + str_val = gconf_client_get_string (default_client, KEY_THEME, &err); cleanup_error (&err); @@ -481,6 +498,38 @@ change_notify (GConfClient *client, if (update_screen_binding (key, str)) queue_changed (META_PREF_SCREEN_KEYBINDINGS); } + else if (strcmp (key, KEY_AUTO_RAISE) == 0) + { + gboolean b; + + if (value && value->type != GCONF_VALUE_BOOL) + { + meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), + KEY_AUTO_RAISE); + goto out; + } + + b = value ? gconf_value_get_bool (value) : auto_raise; + + if (update_auto_raise (b)) + queue_changed (META_PREF_AUTO_RAISE); + } + else if (strcmp (key, KEY_AUTO_RAISE_DELAY) == 0) + { + int d; + + if (value && value->type != GCONF_VALUE_INT) + { + meta_warning (_("GConf key \"%s\" is set to an invalid type\n"), + KEY_AUTO_RAISE_DELAY); + goto out; + } + + d = value ? gconf_value_get_int (value) : 0; + + if (update_auto_raise_delay (d)) + queue_changed (META_PREF_AUTO_RAISE_DELAY); + } else { meta_verbose ("Key %s doesn't mean anything to Metacity\n", @@ -702,6 +751,36 @@ meta_prefs_get_disable_workarounds (void) return disable_workarounds; } +static gboolean +update_auto_raise (gboolean value) +{ + gboolean old = auto_raise; + + auto_raise = value; + + return old != auto_raise; +} + +#define MAX_REASONABLE_AUTO_RAISE_DELAY 10000 + +static gboolean +update_auto_raise_delay (int value) +{ + int old = auto_raise_delay; + + if (value < 0 || value > MAX_REASONABLE_AUTO_RAISE_DELAY) + { + meta_warning (_("%d stored in GConf key %s is out of range 0 to %d\n"), + value, KEY_AUTO_RAISE_DELAY, + MAX_REASONABLE_AUTO_RAISE_DELAY); + value = 0; + } + + auto_raise_delay = value; + + return old != auto_raise_delay; +} + const char* meta_preference_to_string (MetaPreference pref) { @@ -733,6 +812,12 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_DISABLE_WORKAROUNDS: return "DISABLE_WORKAROUNDS"; + + case META_PREF_AUTO_RAISE: + return "AUTO_RAISE"; + + case META_PREF_AUTO_RAISE_DELAY: + return "AUTO_RAISE_DELAY"; } return "(unknown)"; @@ -984,3 +1069,14 @@ meta_prefs_get_window_bindings (const MetaKeyPref **bindings, *n_bindings = (int) G_N_ELEMENTS (window_bindings) - 1; } +gboolean +meta_prefs_get_auto_raise () +{ + return auto_raise; +} + +int +meta_prefs_get_auto_raise_delay () +{ + return auto_raise_delay; +} diff --git a/src/prefs.h b/src/prefs.h index d808cb704..6226e25de 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -29,6 +29,8 @@ typedef enum { META_PREF_FOCUS_MODE, + META_PREF_AUTO_RAISE, + META_PREF_AUTO_RAISE_DELAY, META_PREF_THEME, META_PREF_TITLEBAR_FONT, META_PREF_TITLEBAR_FONT_SIZE, @@ -59,6 +61,8 @@ int meta_prefs_get_titlebar_font_size (void); int meta_prefs_get_num_workspaces (void); gboolean meta_prefs_get_application_based (void); gboolean meta_prefs_get_disable_workarounds (void); +gboolean meta_prefs_get_auto_raise (void); +int meta_prefs_get_auto_raise_delay (void); void meta_prefs_set_num_workspaces (int n_workspaces);