public void hide_others(Client client) { for (int i=0;i<clients.Count; i++) { Client c = (Client) clients[i]; if (c.state == InternalState.NORMAL && c != client) hide (c); } }
public void maximize(Client client, bool full_screen) { if (full_screen) client.move_resize (0, 0, display.default_screen.width (), display.default_screen.height ()); else client.move_resize (space); }
public void give_up_focus(Client client) { if (client == focus) set_focus (next_client_normal (client, true), false); }
public bool grant_preference(Client client) { if (client.class_hint == null) return false; String id = client.class_hint.res + ":"; // no focus if (pref.no_focus (id)) client.state = InternalState.NO_FOCUS; // register int keysym = '0' + pref.register (id); if (keysym >= '0') { int keycode = display.input.keysym_to_keycode (keysym); client.register = keycode - display.input.min_keycode; registers [client.register] = client; } int max_width = display.default_screen.width (); int max_height = display.default_screen.height (); // position Rectangle r = pref.position (id); if (r != null) { // similar to geometry parameter processing in X toolkit r.x = (r.x + max_width) % max_width; r.y = (r.y + max_height) % max_height; client.move_resize (r); return true; // user-specified position } return false; }
//throws NotFoundException public Puppet(String [] args) : base(args) { Preference.staticInit(); print_event = option.booleann ("print-event", "dump all events for debug", false); space = option.rectangle ("space", "workspace for normal windows", pref.space ()); about ("0.1", "puppet window manager", "Stephen Tse <*****@*****.**>", "http://escher.sourceforge.net/", "\nFor bindings, check http://escher.sourceforge.net/" + "current/doc/gnu/app/puppet/Puppet.html."); if (help_option) return; /** * addShutdownHook in IBM JDK 1.3 does not seem to work for processing * Control-C. It simply ignores TERM signal instead of calling shutdown * hooks and then exiting. */ // Runtime.getRuntime ().addShutdownHook (new Thread () { // public void run () { System.err.println ("shutting down..."); }}); root = display.default_root; Window.NONE.display = display; // for move pointer xtest = new XTest (display); // for press button registers = new Client [display.input.max_keycode - display.input.min_keycode]; _mit_priority_colors = (Atom) Atom.intern (display, "_MIT_PRIORITY_COLORS"); wm_change_state = (Atom) Atom.intern (display, "WM_CHANGE_STATE"); wm_state = (Atom) Atom.intern (display, "WM_STATE"); wm_colormap_windows = (Atom) Atom.intern (display, "WM_COLORMAP_WINDOWS"); wm_protocols = (Atom) Atom.intern (display, "WM_PROTOCOLS"); wm_take_focus = (Atom) Atom.intern (display, "WM_TAKE_FOCUS"); wm_save_yourself = (Atom) Atom.intern (display, "WM_SAVE_YOURSELF"); wm_delete_window = (Atom) Atom.intern (display, "WM_DELETE_WINDOW"); sm_client_id = (Atom) Atom.intern (display, "SM_CLIENT_ID"); wm_client_leader = (Atom) Atom.intern (display, "WM_CLIENT_LEADER"); wm_window_role = (Atom) Atom.intern (display, "WM_WINDOW_ROLE"); control_root_window (); scan_children (); focus = (Client) Client.intern (root.pointer ().child ()); focus.set_input_focus (); grab_keybut (); Console.WriteLine ("Initialization completed."); while (!exit_now) read_and_dispatch_event (); }
public void deny_focus(Client client) { client.state = InternalState.NO_FOCUS; give_up_focus (client); }
/** * @see #next_client(Client, bool) */ public Client next_client_same_class(Client from, bool reverse) { Client next = next_client_normal (from, reverse); if (next == null) return null; // prevent looping if (focus_base.class_hint != null && next.class_hint != null && focus_base.class_hint.class_Equals (next.class_hint)) return next; return next_client_same_class (next, reverse); // recursive }
public void when_button_press(ButtonPress evt) { /* Because we are doing grabbing on root window, we should not check * <code>event.window()</code> since it always Equals to * {@link #root}. Instead, check <code>event.child()</code>. */ bool control_down = (evt.state () & gnu.x11.Input.CONTROL_MASK) != 0; bool meta_down = (evt.state () & gnu.x11.Input.META_MASK) != 0; bool on_root = evt.child_id () == 0; if (meta_down && on_root) { // `lanuch-on-root' Process.Start (pref.launch_on_root ()); return; } if (!meta_down && on_root) { // `pointer-root-focus' root.set_input_focus (); return; } Client client = (Client) Client.intern (display, evt.child_id ()); if (client.early_unmapped || client.early_destroyed) return; if (!control_down) return; int button = evt.detail (); switch (button) { case gnu.x11.Input.BUTTON1: if (meta_down) // `delete-window' client.delete (); else { // `focus-with-raise' // same as set_focus () client.raise (); focus = client; focus.set_input_focus (); update_client_order (focus); } break; case gnu.x11.Input.BUTTON2: // `focus-without-raise' focus = client; focus.set_input_focus (); update_client_order (focus); break; case gnu.x11.Input.BUTTON3: if (meta_down) client.kill (); // `kill-window' else { // `lower-behind' // give focus to some other window (under pointer) client.lower (); focus = (Client) Client.intern (root.pointer ().child ()); focus.set_input_focus (); update_client_order (focus); // != client } break; } }
/** * @see #next_client(Client, bool) */ public Client next_client_first_char(Client from, bool reverse, char c, bool all) { Client next = next_client (from, reverse); if (next == null) return null; // prevent looping bool state = all ? // no UNMAPPED next.state == InternalState.NORMAL | next.state == InternalState.HIDDEN | next.state == InternalState.NO_FOCUS : next.state == InternalState.NORMAL; if (next.class_hint != null) { String c1 = next.class_hint.res.Substring (0, 1); String c2 = new String(new char[]{c}); if (state && next.class_hint.res.Length > 0 && String.Compare(c1,c2,true)==0) return next; } return next_client_first_char (next, reverse, c, all); // recursive }
/** * @see #next_client(Client, bool) */ public Client next_client_normal(Client from, bool reverse) { Client next = next_client (from, reverse); if (next == null) return null; // prevent looping if (next.state == InternalState.NORMAL) return next; return next_client_normal (next, reverse); // recursive }
/** * @see #next_client(Client, bool) */ public Client next_client_different_class(Client from, bool reverse) { Client next = next_client_normal (from, reverse); if (next == null) return null; // prevent looping /* Check if WM-CLASS of next window is different from all we have * processed so far since first pressing SUPER-TAB. * * Respect null res_class. */ String res_class = ""; if (next.class_hint != null) res_class = next.class_hint.res_class (); if (!focus_so_far.Contains (res_class)) { focus_so_far.Add (res_class); return next; } return next_client_different_class (next, reverse); // recursive }
public Client next_client(Client from, bool reverse) { int index = clients.IndexOf (from); int n = clients.Count; // + n for no negative value // % n for cycle index = (reverse ? index-1+n : index+1+n) % n; Client next = (Client) clients[index]; /* Detect looping. * * Case !focus_key_pressed: focus is always at the top of * clients, i.e., the end of the ArrayList. next == focus means we * are searching in a loop. We return null to signal it. Callers should * quit recursive searching, and return null to set_focus, which does * nothing (as search fails). * * Case focus_key_pressed: focus_base is the last active window. * Note orders of windows in clients stays constants during * focus_key_pressed, and thus focus cannot be used to detect * looping. next == focus_base means we are searching in a loop. * We return null to signal it. Callers should quit recursive * searching, and return null to set_focus, which, however, sets focus * to focus_base, to allow circular tabbing. * * Note that returning null (instead of focus_base) is critical in * next_* () methods as, say, next_client_normal () will be called by, * say, next_client_first_char (), returning null in next_client_normal * () prevents looping in next_client_first_char (). */ if (focus_key_pressed && next == focus_base) return null; if (!focus_key_pressed && next == focus) return null; if (next.early_unmapped || next.early_destroyed) return next_client (next, reverse); else return next; }
public void minimize(Client client) { client.width = client.size_hints == null || client.size_hints.min_width () == 0 ? client.width/2 : client.size_hints.min_width (); client.height = client.size_hints == null || client.size_hints.min_height () == 0 ? client.height/2 : client.size_hints.min_height (); client.resize (); relocate (client); }
public void unhide(Client client) { if (client.state != InternalState.HIDDEN) return; /* Do not set client.state here. Do it right in * {@link #when_map_notify(MapNotify)}. */ client.map (); }
// find another client of same res_name and res_class public void register_fall_back(Client client) { if (client.register == -1) return; Client fall_back = null; if (client.class_hint != null) for (int i=0;i<clients.Count;i++) { Client c = (Client) clients[i]; if (c != client // another! && c.class_hint.Equals (client.class_hint) && !c.early_unmapped && !c.early_destroyed) { fall_back = c; break; } } registers [client.register] = fall_back; client.register = -1; }
public void update_client_order(Client client) { clients.Remove (client); clients.Add (client); }
public void relocate(Client client) { int x_range = space.width - client.width; int y_range = space.height - client.height; if (x_range < 0) x_range = 0; if (y_range < 0) y_range = 0; client.x = x_range == 0 ? 0 : random.Next (x_range); client.y = y_range == 0 ? 0 : random.Next (y_range); // origin of space client.x += space.x; client.y += space.y; client.move (); }
public void when_key_press(KeyPress evt) { keycode = evt.detail (); int keystate = evt.state (); keysym = display.input.keycode_to_keysym (keycode, keystate); shift_down = (keystate & gnu.x11.Input.SHIFT_MASK) != 0; control_down = (keystate & gnu.x11.Input.CONTROL_MASK) != 0; meta_down = (keystate & gnu.x11.Input.META_MASK) != 0; alt_down = (keystate & gnu.x11.Input.ALT_MASK) != 0; base_down = (keystate & gnu.x11.Input.SUPER_MASK) != 0; if (!system_key_pressed && !focus_key_pressed) { int status = root.grab_keyboard (false, Window.ASYNCHRONOUS, Window.ASYNCHRONOUS, Display.CURRENT_TIME); if (status != Window.SUCCESS) throw new Exception ("Failed to grab keyboard"); focus_key_pressed = keysym == Misc.TAB; system_key_pressed = !focus_key_pressed; if (system_key_pressed) return; // if tab (see #next_client) focus_base = focus; focus_so_far.Clear (); if (focus_base.class_hint != null) focus_so_far.Add (focus.class_hint.res_class ()); } if (focus_key_pressed) { if (keysym == Misc.ESCAPE) { // abort-switch-focus focus_key_pressed = false; set_focus (focus_base, true); } else if (keysym == Misc.TAB) key_switch_focus (); return; } if (key_process ()) { // done display.input.ungrab_keyboard (); system_key_pressed = false; prefix0 = prefix1 = 0; argument = 0; argument_negative = false; argument_present = false; } }
public void restore_size(Client client) { client.resize (client.saved_width, client.saved_height); }
public void client_to_register(Client client, int keycode) { int index = client.register = keycode - display.input.min_keycode; Client old = registers [index]; if (old != null) old.register = -1; registers [index] = client; }
public void save_size(Client client) { client.saved_width = client.width; client.saved_height = client.height; }
public void focus_client_first_char(Client client, bool reverse, char c, bool all) { // support only alphabetic window class if (c < 'A' || c > 'z') return; Client next = next_client_first_char (client, reverse, c, all); if (next == null) alert_user ("Client not found: " + c); // possibly hidden and no-focus, as we search all windows // BUT do not grant focus, leave it as before if (all && next != null) unhide (next); set_focus (next, true); }
public void scale_size(Client client, double factor) { client.width = (int)(client.width*factor); client.height = (int)(client.height*factor); client.width = Math.Min (client.width, space.width); client.height = Math.Min (client.height, space.height); client.resize (); relocate (client); }
public void grant_focus(Client client) { if (client.state == InternalState.NO_FOCUS) client.state = InternalState.NORMAL; }
public void set_focus(Client client, bool warp_pointer) { /* Process return value from next_client_* () to prevent looping. * * Case 1 = !focus_key_pressed && client == null. next_client_* fails * to find a matching client. Operation aborts and this method simply * returns. * * Case 2 = focus_key_pressed && client == null. next_client_* detects * a cycle (start pressing TAB on client A, navigate all matching * clients, and come back to client A). Cycling operation restarts and * this method continues with client = focus_base. * * @see #next_client(Client, bool) * @see #focus_so_far */ if (!focus_key_pressed && client == null) return; if (focus_key_pressed && client == null) { client = focus_base; focus_so_far.Clear (); if (focus_base.class_hint != null) focus_so_far.Add (focus_base.class_hint.res_class ()); } client.raise (); // we choose to do it focus = client; /* At this point, and only at this point, we are 100% sure that the * window is mapped and hence can be assigned focus to. Otherwise, an * {@link Error#BAD_WINDOW} will result. */ focus.set_input_focus (); // give hint if (warp_pointer) client.warp_pointer (10, 10); /* For changing focus in focus_key_pressed mode, do not update client order * until the user decides which window to stay with and releases focus * key modifier. * * @see #when_key_release(KeyRelease) */ if (!focus_key_pressed) update_client_order (focus); }
public void hide(Client client) { if (client.state == InternalState.HIDDEN) return; /* Set this state to give hint to {@link * #when_unmap_notify(UnmapNotify)}. * * <p>Do it before <code>client.unmap ()</code>. */ client.state = InternalState.HIDDEN; client.set_wm_state (Window.WMState.ICONIC); client.unmap (); last_hide = client; }
public void toggle_focus(Client client) { if (client.state == InternalState.NORMAL) deny_focus (client); else if (client.state == InternalState.NO_FOCUS) grant_focus (client); }
public void hide_same_class(Client client) { for (int i=0;i<clients.Count; i++) { Client c = (Client) clients[i]; if (c.state == InternalState.NORMAL && c.class_hint != null && c.class_hint.class_Equals (client.class_hint)) hide (c); } }
public void manage(Client client) { if (!clients.Contains (client)) clients.Add (client); // ready for move and resize client.geometry (); // ready for next focus and preference client.class_hint = client.wm_class_hint (); // ready for minimize client.size_hints = client.wm_normal_hints (); // ready for info client.name = client.wm_name (); client.change_save_set (false); if (!grant_preference (client)) // no position preference, do bounding box client.move_resize (client.rectangle ().within (space)); }