diff --git a/src/core/screen-private.h b/src/core/screen-private.h index c9f4231f0..9d520e5dd 100644 --- a/src/core/screen-private.h +++ b/src/core/screen-private.h @@ -100,8 +100,6 @@ struct _MetaScreen #endif Window wm_cm_selection_window; - guint32 wm_cm_timestamp; - guint work_area_later; guint check_fullscreen_later; diff --git a/src/core/screen.c b/src/core/screen.c index b26137e33..496e693e7 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -496,6 +496,81 @@ create_guard_window (Display *xdisplay, MetaScreen *screen) return guard_window; } +static Window +take_manager_selection (MetaDisplay *display, + Window xroot, + Atom manager_atom, + int timestamp, + gboolean should_replace) +{ + Display *xdisplay = display->xdisplay; + Window current_owner, new_owner; + + current_owner = XGetSelectionOwner (xdisplay, manager_atom); + if (current_owner != None) + { + XSetWindowAttributes attrs; + + if (should_replace) + { + /* We want to find out when the current selection owner dies */ + meta_error_trap_push (display); + attrs.event_mask = StructureNotifyMask; + XChangeWindowAttributes (xdisplay, current_owner, CWEventMask, &attrs); + if (meta_error_trap_pop_with_return (display) != Success) + current_owner = None; /* don't wait for it to die later on */ + } + else + { + meta_warning (_("Display \"%s\" already has a window manager; try using the --replace option to replace the current window manager."), + display->name); + return None; + } + } + + /* We need SelectionClear and SelectionRequest events on the new owner, + * but those cannot be masked, so we only need NoEventMask. + */ + new_owner = meta_create_offscreen_window (xdisplay, xroot, NoEventMask); + + XSetSelectionOwner (xdisplay, manager_atom, new_owner, timestamp); + + if (XGetSelectionOwner (xdisplay, manager_atom) != new_owner) + { + meta_warning ("Could not acquire selection: %s", XGetAtomName (xdisplay, manager_atom)); + return None; + } + + { + /* Send client message indicating that we are now the selection owner */ + XClientMessageEvent ev; + + ev.type = ClientMessage; + ev.window = xroot; + ev.message_type = display->atom_MANAGER; + ev.format = 32; + ev.data.l[0] = timestamp; + ev.data.l[1] = manager_atom; + + XSendEvent (xdisplay, xroot, False, StructureNotifyMask, (XEvent *) &ev); + } + + /* Wait for old window manager to go away */ + if (current_owner != None) + { + XEvent event; + + /* We sort of block infinitely here which is probably lame. */ + + meta_verbose ("Waiting for old window manager to exit\n"); + do + XWindowEvent (xdisplay, current_owner, StructureNotifyMask, &event); + while (event.type != DestroyNotify); + } + + return new_owner; +} + MetaScreen* meta_screen_new (MetaDisplay *display, int number, @@ -505,11 +580,9 @@ meta_screen_new (MetaDisplay *display, Window xroot; Display *xdisplay; Window new_wm_sn_owner; - Window current_wm_sn_owner; gboolean replace_current_wm; Atom wm_sn_atom; char buf[128]; - guint32 manager_timestamp; MetaMonitorManager *manager; replace_current_wm = meta_get_replace_current_wm (); @@ -537,83 +610,11 @@ meta_screen_new (MetaDisplay *display, } sprintf (buf, "WM_S%d", number); + wm_sn_atom = XInternAtom (xdisplay, buf, False); - - current_wm_sn_owner = XGetSelectionOwner (xdisplay, wm_sn_atom); - - if (current_wm_sn_owner != None) - { - XSetWindowAttributes attrs; - - if (!replace_current_wm) - { - meta_warning (_("Screen %d on display \"%s\" already has a window manager; try using the --replace option to replace the current window manager.\n"), - number, display->name); - - return NULL; - } - - /* We want to find out when the current selection owner dies */ - meta_error_trap_push (display); - attrs.event_mask = StructureNotifyMask; - XChangeWindowAttributes (xdisplay, - current_wm_sn_owner, CWEventMask, &attrs); - if (meta_error_trap_pop_with_return (display) != Success) - current_wm_sn_owner = None; /* don't wait for it to die later on */ - } - - /* We need SelectionClear and SelectionRequest events on the new_wm_sn_owner, - * but those cannot be masked, so we only need NoEventMask. - */ - new_wm_sn_owner = meta_create_offscreen_window (xdisplay, xroot, NoEventMask); - - manager_timestamp = timestamp; - - XSetSelectionOwner (xdisplay, wm_sn_atom, new_wm_sn_owner, - manager_timestamp); - - if (XGetSelectionOwner (xdisplay, wm_sn_atom) != new_wm_sn_owner) - { - meta_warning ("Could not acquire window manager selection on screen %d display \"%s\"\n", - number, display->name); - - XDestroyWindow (xdisplay, new_wm_sn_owner); - - return NULL; - } - - { - /* Send client message indicating that we are now the WM */ - XClientMessageEvent ev; - - ev.type = ClientMessage; - ev.window = xroot; - ev.message_type = display->atom_MANAGER; - ev.format = 32; - ev.data.l[0] = manager_timestamp; - ev.data.l[1] = wm_sn_atom; - - XSendEvent (xdisplay, xroot, False, StructureNotifyMask, (XEvent*)&ev); - } - - /* Wait for old window manager to go away */ - if (current_wm_sn_owner != None) - { - XEvent event; - - /* We sort of block infinitely here which is probably lame. */ - - meta_verbose ("Waiting for old window manager to exit\n"); - do - { - XWindowEvent (xdisplay, current_wm_sn_owner, - StructureNotifyMask, &event); - } - while (event.type != DestroyNotify); - } - - /* select our root window events */ - meta_error_trap_push (display); + new_wm_sn_owner = take_manager_selection (display, xroot, wm_sn_atom, timestamp, replace_current_wm); + if (new_wm_sn_owner == None) + return NULL; { long event_mask; @@ -638,16 +639,6 @@ meta_screen_new (MetaDisplay *display, XSelectInput (xdisplay, xroot, event_mask); } - if (meta_error_trap_pop_with_return (display) != Success) - { - meta_warning (_("Screen %d on display \"%s\" already has a window manager\n"), - number, display->name); - - XDestroyWindow (xdisplay, new_wm_sn_owner); - - return NULL; - } - /* Select for cursor changes so the cursor tracker is up to date. */ XFixesSelectCursorInput (xdisplay, xroot, XFixesDisplayCursorNotifyMask); @@ -675,11 +666,7 @@ meta_screen_new (MetaDisplay *display, screen->wm_sn_selection_window = new_wm_sn_owner; screen->wm_sn_atom = wm_sn_atom; - screen->wm_sn_timestamp = manager_timestamp; - - screen->wm_cm_selection_window = meta_create_offscreen_window (xdisplay, - xroot, - NoEventMask); + screen->wm_sn_timestamp = timestamp; screen->work_area_later = 0; screen->check_fullscreen_later = 0; @@ -2898,27 +2885,12 @@ meta_screen_set_cm_selection (MetaScreen *screen) { char selection[32]; Atom a; + guint32 timestamp; - screen->wm_cm_timestamp = meta_display_get_current_time_roundtrip ( - screen->display); - - g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number); - meta_verbose ("Setting selection: %s\n", selection); - a = XInternAtom (screen->display->xdisplay, selection, FALSE); - XSetSelectionOwner (screen->display->xdisplay, a, - screen->wm_cm_selection_window, screen->wm_cm_timestamp); -} - -void -meta_screen_unset_cm_selection (MetaScreen *screen) -{ - char selection[32]; - Atom a; - - g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number); - a = XInternAtom (screen->display->xdisplay, selection, FALSE); - XSetSelectionOwner (screen->display->xdisplay, a, - None, screen->wm_cm_timestamp); + timestamp = meta_display_get_current_time_roundtrip (screen->display); + g_snprintf (selection, sizeof (selection), "_NET_WM_CM_S%d", screen->number); + a = XInternAtom (xdisplay, selection, False); + screen->wm_cm_selection_window = take_manager_selection (screen->display, screen->xroot, a, timestamp, TRUE); } /** diff --git a/src/meta/screen.h b/src/meta/screen.h index 4c3c52e3f..500871b68 100644 --- a/src/meta/screen.h +++ b/src/meta/screen.h @@ -45,7 +45,6 @@ void meta_screen_get_size (MetaScreen *screen, int *height); void meta_screen_set_cm_selection (MetaScreen *screen); -void meta_screen_unset_cm_selection (MetaScreen *screen); GSList *meta_screen_get_startup_sequences (MetaScreen *screen);