From f3d61bf7b024b6926fb8bba889c2b6a778d9b0ff Mon Sep 17 00:00:00 2001 From: rhp Date: Sat, 23 Jun 2001 18:30:27 +0000 Subject: [PATCH] ... --- src/common.h | 3 +- src/display.c | 1 + src/frame.c | 9 ++- src/frames.c | 91 ++++++++++++++++-------- src/window.c | 187 ++++++++++++++++++++++++++++++++++++++++---------- src/window.h | 17 ++++- 6 files changed, 240 insertions(+), 68 deletions(-) diff --git a/src/common.h b/src/common.h index 5f5411b1f..aacb8f402 100644 --- a/src/common.h +++ b/src/common.h @@ -38,7 +38,8 @@ typedef enum META_FRAME_SHADED = 1 << 7, META_FRAME_STUCK = 1 << 8, META_FRAME_MAXIMIZED = 1 << 9, - META_FRAME_ALLOWS_SHADE = 1 << 10 + META_FRAME_ALLOWS_SHADE = 1 << 10, + META_FRAME_ALLOWS_MOVE = 1 << 11 } MetaFrameFlags; typedef enum diff --git a/src/display.c b/src/display.c index 76408122b..6ff12f0de 100644 --- a/src/display.c +++ b/src/display.c @@ -599,6 +599,7 @@ event_callback (XEvent *event, { meta_verbose ("Window %s withdrawn\n", window->desc); + window->withdrawn = TRUE; meta_window_free (window); /* Unmanage withdrawn window */ } else diff --git a/src/frame.c b/src/frame.c index 758be83f2..533a8f082 100644 --- a/src/frame.c +++ b/src/frame.c @@ -164,8 +164,7 @@ meta_frame_get_flags (MetaFrame *frame) { MetaFrameFlags flags; - flags = - META_FRAME_ALLOWS_MENU | META_FRAME_ALLOWS_RESIZE; + flags = META_FRAME_ALLOWS_MENU; if (frame->window->has_close_func) flags |= META_FRAME_ALLOWS_DELETE; @@ -178,6 +177,12 @@ meta_frame_get_flags (MetaFrame *frame) if (frame->window->has_shade_func) flags |= META_FRAME_ALLOWS_SHADE; + + if (frame->window->has_move_func) + flags |= META_FRAME_ALLOWS_MOVE; + + if (frame->window->has_resize_func) + flags |= META_FRAME_ALLOWS_RESIZE; if (frame->window->has_focus) flags |= META_FRAME_HAS_FOCUS; diff --git a/src/frames.c b/src/frames.c index 07ddfab6d..0c82a501a 100644 --- a/src/frames.c +++ b/src/frames.c @@ -598,12 +598,11 @@ meta_frames_calc_geometry (MetaFrames *frames, } title_right_edge = x - props.title_border.right; - + /* Now x changes to be position from the left */ x = props.left_inset; - if ((flags & META_FRAME_ALLOWS_MENU) && - x < title_right_edge) + if (flags & META_FRAME_ALLOWS_MENU) { fgeom->menu_rect.x = x + props.button_border.left; fgeom->menu_rect.y = button_y; @@ -629,6 +628,30 @@ meta_frames_calc_geometry (MetaFrames *frames, fgeom->close_rect.width = 0; fgeom->close_rect.height = 0; } + + /* Check for maximize overlap */ + if (fgeom->max_rect.width > 0 && + fgeom->max_rect.x < (fgeom->menu_rect.x + fgeom->menu_rect.height)) + { + fgeom->max_rect.width = 0; + fgeom->max_rect.height = 0; + } + + /* Check for minimize overlap */ + if (fgeom->min_rect.width > 0 && + fgeom->min_rect.x < (fgeom->menu_rect.x + fgeom->menu_rect.height)) + { + fgeom->min_rect.width = 0; + fgeom->min_rect.height = 0; + } + + /* Check for spacer overlap */ + if (fgeom->spacer_rect.width > 0 && + fgeom->spacer_rect.x < (fgeom->menu_rect.x + fgeom->menu_rect.height)) + { + fgeom->spacer_rect.width = 0; + fgeom->spacer_rect.height = 0; + } /* We always fill as much vertical space as possible with title rect, * rather than centering it like the buttons and spacer @@ -1035,38 +1058,52 @@ meta_frames_button_press_event (GtkWidget *widget, else if (control == META_FRAME_CONTROL_RESIZE_SE && event->button == 1) { - int w, h; - - meta_core_get_size (gdk_display, - frame->xwindow, - &w, &h); + MetaFrameFlags flags; - meta_frames_begin_grab (frames, frame, - META_FRAME_STATUS_RESIZING_SE, - event->button, - event->x_root, - event->y_root, - w, h, - event->time); + flags = meta_core_get_frame_flags (gdk_display, frame->xwindow); + + if (flags & META_FRAME_ALLOWS_RESIZE) + { + int w, h; + + meta_core_get_size (gdk_display, + frame->xwindow, + &w, &h); + + meta_frames_begin_grab (frames, frame, + META_FRAME_STATUS_RESIZING_SE, + event->button, + event->x_root, + event->y_root, + w, h, + event->time); + } } else if (((control == META_FRAME_CONTROL_TITLE || control == META_FRAME_CONTROL_NONE) && event->button == 1) || event->button == 2) { - int x, y; - - meta_core_get_position (gdk_display, - frame->xwindow, - &x, &y); + MetaFrameFlags flags; - meta_frames_begin_grab (frames, frame, - META_FRAME_STATUS_MOVING, - event->button, - event->x_root, - event->y_root, - x, y, - event->time); + flags = meta_core_get_frame_flags (gdk_display, frame->xwindow); + + if (flags & META_FRAME_ALLOWS_MOVE) + { + int x, y; + + meta_core_get_position (gdk_display, + frame->xwindow, + &x, &y); + + meta_frames_begin_grab (frames, frame, + META_FRAME_STATUS_MOVING, + event->button, + event->x_root, + event->y_root, + x, y, + event->time); + } } return TRUE; diff --git a/src/window.c b/src/window.c index 46daf7b25..a13ccefc3 100644 --- a/src/window.c +++ b/src/window.c @@ -56,6 +56,7 @@ static int update_role (MetaWindow *window); static int update_net_wm_type (MetaWindow *window); static int update_initial_workspace (MetaWindow *window); static void recalc_window_type (MetaWindow *window); +static void recalc_window_features (MetaWindow *window); static int set_wm_state (MetaWindow *window, int state); static int set_net_wm_state (MetaWindow *window); @@ -78,6 +79,12 @@ static void meta_window_move_resize_internal (MetaWindow *window, int w, int h); + +static gboolean get_cardinal (MetaDisplay *display, + Window xwindow, + Atom atom, + gulong *val); + void meta_window_unqueue_calc_showing (MetaWindow *window); MetaWindow* @@ -116,9 +123,20 @@ meta_window_new (MetaDisplay *display, Window xwindow, if (must_be_viewable && attrs.map_state != IsViewable) { - meta_verbose ("Deciding not to manage unmapped or unviewable window 0x%lx\n", xwindow); - meta_display_ungrab (display); - return NULL; + /* Only manage if WM_STATE is IconicState or NormalState */ + gulong state; + + if (!(get_cardinal (display, xwindow, + display->atom_wm_state, + &state) && + (state == IconicState || state == NormalState))) + { + meta_verbose ("Deciding not to manage unmapped or unviewable window 0x%lx\n", xwindow); + meta_display_ungrab (display); + return NULL; + } + + /* FIXME should honor WM_STATE probably */ } meta_error_trap_push (display); @@ -214,13 +232,24 @@ meta_window_new (MetaDisplay *display, Window xwindow, window->calc_showing_queued = FALSE; window->keys_grabbed = FALSE; window->grab_on_frame = FALSE; + window->withdrawn = FALSE; window->unmaps_pending = 0; + + window->mwm_decorated = TRUE; + window->mwm_has_close_func = TRUE; + window->mwm_has_minimize_func = TRUE; + window->mwm_has_maximize_func = TRUE; + window->mwm_has_move_func = TRUE; + window->mwm_has_resize_func = TRUE; window->decorated = TRUE; window->has_close_func = TRUE; window->has_minimize_func = TRUE; window->has_maximize_func = TRUE; + window->has_move_func = TRUE; + window->has_resize_func = TRUE; + window->has_shade_func = TRUE; window->wm_state_modal = FALSE; @@ -271,7 +300,6 @@ meta_window_new (MetaDisplay *display, Window xwindow, 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); @@ -306,16 +334,8 @@ meta_window_new (MetaDisplay *display, Window xwindow, if (window->type == META_WINDOW_DESKTOP || window->type == META_WINDOW_DOCK) { - /* Change around the defaults */ + /* Change the default */ window->on_all_workspaces = TRUE; - window->has_close_func = FALSE; - window->has_shade_func = FALSE; - } - - if (window->type != META_WINDOW_NORMAL) - { - window->has_minimize_func = FALSE; - window->has_maximize_func = FALSE; } /* Put our state back where it should be, @@ -373,9 +393,10 @@ meta_window_free (MetaWindow *window) meta_stack_remove (window->screen->stack, window); /* FIXME restore original size if window has maximized */ - - set_wm_state (window, WithdrawnState); + if (window->withdrawn) + set_wm_state (window, WithdrawnState); + if (window->frame) meta_window_destroy_frame (window); @@ -2152,10 +2173,12 @@ update_mwm_hints (MetaWindow *window) gulong bytes_after; int result; - window->decorated = TRUE; - window->has_close_func = TRUE; - window->has_minimize_func = TRUE; - window->has_maximize_func = TRUE; + window->mwm_decorated = TRUE; + window->mwm_has_close_func = TRUE; + window->mwm_has_minimize_func = TRUE; + window->mwm_has_maximize_func = TRUE; + window->mwm_has_move_func = TRUE; + window->mwm_has_resize_func = TRUE; meta_error_trap_push (window->display); XGetWindowProperty (window->display->xdisplay, window->xwindow, @@ -2185,39 +2208,79 @@ update_mwm_hints (MetaWindow *window) window->desc, hints->decorations); if (hints->decorations == 0) - window->decorated = FALSE; + window->mwm_decorated = FALSE; } else meta_verbose ("Decorations flag unset\n"); - + if (hints->flags & MWM_HINTS_FUNCTIONS) { + gboolean toggle_value; + meta_verbose ("Window %s sets MWM_HINTS_FUNCTIONS 0x%lx\n", window->desc, hints->functions); + /* If _ALL is specified, then other flags indicate what to turn off; + * if ALL is not specified, flags are what to turn on. + * at least, I think so + */ + + if ((hints->flags & MWM_FUNC_ALL) == 0) + { + toggle_value = TRUE; + + meta_verbose ("Window %s disables all funcs then reenables some\n", + window->desc); + window->mwm_has_close_func = FALSE; + window->mwm_has_minimize_func = FALSE; + window->mwm_has_maximize_func = FALSE; + window->mwm_has_move_func = FALSE; + window->mwm_has_resize_func = FALSE; + } + else + { + meta_verbose ("Window %s enables all funcs then disables some\n", + window->desc); + toggle_value = FALSE; + } + if ((hints->functions & MWM_FUNC_CLOSE) == 0) { - meta_verbose ("Window %s disables close via MWM hints\n", + meta_verbose ("Window %s toggles close via MWM hints\n", window->desc); - window->has_close_func = FALSE; + window->mwm_has_close_func = toggle_value; } if ((hints->functions & MWM_FUNC_MINIMIZE) == 0) { - meta_verbose ("Window %s disables minimize via MWM hints\n", + meta_verbose ("Window %s toggles minimize via MWM hints\n", window->desc); - window->has_minimize_func = FALSE; + window->mwm_has_minimize_func = toggle_value; } if ((hints->functions & MWM_FUNC_MAXIMIZE) == 0) { - meta_verbose ("Window %s disables maximize via MWM hints\n", + meta_verbose ("Window %s toggles maximize via MWM hints\n", window->desc); - window->has_maximize_func = FALSE; + window->mwm_has_maximize_func = toggle_value; + } + if ((hints->functions & MWM_FUNC_MOVE) == 0) + { + meta_verbose ("Window %s toggles move via MWM hints\n", + window->desc); + window->mwm_has_move_func = toggle_value; + } + if ((hints->functions & MWM_FUNC_RESIZE) == 0) + { + meta_verbose ("Window %s toggles resize via MWM hints\n", + window->desc); + window->mwm_has_resize_func = toggle_value; } } else meta_verbose ("Functions flag unset\n"); XFree (hints); + + recalc_window_features (window); return Success; } @@ -2426,7 +2489,8 @@ update_transient_for (MetaWindow *window) static gboolean -get_cardinal (MetaWindow *window, +get_cardinal (MetaDisplay *display, + Window xwindow, Atom atom, gulong *val) { @@ -2437,15 +2501,15 @@ get_cardinal (MetaWindow *window, gulong *num; int err; - meta_error_trap_push (window->display); + meta_error_trap_push (display); type = None; - XGetWindowProperty (window->display->xdisplay, - window->xwindow, + XGetWindowProperty (display->xdisplay, + xwindow, atom, 0, G_MAXLONG, False, XA_CARDINAL, &type, &format, &nitems, &bytes_after, (guchar **)&num); - err = meta_error_trap_pop (window->display); + err = meta_error_trap_pop (display); if (err != Success) return FALSE; @@ -2497,7 +2561,9 @@ update_net_wm_type (MetaWindow *window) /* Fall back to WIN_LAYER */ gulong layer = WIN_LAYER_NORMAL; - if (get_cardinal (window, window->display->atom_win_layer, + if (get_cardinal (window->display, + window->xwindow, + window->display->atom_win_layer, &layer)) { meta_verbose ("%s falling back to _WIN_LAYER hint, layer %ld\n", @@ -2576,10 +2642,14 @@ update_initial_workspace (MetaWindow *window) * is just to be nice when restarting from old Sawfish basically, * should nuke it eventually */ - if (get_cardinal (window, window->display->atom_net_wm_desktop, + if (get_cardinal (window->display, + window->xwindow, + window->display->atom_net_wm_desktop, &val)) window->initial_workspace = val; - else if (get_cardinal (window, window->display->atom_win_workspace, + else if (get_cardinal (window->display, + window->xwindow, + window->display->atom_win_workspace, &val)) window->initial_workspace = val; @@ -2625,13 +2695,56 @@ recalc_window_type (MetaWindow *window) if (old_type != window->type) { + recalc_window_features (window); + set_net_wm_state (window); - + + /* Update frame */ + if (window->decorated) + meta_window_ensure_frame (window); + else + meta_window_destroy_frame (window); + /* update stacking constraints */ meta_stack_update_layer (window->screen->stack, window); } } +static void +recalc_window_features (MetaWindow *window) +{ + /* Use MWM hints initially */ + window->decorated = window->mwm_decorated; + window->has_close_func = window->mwm_has_close_func; + window->has_minimize_func = window->mwm_has_minimize_func; + window->has_maximize_func = window->mwm_has_maximize_func; + window->has_move_func = window->mwm_has_move_func; + window->has_resize_func = window->mwm_has_resize_func; + + window->has_shade_func = TRUE; + + /* Semantic category overrides the MWM hints */ + + if (window->type == META_WINDOW_DESKTOP || + window->type == META_WINDOW_DOCK) + { + window->has_close_func = FALSE; + window->has_shade_func = FALSE; + window->has_move_func = FALSE; + window->has_resize_func = FALSE; + } + + if (window->type != META_WINDOW_NORMAL) + { + window->has_minimize_func = FALSE; + window->has_maximize_func = FALSE; + } + + /* FIXME perhaps should ensure if we don't have a shade func, + * we aren't shaded, etc. + */ +} + static void constrain_size (MetaWindow *window, MetaFrameGeometry *fgeom, @@ -2792,7 +2905,7 @@ constrain_position (MetaWindow *window, if (parent) { - int w; + int w; meta_window_get_position (parent, &x, &y); w = parent->rect.width; diff --git a/src/window.h b/src/window.h index fa103736b..218fd5cb4 100644 --- a/src/window.h +++ b/src/window.h @@ -104,12 +104,22 @@ struct _MetaWindow /* Globally active / No input */ guint input : 1; - /* Features of window */ + /* MWM hints about features of window */ + guint mwm_decorated : 1; + guint mwm_has_close_func : 1; + guint mwm_has_minimize_func : 1; + guint mwm_has_maximize_func : 1; + guint mwm_has_move_func : 1; + guint mwm_has_resize_func : 1; + + /* Computed features of window */ guint decorated : 1; guint has_close_func : 1; guint has_minimize_func : 1; guint has_maximize_func : 1; guint has_shade_func : 1; + guint has_move_func : 1; + guint has_resize_func : 1; /* Weird "_NET_WM_STATE_MODAL" flag */ guint wm_state_modal : 1; @@ -144,6 +154,11 @@ struct _MetaWindow /* Used by keybindings.c */ guint keys_grabbed : 1; guint grab_on_frame : 1; + + /* Set if the reason for unmanaging the window is that + * it was withdrawn + */ + guint withdrawn : 1; /* Number of UnmapNotify that are caused by us, if * we get UnmapNotify with none pending then the client