From 845833226b7d65019d41eb3afce6fad7ae3d30a2 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 22 Jul 2003 18:09:41 +0000 Subject: [PATCH] add the --replace command line option, and support for the WM_Sn selection --- openbox/event.c | 8 ++++ openbox/openbox.c | 47 ++++++++++--------- openbox/openbox.h | 2 + openbox/screen.c | 112 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 138 insertions(+), 31 deletions(-) diff --git a/openbox/event.c b/openbox/event.c index 35d3472d..018218fc 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -186,6 +186,9 @@ static Window event_get_window(XEvent *e) /* pick a window */ switch (e->type) { + case SelectionClear: + window = RootWindow(ob_display, ob_screen); + break; case MapRequest: window = e->xmap.window; break; @@ -548,6 +551,11 @@ static void event_handle_root(XEvent *e) Atom msgtype; switch(e->type) { + case SelectionClear: + g_message("Another WM has requested to replace us. Exiting."); + ob_exit(); + break; + case ClientMessage: if (e->xclient.format != 32) break; diff --git a/openbox/openbox.c b/openbox/openbox.c index 23476417..4b248a0c 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -59,14 +59,15 @@ RrInstance *ob_rr_inst; RrTheme *ob_rr_theme; Display *ob_display; gint ob_screen; -Cursor ob_cursors[OB_NUM_CURSORS]; -KeyCode ob_keys[OB_NUM_KEYS]; +gboolean ob_replace_wm; static ObState state; static gboolean xsync; static gboolean shutdown; static gboolean restart; static char *restart_path; +static Cursor cursors[OB_NUM_CURSORS]; +static KeyCode keys[OB_NUM_KEYS]; static void signal_handler(const ObEvent *e, void *data); static void parse_args(int argc, char **argv); @@ -169,41 +170,41 @@ int main(int argc, char **argv) putenv(g_strdup_printf("DISPLAY=%s", DisplayString(ob_display))); /* create available cursors */ - ob_cursors[OB_CURSOR_POINTER] = + cursors[OB_CURSOR_POINTER] = XCreateFontCursor(ob_display, XC_left_ptr); - ob_cursors[OB_CURSOR_BUSY] = + cursors[OB_CURSOR_BUSY] = XCreateFontCursor(ob_display, XC_watch); - ob_cursors[OB_CURSOR_MOVE] = + cursors[OB_CURSOR_MOVE] = XCreateFontCursor(ob_display, XC_fleur); - ob_cursors[OB_CURSOR_NORTH] = + cursors[OB_CURSOR_NORTH] = XCreateFontCursor(ob_display, XC_top_side); - ob_cursors[OB_CURSOR_NORTHEAST] = + cursors[OB_CURSOR_NORTHEAST] = XCreateFontCursor(ob_display, XC_top_right_corner); - ob_cursors[OB_CURSOR_EAST] = + cursors[OB_CURSOR_EAST] = XCreateFontCursor(ob_display, XC_right_side); - ob_cursors[OB_CURSOR_SOUTHEAST] = + cursors[OB_CURSOR_SOUTHEAST] = XCreateFontCursor(ob_display, XC_bottom_right_corner); - ob_cursors[OB_CURSOR_SOUTH] = + cursors[OB_CURSOR_SOUTH] = XCreateFontCursor(ob_display, XC_bottom_side); - ob_cursors[OB_CURSOR_SOUTHWEST] = + cursors[OB_CURSOR_SOUTHWEST] = XCreateFontCursor(ob_display, XC_bottom_left_corner); - ob_cursors[OB_CURSOR_WEST] = + cursors[OB_CURSOR_WEST] = XCreateFontCursor(ob_display, XC_left_side); - ob_cursors[OB_CURSOR_NORTHWEST] = + cursors[OB_CURSOR_NORTHWEST] = XCreateFontCursor(ob_display, XC_top_left_corner); /* create available keycodes */ - ob_keys[OB_KEY_RETURN] = + keys[OB_KEY_RETURN] = XKeysymToKeycode(ob_display, XStringToKeysym("Return")); - ob_keys[OB_KEY_ESCAPE] = + keys[OB_KEY_ESCAPE] = XKeysymToKeycode(ob_display, XStringToKeysym("Escape")); - ob_keys[OB_KEY_LEFT] = + keys[OB_KEY_LEFT] = XKeysymToKeycode(ob_display, XStringToKeysym("Left")); - ob_keys[OB_KEY_RIGHT] = + keys[OB_KEY_RIGHT] = XKeysymToKeycode(ob_display, XStringToKeysym("Right")); - ob_keys[OB_KEY_UP] = + keys[OB_KEY_UP] = XKeysymToKeycode(ob_display, XStringToKeysym("Up")); - ob_keys[OB_KEY_DOWN] = + keys[OB_KEY_DOWN] = XKeysymToKeycode(ob_display, XStringToKeysym("Down")); prop_startup(); /* get atoms values for the display */ @@ -503,6 +504,8 @@ static void print_help() g_print(" --sm-client-id ID Specify session management ID\n"); g_print(" --sm-disable Disable connection to session manager\n"); #endif + g_print(" --replace Replace the currently running window " + "manager\n"); g_print(" --help Display this help and exit\n"); g_print(" --version Display the version and exit\n"); g_print(" --sync Run in synchronous mode (this is slow and\n" @@ -523,6 +526,8 @@ static void parse_args(int argc, char **argv) exit(0); } else if (!strcmp(argv[i], "--g-fatal-warnings")) { g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); + } else if (!strcmp(argv[i], "--replace")) { + ob_replace_wm = TRUE; } else if (!strcmp(argv[i], "--sync")) { xsync = TRUE; #ifdef USE_SM @@ -594,13 +599,13 @@ void ob_exit() Cursor ob_cursor(ObCursor cursor) { g_assert(cursor < OB_NUM_CURSORS); - return ob_cursors[cursor]; + return cursors[cursor]; } KeyCode ob_keycode(ObKey key) { g_assert(key < OB_NUM_KEYS); - return ob_keys[key]; + return keys[key]; } ObState ob_state() diff --git a/openbox/openbox.h b/openbox/openbox.h index f5129ecc..a9d32688 100644 --- a/openbox/openbox.h +++ b/openbox/openbox.h @@ -27,6 +27,8 @@ SnDisplay *ob_sn_display; /*! The number of the screen on which we're running */ extern gint ob_screen; +extern gboolean ob_replace_wm; + /* The state of execution of the window manager */ ObState ob_state(); diff --git a/openbox/screen.c b/openbox/screen.c index 58c5b2e5..3e3b9632 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -52,6 +52,91 @@ static void sn_event_func(SnMonitorEvent *event, void *data); static void set_root_cursor(); +static gboolean replace_wm() +{ + char *wm_sn; + Atom wm_sn_atom; + Window current_wm_sn_owner; + Time timestamp; + + wm_sn = g_strdup_printf("WM_S%d", ob_screen); + wm_sn_atom = XInternAtom(ob_display, wm_sn, FALSE); + + current_wm_sn_owner = XGetSelectionOwner(ob_display, wm_sn_atom); + if (current_wm_sn_owner) { + if (!ob_replace_wm) { + g_message("A window manager is already running on screen %d", + ob_screen); + return FALSE; + } + xerror_set_ignore(TRUE); + xerror_occured = FALSE; + + /* We want to find out when the current selection owner dies */ + XSelectInput(ob_display, current_wm_sn_owner, StructureNotifyMask); + XSync(ob_display, FALSE); + + xerror_set_ignore(FALSE); + if (xerror_occured) + current_wm_sn_owner = None; + } + + { + /* Generate a timestamp */ + XEvent event; + + XSelectInput(ob_display, screen_support_win, PropertyChangeMask); + + XChangeProperty(ob_display, screen_support_win, + prop_atoms.wm_class, prop_atoms.string, + 8, PropModeAppend, NULL, 0); + XWindowEvent(ob_display, screen_support_win, + PropertyChangeMask, &event); + + XSelectInput(ob_display, screen_support_win, NoEventMask); + + timestamp = event.xproperty.time; + } + + XSetSelectionOwner(ob_display, wm_sn_atom, screen_support_win, + timestamp); + + if (XGetSelectionOwner(ob_display, wm_sn_atom) != screen_support_win) { + g_message("Could not acquire window manager selection on screen %d", + ob_screen); + return FALSE; + } + + /* Wait for old window manager to go away */ + if (current_wm_sn_owner) { + XEvent event; + gulong wait = 0; + const gulong timeout = G_USEC_PER_SEC * 15; /* wait for 15s max */ + + while (wait < timeout) { + if (XCheckWindowEvent(ob_display, current_wm_sn_owner, + StructureNotifyMask, &event) && + event.type == DestroyNotify) + break; + g_usleep(G_USEC_PER_SEC / 10); + wait += G_USEC_PER_SEC / 10; + } + + if (wait >= timeout) { + g_message("Timeout expired while waiting for the current WM to die " + "on screen %d", ob_screen); + return FALSE; + } + } + + /* Send client message indicating that we are now the WM */ + prop_message(RootWindow(ob_display, ob_screen), prop_atoms.manager, + timestamp, wm_sn_atom, 0, 0, SubstructureNotifyMask); + + + return TRUE; +} + gboolean screen_annex() { XSetWindowAttributes attrib; @@ -59,6 +144,21 @@ gboolean screen_annex() gint i, num_support; guint32 *supported; + /* create the netwm support window */ + attrib.override_redirect = TRUE; + screen_support_win = XCreateWindow(ob_display, + RootWindow(ob_display, ob_screen), + -100, -100, 1, 1, 0, + CopyFromParent, InputOutput, + CopyFromParent, + CWOverrideRedirect, &attrib); + XMapRaised(ob_display, screen_support_win); + + if (!replace_wm()) { + XDestroyWindow(ob_display, screen_support_win); + return FALSE; + } + xerror_set_ignore(TRUE); xerror_occured = FALSE; XSelectInput(ob_display, RootWindow(ob_display, ob_screen), @@ -67,6 +167,8 @@ gboolean screen_annex() if (xerror_occured) { g_message("A window manager is already running on screen %d", ob_screen); + + XDestroyWindow(ob_display, screen_support_win); return FALSE; } @@ -80,16 +182,6 @@ gboolean screen_annex() PROP_SET32(RootWindow(ob_display, ob_screen), openbox_pid, cardinal, pid); - /* create the netwm support window */ - attrib.override_redirect = TRUE; - screen_support_win = XCreateWindow(ob_display, - RootWindow(ob_display, ob_screen), - -100, -100, 1, 1, 0, - CopyFromParent, InputOutput, - CopyFromParent, - CWOverrideRedirect, &attrib); - XMapRaised(ob_display, screen_support_win); - /* set supporting window */ PROP_SET32(RootWindow(ob_display, ob_screen), net_supporting_wm_check, window, screen_support_win); -- 2.39.2