screen: Behave better about CM selections
This commit is contained in:
parent
41303101e5
commit
fa97364fa8
@ -100,8 +100,6 @@ struct _MetaScreen
|
||||
#endif
|
||||
|
||||
Window wm_cm_selection_window;
|
||||
guint32 wm_cm_timestamp;
|
||||
|
||||
guint work_area_later;
|
||||
guint check_fullscreen_later;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user