diff --git a/src/display.c b/src/display.c index 503b02eb1..b38c01ccb 100644 --- a/src/display.c +++ b/src/display.c @@ -589,7 +589,7 @@ event_queue_callback (MetaEventQueue *queue, xwc.height = event->xconfigurerequest.height; xwc.border_width = event->xconfigurerequest.border_width; - meta_verbose ("Configuring withdrawn window to %d,%d %dx%d border %d\n", + meta_verbose ("Configuring withdrawn window to %d,%d %dx%d border %d (some values may not be in mask)\n", xwc.x, xwc.y, xwc.width, xwc.height, xwc.border_width); XConfigureWindow (display->xdisplay, event->xconfigurerequest.window, xwcm, &xwc); @@ -897,14 +897,24 @@ meta_spew_event (MetaDisplay *display, break; case ConfigureRequest: name = "ConfigureRequest"; - extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx x: %d y: %d w: %d h: %d border: %d", + extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx x: %d %sy: %d %sw: %d %sh: %d %sborder: %d %s", event->xconfigurerequest.parent, event->xconfigurerequest.window, event->xconfigurerequest.x, + event->xconfigurerequest.value_mask & + CWX ? "" : "(unset) ", event->xconfigurerequest.y, + event->xconfigurerequest.value_mask & + CWY ? "" : "(unset) ", event->xconfigurerequest.width, + event->xconfigurerequest.value_mask & + CWWidth ? "" : "(unset) ", event->xconfigurerequest.height, - event->xconfigurerequest.border_width); + event->xconfigurerequest.value_mask & + CWHeight ? "" : "(unset) ", + event->xconfigurerequest.border_width, + event->xconfigurerequest.value_mask & + CWBorderWidth ? "" : "(unset)"); break; case GravityNotify: name = "GravityNotify"; diff --git a/src/display.h b/src/display.h index 6016b10b7..e44d6d121 100644 --- a/src/display.h +++ b/src/display.h @@ -76,6 +76,8 @@ struct _MetaDisplay Atom atom_net_wm_state_modal; Atom atom_net_client_list; Atom atom_net_client_list_stacking; + Atom atom_net_wm_state_skip_taskbar; + Atom atom_net_wm_state_skip_pager; /* This is the actual window from focus events, * not the one we last set diff --git a/src/frame.c b/src/frame.c index fc424aeea..222a1008e 100644 --- a/src/frame.c +++ b/src/frame.c @@ -250,10 +250,13 @@ meta_window_ensure_frame (MetaWindow *window) * we don't want to take that as a withdraw */ window->unmaps_pending += 1; + window->rect.x = 0; + window->rect.y = 0; XReparentWindow (window->display->xdisplay, window->xwindow, frame->xwindow, - 0, 0); + window->rect.x, + window->rect.y); meta_error_trap_pop (window->display); /* stick frame to the window */ diff --git a/src/main.c b/src/main.c index bfd62b9c6..a71ac08ad 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,11 @@ #include "errors.h" #include +#include +#include +#include +#include +#include static MetaExitCode meta_exit_code = META_EXIT_SUCCESS; static GMainLoop *meta_main_loop = NULL; @@ -32,6 +37,15 @@ static GMainLoop *meta_main_loop = NULL; int main (int argc, char **argv) { + struct sigaction act; + sigset_t empty_mask; + + sigemptyset (&empty_mask); + act.sa_handler = SIG_IGN; + act.sa_mask = empty_mask; + act.sa_flags = 0; + sigaction (SIGPIPE, &act, 0); + g_set_prgname (PACKAGE); meta_main_loop = g_main_loop_new (NULL, FALSE); diff --git a/src/run-metacity.sh b/src/run-metacity.sh index 9f150c46f..abf28b370 100755 --- a/src/run-metacity.sh +++ b/src/run-metacity.sh @@ -13,15 +13,19 @@ if test -z "$CLIENTS"; then CLIENTS=0 fi -Xnest :1 -scrns $SCREENS -geometry 640x480 -bw 15 & -usleep 50000 +if test -z "$ONLY_WM"; then + Xnest :1 -scrns $SCREENS -geometry 640x480 -bw 15 & + usleep 50000 -if test $CLIENTS != 0; then - for I in `seq 1 $CLIENTS`; do - DISPLAY=:1 xterm -geometry 25x15 & - done + if test $CLIENTS != 0; then + for I in `seq 1 $CLIENTS`; do + DISPLAY=:1 xterm -geometry 25x15 & + done + fi + + DISPLAY=:1 xsetroot -solid royalblue3 fi -DISPLAY=:1 xsetroot -solid royalblue3 -METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity -killall Xnest +if test -z "$ONLY_SETUP"; then + METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity +fi diff --git a/src/screen.c b/src/screen.c index 90f75d276..5374b0082 100644 --- a/src/screen.c +++ b/src/screen.c @@ -61,7 +61,7 @@ set_wm_check_hint (MetaScreen *screen) static int set_supported_hint (MetaScreen *screen) { -#define N_SUPPORTED 19 +#define N_SUPPORTED 21 Atom atoms[N_SUPPORTED]; atoms[0] = screen->display->atom_net_wm_name; @@ -83,6 +83,8 @@ set_supported_hint (MetaScreen *screen) atoms[16] = screen->display->atom_net_wm_state_modal; atoms[17] = screen->display->atom_net_client_list; atoms[18] = screen->display->atom_net_client_list_stacking; + atoms[19] = screen->display->atom_net_wm_state_skip_taskbar; + atoms[20] = screen->display->atom_net_wm_state_skip_pager; XChangeProperty (screen->display->xdisplay, screen->xroot, screen->display->atom_net_wm_supported, @@ -244,7 +246,7 @@ meta_screen_manage_all_windows (MetaScreen *screen) i = 0; while (i < n_children) { - meta_window_new (screen->display, children[i]); + meta_window_new (screen->display, children[i], TRUE); ++i; } diff --git a/src/stack.c b/src/stack.c index 2cd76b453..6e1864f51 100644 --- a/src/stack.c +++ b/src/stack.c @@ -60,7 +60,8 @@ meta_stack_new (MetaScreen *screen) } stack->pending = NULL; stack->freeze_count = 0; - + stack->n_added = 0; + return stack; } @@ -124,6 +125,8 @@ meta_stack_add (MetaStack *stack, { MetaStackOp *op; + meta_verbose ("Adding window %s to the stack\n", window->desc); + op = ensure_op (stack, window); if (op->add_order >= 0) @@ -148,6 +151,8 @@ meta_stack_remove (MetaStack *stack, MetaWindow *window) { MetaStackOp *op; + + meta_verbose ("Removing window %s from the stack\n", window->desc); op = ensure_op (stack, window); diff --git a/src/uislave.c b/src/uislave.c index 023b82599..74c8dd14c 100644 --- a/src/uislave.c +++ b/src/uislave.c @@ -56,7 +56,7 @@ meta_ui_slave_new (const char *display_name, reset_vals (uislave); /* This may fail; all UISlave functions become no-ops - * if uislave->child_pids == 0, and metacity just runs + * if uislave->disabled, and metacity just runs * with no UI features other than window borders. */ respawn_child (uislave); @@ -86,6 +86,7 @@ meta_ui_slave_disable (MetaUISlave *uislave) */ kill_child (uislave); uislave->no_respawn = TRUE; + meta_warning ("UI slave disabled, no tooltips or window menus will work\n"); } static void @@ -105,21 +106,36 @@ respawn_child (MetaUISlave *uislave) { GError *error; const char *uislavedir; - char *argv[] = { "./metacity-uislave", NULL }; + char *argv[] = { NULL, NULL, NULL, NULL, NULL }; char *envp[2] = { NULL, NULL }; int child_pid, inpipe, outpipe, errpipe; - + char *path; + if (uislave->no_respawn) return; + + if (uislave->child_pid != 0) + return; uislavedir = g_getenv ("METACITY_UISLAVE_DIR"); if (uislavedir == NULL) uislavedir = METACITY_LIBEXECDIR; - + envp[0] = g_strconcat ("DISPLAY=", uislave->display_name, NULL); + + path = g_strconcat (uislavedir, "/", "metacity-uislave", NULL); +#if 0 + argv[0] = "/usr/bin/strace"; + argv[1] = "-o"; + argv[2] = "uislave-strace.log"; +#endif + argv[0] = path; + + meta_verbose ("Launching UI slave in dir %s display %s\n", + uislavedir, envp[0]); error = NULL; - if (g_spawn_async_with_pipes (uislavedir, + if (g_spawn_async_with_pipes (NULL, argv, envp, /* flags */ @@ -155,7 +171,8 @@ respawn_child (MetaUISlave *uislave) g_error_free (error); } - g_free (envp[0]); + g_free (envp[0]); + g_free (path); } static gboolean @@ -168,14 +185,35 @@ error_callback (GIOChannel *source, MetaUISlave *uislave; char buf[1024]; int n; + static int logfile = -1; + + if (meta_is_debugging () && logfile < 0) + { + const char *dir; + char *str; + + dir = g_get_home_dir (); + str = g_strconcat (dir, "/", "metacity-uislave.log", NULL); + + logfile = open (str, O_TRUNC | O_CREAT, 0644); + + if (logfile < 0) + meta_warning ("Failed to open uislave log file %s\n", str); + else + meta_verbose ("Opened uislave log file %s\n", str); + + g_free (str); + } + + if (logfile < 0) + logfile = 2; uislave = data; - /* Classic loop from Stevens */ n = read (uislave->err_pipe, buf, BUFSIZE); if (n > 0) { - if (write (2, buf, n) != n) + if (write (logfile, buf, n) != n) ; /* error, but printing a message to stderr will hardly help. */ } else if (n < 0) @@ -270,6 +308,11 @@ send_message (MetaUISlave *uislave, MetaMessage *message) { static int serial = 0; MetaMessageFooter *footer; + + if (uislave->no_respawn) + return; + + respawn_child (uislave); message->header.serial = serial; footer = META_MESSAGE_FOOTER (message); @@ -279,12 +322,18 @@ send_message (MetaUISlave *uislave, MetaMessage *message) if (write_bytes (uislave->in_pipe, META_MESSAGE_ESCAPE, META_MESSAGE_ESCAPE_LEN) < 0) - meta_warning ("Failed to write escape sequence: %s\n", - g_strerror (errno)); + { + meta_warning ("Failed to write escape sequence: %s\n", + g_strerror (errno)); + kill_child (uislave); + } if (write_bytes (uislave->in_pipe, message, message->header.length) < 0) - meta_warning ("Failed to write message: %s\n", - g_strerror (errno)); + { + meta_warning ("Failed to write message: %s\n", + g_strerror (errno)); + kill_child (uislave); + } } void diff --git a/src/util.c b/src/util.c index 379a3d95f..0da9a82bc 100644 --- a/src/util.c +++ b/src/util.c @@ -30,6 +30,29 @@ static gboolean is_verbose = FALSE; static gboolean is_debugging = FALSE; static gboolean is_syncing = FALSE; static int no_prefix = 0; +static FILE* logfile = NULL; + +static void +ensure_logfile (void) +{ + if (logfile == NULL) + { + const char *dir; + char *str; + + dir = g_get_home_dir (); + str = g_strconcat (dir, "/", "metacity.log", NULL); + + logfile = fopen (str, "w"); + + if (logfile == NULL) + meta_warning ("Failed to open log file %s\n", str); + else + meta_verbose ("Opened log file %s\n", str); + + g_free (str); + } +} gboolean meta_is_verbose (void) @@ -40,6 +63,9 @@ meta_is_verbose (void) void meta_set_verbose (gboolean setting) { + if (setting) + ensure_logfile (); + is_verbose = setting; } @@ -52,10 +78,12 @@ meta_is_debugging (void) void meta_set_debugging (gboolean setting) { + if (setting) + ensure_logfile (); + is_debugging = setting; } - gboolean meta_is_syncing (void) { @@ -86,7 +114,8 @@ meta_debug_spew (const char *format, ...) { va_list args; gchar *str; - + FILE *out; + g_return_if_fail (format != NULL); if (!is_debugging) @@ -96,9 +125,11 @@ meta_debug_spew (const char *format, ...) str = g_strdup_vprintf (format, args); va_end (args); + out = logfile ? logfile : stderr; + if (no_prefix == 0) - fputs ("Window manager: ", stderr); - fputs (str, stderr); + fputs ("Window manager: ", out); + fputs (str, out); g_free (str); } @@ -108,6 +139,7 @@ meta_verbose (const char *format, ...) { va_list args; gchar *str; + FILE *out; g_return_if_fail (format != NULL); @@ -118,9 +150,11 @@ meta_verbose (const char *format, ...) str = g_strdup_vprintf (format, args); va_end (args); + out = logfile ? logfile : stderr; + if (no_prefix == 0) - fputs ("Window manager: ", stderr); - fputs (str, stderr); + fputs ("Window manager: ", out); + fputs (str, out); g_free (str); } @@ -130,6 +164,7 @@ meta_bug (const char *format, ...) { va_list args; gchar *str; + FILE *out; g_return_if_fail (format != NULL); @@ -137,9 +172,11 @@ meta_bug (const char *format, ...) str = g_strdup_vprintf (format, args); va_end (args); + out = logfile ? logfile : stderr; + if (no_prefix == 0) - fputs ("Bug in window manager: ", stderr); - fputs (str, stderr); + fputs ("Bug in window manager: ", out); + fputs (str, out); g_free (str); @@ -152,16 +189,19 @@ meta_warning (const char *format, ...) { va_list args; gchar *str; - + FILE *out; + g_return_if_fail (format != NULL); va_start (args, format); str = g_strdup_vprintf (format, args); va_end (args); + out = logfile ? logfile : stderr; + if (no_prefix == 0) - fputs ("Window manager: ", stderr); - fputs (str, stderr); + fputs ("Window manager: ", out); + fputs (str, out); g_free (str); } @@ -171,16 +211,19 @@ meta_fatal (const char *format, ...) { va_list args; gchar *str; - + FILE *out; + g_return_if_fail (format != NULL); va_start (args, format); str = g_strdup_vprintf (format, args); va_end (args); + out = logfile ? logfile : stderr; + if (no_prefix == 0) - fputs ("Window manager: ", stderr); - fputs (str, stderr); + fputs ("Window manager: ", out); + fputs (str, out); g_free (str); diff --git a/src/window.c b/src/window.c index a63b2ec20..9f6ac08c5 100644 --- a/src/window.c +++ b/src/window.c @@ -76,7 +76,8 @@ static void meta_window_move_resize_internal (MetaWindow *window, int h); MetaWindow* -meta_window_new (MetaDisplay *display, Window xwindow) +meta_window_new (MetaDisplay *display, Window xwindow, + gboolean must_be_viewable) { MetaWindow *window; XWindowAttributes attrs; @@ -107,6 +108,13 @@ meta_window_new (MetaDisplay *display, Window xwindow) return NULL; } + 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; + } + meta_error_trap_push (display); XAddToSaveSet (display->xdisplay, xwindow); @@ -203,6 +211,8 @@ meta_window_new (MetaDisplay *display, Window xwindow) window->has_maximize_func = TRUE; window->wm_state_modal = FALSE; + window->wm_state_skip_taskbar = FALSE; + window->wm_state_skip_pager = FALSE; window->res_class = NULL; window->res_name = NULL; @@ -345,7 +355,24 @@ set_net_wm_state (MetaWindow *window) { int i; unsigned long data[10]; + gboolean skip_pager; + gboolean skip_taskbar; + if (window->type == META_WINDOW_DESKTOP || + window->type == META_WINDOW_DOCK || + window->type == META_WINDOW_TOOLBAR || + window->type == META_WINDOW_MENU) + skip_pager = TRUE; + else + skip_pager = FALSE; + + if (window->type == META_WINDOW_DESKTOP || + window->type == META_WINDOW_DOCK || + window->type == META_WINDOW_MENU) + skip_taskbar = TRUE; + else + skip_taskbar = FALSE; + i = 0; if (window->shaded) { @@ -357,6 +384,16 @@ set_net_wm_state (MetaWindow *window) data[i] = window->display->atom_net_wm_state_modal; ++i; } + if (window->wm_state_skip_pager || skip_pager) + { + data[i] = window->display->atom_net_wm_state_skip_pager; + ++i; + } + if (window->wm_state_skip_taskbar || skip_pager) + { + data[i] = window->display->atom_net_wm_state_skip_taskbar; + ++i; + } if (window->maximized) { data[i] = window->display->atom_net_wm_state_maximized_horz; @@ -1307,9 +1344,28 @@ meta_window_client_message (MetaWindow *window, recalc_window_type (window); meta_window_queue_move_resize (window); + } + + if (first == display->atom_net_wm_state_skip_pager || + second == display->atom_net_wm_state_skip_pager) + { + window->wm_state_skip_pager = + (action == _NET_WM_STATE_ADD) || + (action == _NET_WM_STATE_TOGGLE && !window->wm_state_skip_pager); + set_net_wm_state (window); } + if (first == display->atom_net_wm_state_skip_taskbar || + second == display->atom_net_wm_state_skip_taskbar) + { + window->wm_state_skip_taskbar = + (action == _NET_WM_STATE_ADD) || + (action == _NET_WM_STATE_TOGGLE && !window->wm_state_skip_taskbar); + + set_net_wm_state (window); + } + return TRUE; } else if (event->xclient.message_type == @@ -2211,6 +2267,10 @@ update_net_wm_type (MetaWindow *window) static void recalc_window_type (MetaWindow *window) { + int old_type; + + old_type = window->type; + if (window->type_atom != None) { if (window->type_atom == window->display->atom_net_wm_window_type_desktop) @@ -2241,8 +2301,13 @@ recalc_window_type (MetaWindow *window) meta_verbose ("Calculated type %d for %s\n", window->type, window->desc); - /* update stacking constraints */ - meta_stack_update_layer (window->screen->stack, window); + if (old_type != window->type) + { + set_net_wm_state (window); + + /* update stacking constraints */ + meta_stack_update_layer (window->screen->stack, window); + } } static void diff --git a/src/window.h b/src/window.h index c2146741d..c5d0d919b 100644 --- a/src/window.h +++ b/src/window.h @@ -109,12 +109,18 @@ struct _MetaWindow /* Weird "_NET_WM_STATE_MODAL" flag */ guint wm_state_modal : 1; + /* If these are TRUE, it just means a client explicitly + * toggled them on; we compute actual _NET_WM_STATE from + * window type usually + */ + guint wm_state_skip_taskbar : 1; + guint wm_state_skip_pager : 1; /* this flag tracks receipt of focus_in focus_out and * determines whether we draw the focus */ guint has_focus : 1; - + /* Track whether the user has ever manually modified * the window; if so, we remove some constraints * that exist on program modifications. @@ -153,7 +159,8 @@ struct _MetaWindow }; MetaWindow* meta_window_new (MetaDisplay *display, - Window xwindow); + Window xwindow, + gboolean must_be_viewable); void meta_window_free (MetaWindow *window); void meta_window_calc_showing (MetaWindow *window); void meta_window_queue_calc_showing (MetaWindow *window);