diff --git a/ChangeLog b/ChangeLog index dc73b9481..7e9e95dae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2004-01-09 Thomas Fitzsimmons + + Add _NET_FRAME_EXTENTS and _NET_REQUEST_FRAME_EXTENTS. + + * src/display.c: include xprops.h + (process_request_frame_extents): new function + (meta_display_open): add _NET_FRAME_EXTENTS and + _NET_REQUEST_FRAME_EXTENTS atoms + (event_callback): handle frame extents message + + * src/display.h (struct _MetaDisplay): add atom_net_frame_extents + and atom_net_request_frame_extents + + * src/theme.c (meta_pango_font_desc_get_text_height): make font_desc + parameter const + + * src/ui.c: include prefs.h + (meta_ui_theme_get_frame_borders): new function + + * src/window.c (update_net_frame_extents): new function + (meta_window_move_resize_internal): update frame extents + property when frame geometry changes + + * src/screen.c (set_supported_hint): add atom_net_frame_extents + and atom_net_request_frame_extents + 2004-01-09 Calum Benson * src/themes/Atlanta/metacity-theme-1.xml: diff --git a/src/display.c b/src/display.c index 47fd4039c..fcc51d454 100644 --- a/src/display.c +++ b/src/display.c @@ -33,6 +33,7 @@ #include "keybindings.h" #include "prefs.h" #include "resizepopup.h" +#include "xprops.h" #include "workspace.h" #include "bell.h" #include "effects.h" @@ -90,6 +91,8 @@ static Window event_get_modified_window (MetaDisplay *display, XEvent *event); static guint32 event_get_time (MetaDisplay *display, XEvent *event); +static void process_request_frame_extents (MetaDisplay *display, + XEvent *event); static void process_pong_message (MetaDisplay *display, XEvent *event); static void process_selection_request (MetaDisplay *display, @@ -274,7 +277,9 @@ meta_display_open (const char *name) "_METACITY_SENTINEL", "_NET_WM_STRUT_PARTIAL", "_NET_WM_ACTION_FULLSCREEN", - "_NET_WM_ACTION_MINIMIZE" + "_NET_WM_ACTION_MINIMIZE", + "_NET_FRAME_EXTENTS", + "_NET_REQUEST_FRAME_EXTENTS", }; Atom atoms[G_N_ELEMENTS(atom_names)]; @@ -419,7 +424,9 @@ meta_display_open (const char *name) display->atom_net_wm_strut_partial = atoms[80]; display->atom_net_wm_action_fullscreen = atoms[81]; display->atom_net_wm_action_minimize = atoms[82]; - + display->atom_net_frame_extents = atoms[83]; + display->atom_net_request_frame_extents = atoms[84]; + display->prop_hooks = NULL; meta_display_init_window_prop_hooks (display); display->group_prop_hooks = NULL; @@ -1990,6 +1997,13 @@ event_callback (XEvent *event, } } } + + if (event->xclient.message_type == + display->atom_net_request_frame_extents) + { + meta_verbose ("Received _NET_REQUEST_FRAME_EXTENTS message\n"); + process_request_frame_extents (display, event); + } } break; case MappingNotify: @@ -3543,6 +3557,74 @@ meta_display_ping_window (MetaDisplay *display, timestamp); } +static void +process_request_frame_extents (MetaDisplay *display, + XEvent *event) +{ + /* The X window whose frame extents will be set. */ + Window xwindow = event->xclient.window; + unsigned long data[4] = { 0, 0, 0, 0 }; + + MotifWmHints *hints = NULL; + gboolean hints_set = FALSE; + + meta_verbose ("Setting frame extents for 0x%lx\n", xwindow); + + /* See if the window is decorated. */ + hints_set = meta_prop_get_motif_hints (display, + xwindow, + display->atom_motif_wm_hints, + &hints); + if ((hints_set && hints->decorations) || !hints_set) + { + int top = 0; + int bottom = 0; + int left = 0; + int right = 0; + + MetaScreen *screen; + + screen = meta_display_screen_for_xwindow (display, + event->xclient.window); + if (screen == NULL) + { + meta_warning ("Received request to set _NET_FRAME_EXTENTS " + "on 0x%lx which is on a screen we are not managing\n", + event->xclient.window); + meta_XFree (hints); + return; + } + + /* Return estimated frame extents for a normal window. */ + meta_ui_theme_get_frame_borders (screen->ui, + META_FRAME_TYPE_NORMAL, + 0, + &top, + &bottom, + &left, + &right); + + data[0] = left; + data[1] = right; + data[2] = top; + data[3] = bottom; + } + + meta_topic (META_DEBUG_GEOMETRY, + "Setting _NET_FRAME_EXTENTS on unmanaged window 0x%lx " + "to top = %ld, left = %ld, bottom = %ld, right = %ld\n", + xwindow, data[0], data[1], data[2], data[3]); + + meta_error_trap_push (display); + XChangeProperty (display->xdisplay, xwindow, + display->atom_net_frame_extents, + XA_CARDINAL, + 32, PropModeReplace, (guchar*) data, 4); + meta_error_trap_pop (display, FALSE); + + meta_XFree (hints); +} + /* process the pong from our ping */ static void process_pong_message (MetaDisplay *display, diff --git a/src/display.h b/src/display.h index fc7e631c0..699693172 100644 --- a/src/display.h +++ b/src/display.h @@ -172,7 +172,9 @@ struct _MetaDisplay Atom atom_gnome_panel_action_run_dialog; Atom atom_metacity_sentinel; Atom atom_net_wm_strut_partial; - + Atom atom_net_frame_extents; + Atom atom_net_request_frame_extents; + /* This is the actual window from focus events, * not the one we last set */ diff --git a/src/screen.c b/src/screen.c index db6f59024..6f3ea0952 100644 --- a/src/screen.c +++ b/src/screen.c @@ -82,7 +82,7 @@ set_wm_check_hint (MetaScreen *screen) static int set_supported_hint (MetaScreen *screen) { -#define N_SUPPORTED 68 +#define N_SUPPORTED 70 Atom atoms[N_SUPPORTED]; atoms[0] = screen->display->atom_net_wm_name; @@ -153,6 +153,8 @@ set_supported_hint (MetaScreen *screen) atoms[65] = screen->display->atom_net_wm_strut_partial; atoms[66] = screen->display->atom_net_wm_action_fullscreen; atoms[67] = screen->display->atom_net_wm_action_minimize; + atoms[68] = screen->display->atom_net_frame_extents; + atoms[69] = screen->display->atom_net_request_frame_extents; XChangeProperty (screen->display->xdisplay, screen->xroot, screen->display->atom_net_supported, diff --git a/src/theme.c b/src/theme.c index b07d7cdd9..25e569575 100644 --- a/src/theme.c +++ b/src/theme.c @@ -5168,7 +5168,7 @@ meta_gtk_widget_get_font_desc (GtkWidget *widget, } int -meta_pango_font_desc_get_text_height (PangoFontDescription *font_desc, +meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc, PangoContext *context) { PangoFontMetrics *metrics; diff --git a/src/theme.h b/src/theme.h index f87e857d7..7513a77a4 100644 --- a/src/theme.h +++ b/src/theme.h @@ -815,7 +815,7 @@ char* meta_theme_replace_constants (MetaTheme *theme, PangoFontDescription* meta_gtk_widget_get_font_desc (GtkWidget *widget, double scale, const PangoFontDescription *override); -int meta_pango_font_desc_get_text_height (PangoFontDescription *font_desc, +int meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc, PangoContext *context); diff --git a/src/ui.c b/src/ui.c index 76fb958ad..c8486c5d8 100644 --- a/src/ui.c +++ b/src/ui.c @@ -21,6 +21,7 @@ */ #include +#include "prefs.h" #include "ui.h" #include "frames.h" #include "util.h" @@ -684,6 +685,44 @@ meta_text_property_to_utf8 (Display *xdisplay, return retval; } +void +meta_ui_theme_get_frame_borders (MetaUI *ui, + MetaFrameType type, + MetaFrameFlags flags, + int *top_height, + int *bottom_height, + int *left_width, + int *right_width) +{ + int text_height; + PangoContext *context; + const PangoFontDescription *font_desc; + GtkStyle *default_style; + + if (meta_ui_have_a_theme ()) + { + context = gtk_widget_get_pango_context (GTK_WIDGET (ui->frames)); + font_desc = meta_prefs_get_titlebar_font (); + + if (!font_desc) + { + default_style = gtk_widget_get_default_style (); + font_desc = default_style->font_desc; + } + + text_height = meta_pango_font_desc_get_text_height (font_desc, context); + + meta_theme_get_frame_borders (meta_theme_get_current (), + type, text_height, flags, + top_height, bottom_height, + left_width, right_width); + } + else + { + *top_height = *bottom_height = *left_width = *right_width = 0; + } +} + void meta_ui_set_current_theme (const char *name, gboolean force_reload) diff --git a/src/ui.h b/src/ui.h index 3740d870f..2d4af4a09 100644 --- a/src/ui.h +++ b/src/ui.h @@ -55,6 +55,13 @@ MetaUI* meta_ui_new (Display *xdisplay, Screen *screen); void meta_ui_free (MetaUI *ui); +void meta_ui_theme_get_frame_borders (MetaUI *ui, + MetaFrameType type, + MetaFrameFlags flags, + int *top_height, + int *bottom_height, + int *left_width, + int *right_width); void meta_ui_get_frame_geometry (MetaUI *ui, Window frame_xwindow, int *top_height, int *bottom_height, diff --git a/src/window.c b/src/window.c index 673b2be13..100b158d2 100644 --- a/src/window.c +++ b/src/window.c @@ -64,12 +64,14 @@ static void update_transient_for (MetaWindow *window); static void update_sm_hints (MetaWindow *window); static void update_role (MetaWindow *window); static void update_net_wm_type (MetaWindow *window); +static void update_net_frame_extents (MetaWindow *window); static void recalc_window_type (MetaWindow *window); static void recalc_window_features (MetaWindow *window); static void invalidate_work_areas (MetaWindow *window); static void set_wm_state (MetaWindow *window, int state); static void set_net_wm_state (MetaWindow *window); + static void send_configure_notify (MetaWindow *window); static gboolean process_property_notify (MetaWindow *window, XPropertyEvent *event); @@ -2541,15 +2543,22 @@ meta_window_move_resize_internal (MetaWindow *window, use_static_gravity = FALSE; } - /* Fill in other frame member variables */ - if (window->frame) + /* If frame extents have changed, fill in other frame fields and + change frame's extents property. */ + if (window->frame && + (window->frame->child_x != fgeom.left_width || + window->frame->child_y != fgeom.top_height || + window->frame->right_width != fgeom.right_width || + window->frame->bottom_height != fgeom.bottom_height)) { window->frame->child_x = fgeom.left_width; window->frame->child_y = fgeom.top_height; window->frame->right_width = fgeom.right_width; window->frame->bottom_height = fgeom.bottom_height; + + update_net_frame_extents (window); } - + /* See ICCCM 4.1.5 for when to send ConfigureNotify */ need_configure_notify = FALSE; @@ -3319,6 +3328,36 @@ meta_window_get_net_wm_desktop (MetaWindow *window) return meta_workspace_index (window->workspaces->data); } +static void +update_net_frame_extents (MetaWindow *window) +{ + unsigned long data[4] = { 0, 0, 0, 0 }; + + if (window->frame) + { + /* Left */ + data[0] = window->frame->child_x; + /* Right */ + data[1] = window->frame->right_width; + /* Top */ + data[2] = window->frame->child_y; + /* Bottom */ + data[3] = window->frame->bottom_height; + } + + meta_topic (META_DEBUG_GEOMETRY, + "Setting _NET_FRAME_EXTENTS on managed window 0x%lx " + "to top = %ld, left = %ld, bottom = %ld, right = %ld\n", + window->xwindow, data[0], data[1], data[2], data[3]); + + meta_error_trap_push (window->display); + XChangeProperty (window->display->xdisplay, window->xwindow, + window->display->atom_net_frame_extents, + XA_CARDINAL, + 32, PropModeReplace, (guchar*) data, 4); + meta_error_trap_pop (window->display, FALSE); +} + void meta_window_set_current_workspace_hint (MetaWindow *window) {