+++ /dev/null
-Change Log for "lwm"
-
-2016-02-12 jfc York
- Patches from Greg Kenneky and other fixes for fullscreen windows.
-
- Released lvm-1.2.4.
-
-2013-07-09 jfc York
- Applied a couple of minor patches suggested by Jari Aalto, the
- Debian package maintainer.
-
- Released lwm-1.2.3.
-
-
-2009-11-24 jfc York
- Released lwm-1.2.2.
-
-2009-11-20 jfc York
- Improved performance by only checking for pending X events when the
- socket it ready for reading.
-
- Fixed applyGravity() bug that caused frameless windows to be
- mis-positioned.
-
- Applied a workaround in destroy() to avoid error reports when closing
- windows.
-
-2005-01-28 jfc York
-
- Applied a patch from Chris Reece that ensures that the popup
- menu does not disappear off the bottom of the screen.
-
-2004-09-30 jfc York
-
- Fixed an issue with IRIX 6.5 and lwm, where the root menu could
- not be used because motion events had coordinates with respect to
- the popup, not the root. Fixed by explicitly using the root window
- coordinates.
-
- Released lwm-1.2.1.
-
-2004-09-28 jfc York
-
- Added missing -lSM to no_xmkmf_makefile.
-
-2003-12-09 jfc York
-
- Fixed bug (reported by Matthew Wilcox) where windows with extremely
- long names could cause the pop menu to be unusable. Fixed by
- maintaining a separate, shortened name for the menu, if
- necessary ("this is a very very [...] ry long window name"). This
- takes no account of UTF-8 names as yet.
-
-2003-12-08 jfc York
-
- Fixed bug (reported by Eugene Wong) where resizing the top of
- a window would cause it to jump up several pixels. The height of
- the titlebar was not being considered when calculating mouse
- motion in reshaping_motionnotify().
-
- Modified manage() to avoid autoplacing windows during
- initialisation.
-
- Released lwm-1.2.0.
-
-2003-12-03 jfc York
-
- Applied patch from Elliott that gives focus to new windows in
- click-to-focus mode.
-
- Changed the buttonpress code in disp.c to ignore scroll wheel
- "clicks".
-
- Modified Client_Remove so that, in click-to-focus mode, it
- refocuses on the most sensible window (either the top window,
- or the window that the closing window was a transient for).
-
- Attempted to fix the edit placement bug by adding titleHeight()
- to the supplied X coordinate during a ConfigureRequest event,
- and not attempting to fix clients that don't supply a border
- width during a configure request.
-
- Fixed fullscreen-mode bug where galeon windows appeared to jump
- up and to the left after the first click.
-
- Released lwm-1.1.7.
-
-2003-11-28 jfc York
-
- Changed the behaviour when unhiding a window in click-to-focus mode.
- An unhidden window now automatically gets focus in this mode.
-
- Fixed a small bug in the session management code that could
- cause a crash when lwm quit.
-
- Moved a call to ewmh_set_client_list make before ewmh was
- initialised.
-
- Changed lwm's behaviour when minimising windows. Button three must
- now be pressed and released before the window is hidden (or
- moved to the bottom of the stack). This ensures that lwm swallows
- all the events generated during the operation, and allows the user
- to back out of the operation by moving the mouse out of the window
- before releasing the button.
-
- Removed include of Xm/MwmUtil.h in manage.c, and the HAVE_MOTIF
- kludge from the Imakefile, in favour of copying the few lines
- that are required from Xm/MwmUtil.h (LessTif, so hopefully no
- licensing issues).
-
- Fixed bug that caused the last cursor displayed in a frame
- to be incorrectly used when moving into the frame when the
- root menu was on screen. This is done by brute force -
- see Client_ResetAllCursors().
-
- Released lwm-1.1.6.
-
-2003-11-26 jfc York
-
- Fixed bug in Client_MakeSane that caused occasional crashes
- during window moves/resizing. Should investigate why it occasionally
- gets called with a NULL client.
-
-2003-11-03 jfc York
-
- Added an entry for LeaveNotify in the dispatch table (disp.c).
-
-2003-08-13 jfc York
-
- Removed "error" message when lwm fails to connect to a session
- manager. This isn't actually an error and the message is confusing.
-
-2003-08-01 jfc York
-
- Fixed bug that allowed clients to grab the focus and confuse lwm.
-
- Cleaned up the code for raising and lowering clients, and added
- code to prevent a client from being raised above its transients.
-
- Retired disp.old, and CLOSE_PATCH.txt.
-
- Added an edge resistance to the workarea, so that window may
- be moved to the edge of the workarea without precise mousing,
- as requested by MAD. EDGE_RESIST in lwm.h defines the number of
- pixels of resistance and may be safely set to zero.
-
- Released lwm-1.1.5.
-
-2003-07-31 jfc York
-
- In click-to-focus mode, always draw the box in the frame.
-
-2003-07-29 jfc York
-
- Added a click-to-focus mode. The default remains (sloppy)
- enter-to-focus.
-
- Released lwm-1.1.4.
-
-
-2003-07-28 jfc York
-
- Updated no_xmkmf_makefile to reflect the changes made since 1.01.
-
-2003-07-10 jfc York
-
- Fixed a bug in manage.c than prevented lwm compiling on systems
- with no variety of Motif installed. If this means you, remove
- _DHAVE_MOTIF from Imakefile.
-
- Released lwm-1.1.3.
-
-2003-07-08 jfc York
-
- Added support for NET_MOVERESIZE, but I cannot find any
- applications the want to use it, apart from the keyboard
- variants. I don't know what to do about the keyboard move/resize.
-
-2003-07-03 jfc York
-
- Fixed a few buglets thrown up by running lwm through the compiler
- with all warnings on.
-
-2003-07-02 jfc York
-
- In Client_MakeSane(), added a check to prevent windows being
- moved into a position where they might be completely obscured
- by panels/docks.
-
- Changed ewmh_set_strut() to run Client_MakeSane() across all
- clients when the work area changes. This avoids clients getting
- lost behind panels/docks.
-
- Added support for _NET_WM_STATE_ABOVE and
- _NET_WM_STATE_BELOW. Added fix_stack() to maintain the window
- stack as dictated by the EWMH spec.
-
-2003-07-01 jfc York
-
- Added support for _NET_WM_STRUT. lwm now maintains _NET_WORKAREA
- correctly, and takes the reserved space into account in its
- window placing algorithm.
-
- Released lwm-1.1.2.
-
-2003-06-30 jfc York
-
- Fixed bug that caused tk menus to be badly placed placed by
- sending a configure notify where appropriate in setactive().
-
- Removed compile time option of prepending window title's with
- the client machines's name (PREPEND_CLIENT_MACHINE).
-
- Added i18n support for window titles, using UTF8 names from
- _NET_WM_NAME where available and supported (ie XFree86).
-
- Added code in disp.c to change the pointer in some areas of the
- frame to indicate the action taken by button1. I didn't allow the
- "move" pointer in the titlebar because it looked nasty. Added
- the xkill pointer for the the box. This was a TODO item.
-
-2003-06-28 jfc York
-
- Added GPL headers to all the source files.
-
- Released lwm-1.1.1.
-
-2003-06-27 jfc York
-
- Fixed the bug where each GTK window generated an extra
- window when lwm shut down by unmapping all the clients in
- Client_FreeAll(). Elliott thinks this is bad magic, and that
- the X server should lose the windows, but this doesn't happen
- with XFree86.
-
- Fixed bug, reported by Ed Porter, that caused moving the mouse
- wheel to generate xterms. Wheel mice generate button press events
- on buttons 4 and 5 and shell() wasn't taking this into account.
-
- Fixed silly bug in motifWouldDecorate(): windows should have a
- frame is MWM_DECOR_ALL is set.
-
-2003-06-26 jfc York
-
- Shaped windows now work again. I'm not sure what I changed
- to break it, but the fix was to process shaped windows in
- scanWindowTree (they were previously ignored). They had to be
- clients anyway, if they were to appear in _NET_CLIENT_LIST.
-
-2003-06-25 jfc York
-
- Fixed bug that caused frameless windows to be immoveable.
-
- In manage.c, allowed lwm to fall back on Motif hints when
- deciding if a window should have a frame, if _NET_WM_WINDOW_TYPE
- is not set. This breaks the EWMH spec, in that a window
- without _NET_WM_WINDOW_TYPE should be assumed to have
- _NET_WM_WINDOW_TYPE_NORMAL, but it's the only way for older
- apps to indicate that they don't want decorating, and in the
- absence of Motif hints the default state is
- _NET_WM_WINDOW_TYPE_NORMAL.
-
-2003-06-24 jfc York
-
- Fixed the following TODO item:
- allow users to back out of closing a window if
- they leave the box before letting go of the button.
- Implemented by adding an extra wm_closing_window mode rather
- than adding to the Client structure, as per AMidthune's
- patch. Not sure which is the better solution, though.
-
- Added initial support for _NET_WM_STATE, but only for
- _NET_WM_STATE_SKIP_TASKBAR, _NET_WM_STATE_SKIP_PAGER and
- _NET_WM_HIDDEN.
-
- Added simple hardwired _NET_WM_ALLOWED_ACTIONS support, and
- support for the _NET_CLOSE_WINDOW client message.
-
- First attempt an _WM_STATE_FULLSCREEN and a full-screen mode.
- It's not quite right yet, but useable.
-
-
-2003-06-23 jfc York
-
- Fixed some silly bugs in the session management code.
-
- Added initial EWMH code using the 1.2 spec:
- http://www.freedesktop.org/standards/wm-spec/1.2/html/
- Initial support covers the mechanisms for announcing support
- for EWMH (_NET_SUPPORTED, _NET_SUPPORTING_WM_CHECK), the
- client list and active client (_NET_CLIENT_LIST and
- _NET_ACTIVE_WINDOW), and the window type (_NET_WM_WINDOW_TYPE).
- Windows may now be frameless if their window type indicates.
-
-2003-06-21 jfc York
-
- Added session management so that GNOME2's gnome-session does
- not wait a long timeout when starting the window manager.
-
-2000-02-08 enh Basel
-
- Tried out a patch from Robert Bauer so that it's possible to move
- windows with button 1, if you're in the ``titlebar'' (i.e. not touching
- the top border). This makes it easier for Windows users to cope
- with lwm, and easier for those with two-button mice (or laptops)
- too. At the moment, "mv disp.old disp.c" will give back the old
- behaviour.
-
-1999-11-11 enh Basel
-
- Fixed a cut-and-paste bug in client.c that made the check for
- a window being too large or too small wrong. This bug was found
- by Mike Meyer.
-
-1999-09-22 enh Basel
-
- Altered the button-press code so that it's now easier for unhappy
- users to alter which button performs which function. Simply edit
- lwm.h and modify the three relevant #define statements.
-
-1999-07-19 enh Basel
-
- Added a handler for circulation events so that other programs
- can offer "Alt-Tab" functionality.
-
-1999-07-08 enh Basel
-
- Fixed the cosmetic problem with titlebars of dialogue boxes. If
- this looks to be OK, I can think about another lwm release.
-
-1999-06-10 enh Basel
-
- Incorporated bug fix by Adrian Colley regarding the attempt in
- manage.c to call XSetWindowBorderWidth on an InputOnly window,
- and moved the #include of <signal.h> after <sys/types.h> so that
- lwm can compile on Solaris 2.6. Cosmetic change to move the close
- box to line up with the client window. The effect is spoilt if the
- child insists on drawing a black border around itself, though.
-
-1999-02-07 enh Basel
-
- Title-bars no longer pop up and down. An inactive window has a
- grey title instead. This means less load on the server, no annoying
- "I want to type the information from one window's title-bar into
- the current window but can't" syndrome, and a final solution to
- the race condition that's been with us since the very beginning.
-
- The size feedback no longer pops up as soon as you grab a window,
- because that made it almost impossible to grab a window without
- resizing it.
-
-1998-11-03 enh Basel
-
- The size feedback now pops up as soon as you grab a window,
- rather than waiting for you to actually move.
-
-1998-10-06 enh Basel
-
- Al pointed out that my Sun actually has two framebuffers. One
- monitor-lugging later, and I suddenly have a need for a window
- manager that can cope with multiple screens. And here it is!
-
-1998-05-29 enh Basel
-
- Fixed window minimum/maximum height code so that it no longer
- includes the title decoration. Menu now pops down if a window
- disappears while the menu is up.
-
-1998-03-23 enh Basel
-
- Removed unused constant. A little tidying up, renaming. Some
- debugging code removed. The width of the size-feedback window
- is now calculated at run-time depending on the size of the screen.
-
-1998-02-05 enh Basel
-
- Fixed bug found by Marty Olevitch: lwm's automatic window
- placement heuristics broke down when either the right or bottom
- of the display were reached.
- Changed menu placement to ensure that the menu is fully
- on-screen.
-
-1998-01-06 enh Basel
-
- Fixed bug found by J. Han whereby lwm dumped core if a window
- disappeared while being reshaped.
-
-1997-09-01 enh Basel
-
- "Push to back" functionality moved from button 3 click in box
- to button 3 click anywhere in frame with Shift held down.
-
-1997-08-29 enh Basel
-
- Simple version numbering introduced.
-
-1997-08-25 enh Basel
-
- Fixed stupid mistake introduced with the last change, with regard
- to setting the input focus.
-
-1997-08-22 enh Basel
-
- Xt applications (strictly, applications whose window title is
- the same as their class hint resource name) no longer have a
- title bar. This means it's more awkward to kill them, but that
- they don't have pointless decoration.
-
-1997-08-07 enh Basel
-
- Bug related to hiding windows fixed.
-
-1997-08-06 enh Basel
-
- The size indictor now has the correct GC settings. Whoops!
- Improved handling of WM_NORMAL_HINTS. Amongst other things,
- this means that size reporting of xterm et al is more reliable.
-
-1997-07-31 enh Basel
-
- Reshaping now uses the popup to display the current width and
- height of the window being reshaped (in whatever units it uses).
-
-1997-07-04 enh Swanwick
-
- Clicking button 3 on the "box" pushes the window to the bottom.
- Changing image in xv no longer causes the window to gravitate to
- the southeast. There's an ICCCM convention that clients should
- set the border width with each ConfigureWindow request. As usual,
- many clients fail to follow this convention. I get the distinct
- impression that the very reason for the existance of the Xt
- library is because the X11 protocol and ICCCM are so messy and
- involved that the only way to make X11 bearable was to write
- this code once and for all. The menu code has been rewritten,
- changing as a side-effect the order in which hidden windows
- appear on the menu. The rewrite now means that the order is very
- easy to change for experiments like alphabetical ordering etc. I
- like it as it is: a stack.
-
-1997-06-24 enh York
-
- Now handles NoExpose events. Better protocol error reporting.
- Default minimum size calculation improved.
-
-1997-06-23 enh York
-
- Both button 1 and 2 can now have commands associated with them.
- See the documentation for details. Windows whose minimum and
- maximum sizes are identical can no longer be resized. The
- oscillation race condition is now less likely to occur. Some
- dead code removed.
-
-1997-05-25 enh York
-
- lwm now does the right thing with respect to hidden windows on
- exit and startup. a hidden window is now re-hidden if lwm exits
- and is then restarted.
-
-1997-05-21 enh York
-
- Fixed a bug that meant a client could confuse lwm by remapping
- a hidden window: the menu of hidden windows wasn't being updated.
-
-1997-05-16 enh York
-
- A bug relating to ConfigureRequests on the current window caused
- the title-bar to be redrawn incorrectly. Once again, this came
- to light with xv.
-
- The "New Shell" command has gone from the button 3 menu, and
- button 2 now performs this function.
-
-1997-05-09 enh York
-
- This version fixes a bug relating to ConfigureRequests. Client
- windows that were resized under program control were resized,
- but the client was misinformed as to what change had actually
- taken place. xv's optimised redraw, for example, missed out on
- part of the window because of this.
- The behaviour with regard to hidden windows on exit has also
- changed. They're now remapped, but lowered in the window stack.
- This means that you don't lose them, but that they don't
- obliterate the more important windows on your screen if you kill
- the window manager.
-
-- Initial announcement on comp.windows.x.announce -
+++ /dev/null
-XCOMM lwm, a window manager for X11
-XCOMM Copyright (C) 1997-2016 Elliott Hughes, James Carter
-XCOMM
-XCOMM This program is free software; you can redistribute it and/or
-XCOMM modify it under the terms of the GNU General Public License
-XCOMM as published by the Free Software Foundation; either version 2
-XCOMM of the License, or (at your option) any later version.
-XCOMM
-XCOMM This program is distributed in the hope that it will be useful,
-XCOMM but WITHOUT ANY WARRANTY; without even the implied warranty of
-XCOMM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-XCOMM GNU General Public License for more details.
-XCOMM
-XCOMM You should have received a copy of the GNU General Public License
-XCOMM along with this program; if not, write to the Free Software
-XCOMM Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-INCLUDES = -I$(TOP)
-DEPLIBS = $(DEPXLIB) $(DEPSMLIB)
-LOCAL_LIBRARIES = $(XLIB) $(SMLIB) -lICE
-DEFINES = -DSHAPE
-
-HEADERS = lwm.h ewmh.h
-SRCS = lwm.c manage.c mouse.c client.c cursor.c error.c disp.c shape.c resource.c session.c ewmh.c
-OBJS = ${SRCS:.c=.o}
-
-ComplexProgramTarget(lwm)
-
-${OBJS}: ${HEADERS}
--- /dev/null
+#!/bin/sh
+cc -g -o lwm *.c -I. -I/usr/X11/include/ -L/usr/X11/lib -lX11 -lICE -lSM
Client *current;
Client *last_focus = NULL;
static Client *clients;
-
-static int popup_width; /* The width of the size-feedback window. */
-
Edge interacting_edge;
static void sendClientMessage(Window, Atom, long, long);
Client *
-client_head(void) {
- return clients;
+Client_List(void) {
+ return clients;
}
void
-setactive(Client *c, int on, long timestamp) {
- int inhibit;
-
- if (c == 0 || hidden(c))
- return;
-
- inhibit = !c->framed;
-
- if (!inhibit) {
- XMoveResizeWindow(dpy, c->parent,
- c->size.x, c->size.y - titleHeight(),
- c->size.width, c->size.height + titleHeight());
- XMoveWindow(dpy, c->window, border, border + titleHeight());
- sendConfigureNotify(c);
- }
-
- if (on && c->accepts_focus) {
- XSetInputFocus(dpy, c->window, RevertToPointerRoot, CurrentTime);
- if (c->proto & Ptakefocus)
- sendClientMessage(c->window, wm_protocols,
- wm_take_focus, timestamp);
- if (focus_mode == focus_click) {
- XUngrabButton(dpy, AnyButton, AnyModifier, c->window);
- }
- cmapfocus(c);
- }
-
- /* FIXME: is this sensible? */
- if (on && !c->accepts_focus) {
- XSetInputFocus(dpy, None, RevertToPointerRoot, CurrentTime);
- }
-
- if (!on && focus_mode == focus_click)
- XGrabButton(dpy, AnyButton, AnyModifier, c->window, False,
- ButtonPressMask | ButtonReleaseMask, GrabModeAsync,
- GrabModeSync, None, None);
-
- if (!inhibit)
- Client_DrawBorder(c, on);
+Client_SetActive(Client *c, int on, long timestamp) {
+ int inhibit;
+
+ if (c == 0)
+ return;
+
+ inhibit = !c->framed;
+
+ if (!inhibit) {
+ XMoveResizeWindow(dpy, c->parent,
+ c->size.x, c->size.y - titleHeight(),
+ c->size.width, c->size.height + titleHeight());
+ XMoveWindow(dpy, c->window, border, border + titleHeight());
+ sendConfigureNotify(c);
+ }
+
+ if (on && Client_HasFlags(c, F_ACCEPT_FOCUS)) {
+ XSetInputFocus(dpy, c->window, RevertToPointerRoot, CurrentTime);
+ if (Client_HasFlags(c, F_EWMH_TAKE_FOCUS))
+ sendClientMessage(c->window, wm_protocols,
+ wm_take_focus, timestamp);
+ }
+
+ /* FIXME: is this sensible? */
+ if (on && !Client_HasFlags(c, F_ACCEPT_FOCUS)) {
+ XSetInputFocus(dpy, None, RevertToPointerRoot, CurrentTime);
+ }
+
+ if (!inhibit)
+ Client_DrawFrame(c, on);
}
void
-Client_DrawBorder(Client *c, int active) {
- int quarter = (border + titleHeight()) / 4;
-
- if (c->parent == c->screen->root || c->parent == 0 ||
- c->framed == False || c->wstate.fullscreen == True)
- return;
-
- XSetWindowBackground(dpy, c->parent,
- active ? c->screen->black : c->screen->gray);
- XClearWindow(dpy, c->parent);
-
- /* Draw the ``box''. */
- if (active || focus_mode == focus_click) {
- XDrawRectangle(dpy, c->parent, c->screen->gc,
- quarter + 2, quarter, 2 * quarter, 2 * quarter);
- }
-
- /* Draw window title. */
- if (c->name != 0) {
-#ifdef X_HAVE_UTF8_STRING
- if (c->name_utf8 == True)
- Xutf8DrawString(dpy, c->parent, font_set,
- c->screen->gc, border + 2 + (3 * quarter),
- 2 + ascent(font_set_ext),
- c->name, c->namelen);
- else
-#endif
- XmbDrawString(dpy, c->parent, font_set,
- c->screen->gc, border + 2 + (3 * quarter),
- 2 + ascent(font_set_ext),
- c->name, c->namelen);
- }
+Client_DrawFrame(Client *c, int active) {
+ int quarter = (border + titleHeight()) / 4;
+
+ if (c->parent == c->screen->root || c->parent == 0 || c->framed == False)
+ return;
+
+ XSetWindowBackground(dpy, c->parent,
+ active ? c->screen->black : c->screen->gray);
+ XClearWindow(dpy, c->parent);
+
+ /* Draw window title. */
+ if (c->name != 0) {
+ Xutf8DrawString(dpy, c->parent, font_set,
+ c->screen->gc, border + 2 + (3 * quarter),
+ 2 + ascent(font_set_ext),
+ c->name, c->namelen);
+ }
}
Client *
Client_Get(Window w) {
- Client * c;
+ Client * c;
- if (w == 0 || (getScreenFromRoot(w) != 0))
- return 0;
+ if (w == 0 || (getScreenFromRoot(w) != 0))
+ return 0;
- /* Search for the client corresponding to this window. */
- for (c = clients; c; c = c->next)
- if (c->window == w || c->parent == w)
- return c;
+ /* Search for the client corresponding to this window. */
+ for (c = clients; c; c = c->next)
+ if (c->window == w || c->parent == w)
+ return c;
- /* Not found. */
- return 0;
+ /* Not found. */
+ return 0;
}
Client *
Client_Add(Window w, Window root) {
- Client * c;
-
- if (w == 0 || w == root)
- return 0;
-
- /* Search for the client corresponding to this window. */
- for (c = clients; c != 0; c = c->next)
- if (c->window == w || c->parent == w)
- return c;
-
- c = calloc(1, sizeof *c);
- c->window = w;
- c->parent = root;
- c->framed = False;
- c->hidden = False;
- c->state = WithdrawnState;
- c->internal_state = INormal;
- c->cmap = None;
- c->name = 0;
- c->menu_name = 0;
- c->cursor = ENone;
- c->wtype = WTypeNone;
- c->wstate.skip_taskbar = False;
- c->wstate.skip_pager = False;
- c->wstate.fullscreen = False;
- c->wstate.above = False;
- c->wstate.below = False;
- c->strut.left = 0;
- c->strut.right = 0;
- c->strut.top = 0;
- c->strut.bottom = 0;
- c->ncmapwins = 0;
- c->cmapwins = 0;
- c->wmcmaps = 0;
- c->accepts_focus = 1;
- c->next = clients;
-
- /* Add to head of list of clients. */
- clients = c;
- return clients;
+ Client * c;
+
+ if (w == 0 || w == root)
+ return 0;
+
+ /* Search for the client corresponding to this window. */
+ for (c = clients; c != 0; c = c->next)
+ if (c->window == w || c->parent == w)
+ return c;
+
+ c = calloc(1, sizeof *c);
+ c->window = w;
+ c->parent = root;
+ c->framed = False;
+ c->state = WithdrawnState;
+ c->internal_state = INormal;
+ c->name = 0;
+ c->cursor = ENone;
+ c->wtype = WTypeNone;
+ c->flags |= F_ACCEPT_FOCUS;
+ c->next = clients;
+
+ /* Add to head of list of clients. */
+ clients = c;
+ return clients;
}
void
Client_Remove(Client *c) {
- Client * cc;
- ScreenInfo *screen = c->screen;
-
- if (c == 0)
- return;
-
- /* Remove the client from our client list. */
- if (c == clients)
- clients = c->next;
- for (cc = clients; cc && cc->next; cc = cc->next) {
- if (cc->next == c)
- cc->next = cc->next->next;
- }
-
- /* Remove it from the hidden list if it's hidden. */
- if (hidden(c)) {
- /* Al Smith points out that you also want to get rid of the menu
- * so you can be sure that if you let go on an item, you always
- * get the corresponding window. */
- if (mode == wm_menu_up) {
- XUnmapWindow(dpy, current_screen->popup);
- mode = wm_idle;
- }
- }
-
- /* A deleted window can no longer be the current window. */
- if (c == current || (current == NULL && c == last_focus)) {
- Client *focus = NULL;
-
- /* As pointed out by J. Han, if a window disappears while it's
- * being reshaped you need to get rid of the size indicator. */
- if (c == current && mode == wm_reshaping) {
- XUnmapWindow(dpy, current_screen->popup);
- mode = wm_idle;
- }
- if (focus_mode == focus_click) {
- /* Try and find the window that this was a transient
- * for, else focus on the top client. */
- if (c->trans != None) {
- focus = Client_Get(c->trans);
- }
- if (!focus) {
- Window dw1;
- Window dw2;
- Window *wins;
- unsigned int nwins;
-
- XQueryTree(dpy, c->screen->root, &dw1,
- &dw2, &wins, &nwins);
- while (nwins) {
- focus = Client_Get(wins[nwins -1]);
- if (focus) break;
- nwins--;
- }
- if (wins) XFree(wins);
- }
- }
- Client_Focus(focus, CurrentTime);
- }
-
- if (getScreenFromRoot(c->parent) == 0)
- XDestroyWindow(dpy, c->parent);
-
- if (c->ncmapwins != 0) {
- XFree(c->cmapwins);
- free(c->wmcmaps);
- }
-
- if (c->name != 0)
- free(c->name);
- if (c->menu_name != 0)
- free(c->name);
-
- free(c);
-
- ewmh_set_client_list(screen);
- ewmh_set_strut(screen);
+ Client * cc;
+ ScreenInfo *screen = c->screen;
+
+ if (c == 0)
+ return;
+
+ /* Remove the client from our client list. */
+ if (c == clients)
+ clients = c->next;
+ for (cc = clients; cc && cc->next; cc = cc->next) {
+ if (cc->next == c)
+ cc->next = cc->next->next;
+ }
+
+ /* A deleted window can no longer be the current window. */
+ if (c == current || (current == NULL && c == last_focus)) {
+ Client *focus = NULL;
+ Client_Focus(focus, CurrentTime);
+ }
+
+ if (getScreenFromRoot(c->parent) == 0)
+ XDestroyWindow(dpy, c->parent);
+
+ if (c->name != 0)
+ free(c->name);
+ free(c);
+
+ ewmh_set_client_list(screen);
}
void
Client_MakeSane(Client *c, Edge edge, int *x, int *y, int *dx, int *dy) {
- Bool horizontal_ok = True;
- Bool vertical_ok = True;
-
- if (edge != ENone) {
- /*
- * Make sure we're not making the window too small.
- */
- if (*dx < c->size.min_width)
- horizontal_ok = False;
- if (*dy < c->size.min_height)
- vertical_ok = False;
-
- /*
- * Make sure we're not making the window too large.
- */
- if (c->size.flags & PMaxSize) {
- if (*dx > c->size.max_width)
- horizontal_ok = False;
- if (*dy > c->size.max_height)
- vertical_ok = False;
- }
-
- /*
- * Make sure the window's width & height are multiples of
- * the width & height increments (not including the base size).
- */
-
- if (c->size.width_inc > 1) {
- int apparent_dx = *dx - 2 * border - c->size.base_width;
- int x_fix = apparent_dx % c->size.width_inc;
-
- switch (edge) {
- case ELeft:
- case ETopLeft:
- case EBottomLeft:
- *x += x_fix;
- /*FALLTHROUGH*/
- case ERight:
- case ETopRight:
- case EBottomRight:
- *dx -= x_fix;
- break;
- default: break;
- }
- }
-
- if (c->size.height_inc > 1) {
- int apparent_dy = *dy - 2 * border - c->size.base_height;
- int y_fix = apparent_dy % c->size.height_inc;
-
- switch (edge) {
- case ETop:
- case ETopLeft:
- case ETopRight:
- *y += y_fix;
- /*FALLTHROUGH*/
- case EBottom:
- case EBottomLeft:
- case EBottomRight:
- *dy -= y_fix;
- break;
- default: break;
- }
- }
-
- /*
- * Check that we may change the client horizontally and vertically.
- */
-
- if (c->size.width_inc == 0)
- horizontal_ok = False;
- if (c->size.height_inc == 0)
- vertical_ok = False;
- }
-
- /* Ensure that at least one border is not entirely within the
- * reserved areas. Keeping clients completely within the
- * the workarea is too restrictive, but this measure means they
- * should always be accessible.
- * Of course all of this is only applicable if the client doesn't
- * set a strut itself. jfc
- */
- if (c->strut.left == 0 && c->strut.right == 0 &&
- c->strut.top == 0 && c->strut.bottom == 0) {
- if ((int)(*y + border) >=
- (int)(c->screen->display_height -
- c->screen->strut.bottom)) {
- *y = c->screen->display_height -
- c->screen->strut.bottom -border;
- }
- if ((int)(*y + c->size.height - border) <=
- (int)c->screen->strut.top) {
- *y = c->screen->strut.top + border - c->size.height;
- }
- if ((int)(*x + border) >=
- (int)(c->screen->display_width -
- c->screen->strut.right)) {
- *x = c->screen->display_width -
- c->screen->strut.right -border;
- }
- if ((int)(*x + c->size.width - border) <=
- (int)c->screen->strut.left) {
- *x = c->screen->strut.left + border - c->size.width;
- }
- }
-
- /*
- * Introduce a resistance to the workarea edge, so that windows may
- * be "thrown" to the edge of the workarea without precise mousing,
- * as requested by MAD.
- */
- if (*x < (int)c->screen->strut.left &&
- *x > ((int)c->screen->strut.left - EDGE_RESIST)) {
- *x = (int)c->screen->strut.left;
- }
- if ((*x + c->size.width) >
- (int)(c->screen->display_width - c->screen->strut.right) &&
- (*x + c->size.width) <
- (int)(c->screen->display_width - c->screen->strut.right + EDGE_RESIST)) {
- *x = (int)(c->screen->display_width - c->screen->strut.right -
- c->size.width);
- }
- if ((*y - titleHeight()) < (int)c->screen->strut.top &&
- (*y - titleHeight()) >
- ((int)c->screen->strut.top - EDGE_RESIST)) {
- *y = (int)c->screen->strut.top + titleHeight();
- }
- if ((*y + c->size.height) >
- (int)(c->screen->display_height - c->screen->strut.bottom) &&
- (*y + c->size.height) <
- (int)(c->screen->display_height - c->screen->strut.bottom + EDGE_RESIST)) {
- *y = (int)(c->screen->display_height - c->screen->strut.bottom -
- c->size.height);
- }
-
- /*
- * Update that part of the client information that we're happy with.
- */
- if (interacting_edge != ENone) {
- if (horizontal_ok) {
- c->size.x = *x;
- c->size.width = *dx;
- }
- if (vertical_ok) {
- c->size.y = *y;
- c->size.height = *dy;
- }
- } else {
- if (horizontal_ok)
- c->size.x = *x;
- if (vertical_ok)
- c->size.y = *y;
- }
-}
-
-void
-size_expose(void) {
- int width, height;
- char buf[4*2 + 3 + 1];
-
- width = current->size.width - 2*border;
- height = current->size.height - 2*border;
-
- /* This dance ensures that we report 80x24 for an xterm even when
- * it has a scrollbar. */
- if (current->size.flags & (PMinSize|PBaseSize) && current->size.flags & PResizeInc) {
- if (current->size.flags & PBaseSize) {
- width -= current->size.base_width;
- height -= current->size.base_height;
- } else {
- width -= current->size.min_width;
- height -= current->size.min_height;
- }
- }
-
- if (current->size.width_inc != 0)
- width /= current->size.width_inc;
- if (current->size.height_inc != 0)
- height /= current->size.height_inc;
-
- snprintf(buf, sizeof(buf), "%i x %i", width, height);
- XmbDrawString(dpy, current_screen->popup, popup_font_set,
- current_screen->size_gc,
- (popup_width - popupWidth(buf, strlen(buf))) / 2,
- ascent(popup_font_set_ext) + 1, buf, strlen(buf));
+ Bool horizontal_ok = True;
+ Bool vertical_ok = True;
+
+ if (edge != ENone) {
+ /*
+ * Make sure we're not making the window too small.
+ */
+ if (*dx < c->size.min_width)
+ horizontal_ok = False;
+ if (*dy < c->size.min_height)
+ vertical_ok = False;
+
+ /*
+ * Make sure we're not making the window too large.
+ */
+ if (c->size.flags & PMaxSize) {
+ if (*dx > c->size.max_width)
+ horizontal_ok = False;
+ if (*dy > c->size.max_height)
+ vertical_ok = False;
+ }
+
+ /*
+ * Make sure the window's width & height are multiples of
+ * the width & height increments (not including the base size).
+ */
+
+ if (c->size.width_inc > 1) {
+ int apparent_dx = *dx - 2 * border - c->size.base_width;
+ int x_fix = apparent_dx % c->size.width_inc;
+
+ switch (edge) {
+ case ELeft:
+ case ETopLeft:
+ case EBottomLeft:
+ *x += x_fix;
+ /*FALLTHROUGH*/
+ case ERight:
+ case ETopRight:
+ case EBottomRight:
+ *dx -= x_fix;
+ break;
+ default: break;
+ }
+ }
+
+ if (c->size.height_inc > 1) {
+ int apparent_dy = *dy - 2 * border - c->size.base_height;
+ int y_fix = apparent_dy % c->size.height_inc;
+
+ switch (edge) {
+ case ETop:
+ case ETopLeft:
+ case ETopRight:
+ *y += y_fix;
+ /*FALLTHROUGH*/
+ case EBottom:
+ case EBottomLeft:
+ case EBottomRight:
+ *dy -= y_fix;
+ break;
+ default: break;
+ }
+ }
+
+ /*
+ * Check that we may change the client horizontally and vertically.
+ */
+
+ if (c->size.width_inc == 0)
+ horizontal_ok = False;
+ if (c->size.height_inc == 0)
+ vertical_ok = False;
+ }
+
+ /*
+ * Update that part of the client information that we're happy with.
+ */
+ if (interacting_edge != ENone) {
+ if (horizontal_ok) {
+ c->size.x = *x;
+ c->size.width = *dx;
+ }
+ if (vertical_ok) {
+ c->size.y = *y;
+ c->size.height = *dy;
+ }
+ } else {
+ if (horizontal_ok)
+ c->size.x = *x;
+ if (vertical_ok)
+ c->size.y = *y;
+ }
}
static void
Client_OpaquePrimitive(Client *c, Edge edge) {
- Cursor cursor;
- int ox, oy;
-
- if (c == 0 /*|| c != current*/)
- return;
-
- /* Find out where we've got hold of the window. */
- getMousePosition(&ox, &oy);
- ox = c->size.x - ox;
- oy = c->size.y - oy;
-
- cursor = getEdgeCursor(edge);
- XChangeActivePointerGrab(dpy, ButtonMask | PointerMotionHintMask |
- ButtonMotionMask | OwnerGrabButtonMask, cursor, CurrentTime);
-
- /*
- * Store some state so that we can get back into the main event
- * dispatching thing.
- */
- interacting_edge = edge;
- start_x = ox;
- start_y = oy;
- mode = wm_reshaping;
- ewmh_set_client_list(c->screen);
+ Cursor cursor;
+ int ox, oy;
+
+ if (c == 0 /*|| c != current*/)
+ return;
+
+ /* Find out where we've got hold of the window. */
+ getMousePosition(&ox, &oy);
+ ox = c->size.x - ox;
+ oy = c->size.y - oy;
+
+ cursor = getEdgeCursor(edge);
+ XChangeActivePointerGrab(dpy, ButtonMask | PointerMotionHintMask |
+ ButtonMotionMask | OwnerGrabButtonMask, cursor, CurrentTime);
+
+ /*
+ * Store some state so that we can get back into the main event
+ * dispatching thing.
+ */
+ interacting_edge = edge;
+ start_x = ox;
+ start_y = oy;
+ mode = wm_reshaping;
+ ewmh_set_client_list(c->screen);
}
void
Client_Lower(Client *c)
{
- if (c == 0) return;
+ if (c == 0) return;
- XLowerWindow(dpy, c->window);
- if (c->framed) XLowerWindow(dpy, c->parent);
- ewmh_set_client_list(c->screen);
+ XLowerWindow(dpy, c->window);
+ if (c->framed) XLowerWindow(dpy, c->parent);
+ ewmh_set_client_list(c->screen);
}
void
Client_Raise(Client *c)
{
- Client * trans;
+ Client * trans;
- if (c == 0) return;
+ if (c == 0) return;
- if (c->framed) XRaiseWindow(dpy, c->parent);
- XRaiseWindow(dpy, c->window);
+ if (c->framed) XRaiseWindow(dpy, c->parent);
+ XRaiseWindow(dpy, c->window);
- for (trans = clients; trans != NULL; trans = trans->next) {
- if (trans->trans != c->window &&
- !(c->framed == True && trans->trans == c->parent))
- continue;
- if (trans->framed) XRaiseWindow(dpy, trans->parent);
- XRaiseWindow(dpy, trans->window);
- }
+ for (trans = clients; trans != NULL; trans = trans->next) {
+ if (trans->trans != c->window &&
+ !(c->framed == True && trans->trans == c->parent))
+ continue;
+ if (trans->framed) XRaiseWindow(dpy, trans->parent);
+ XRaiseWindow(dpy, trans->window);
+ }
- ewmh_set_client_list(c->screen);
+ ewmh_set_client_list(c->screen);
}
void
Client_Close(Client *c) {
- if (c == 0)
- return;
-
- /*
- * Terminate the client nicely if possible. Be brutal otherwise.
- */
- if (c->proto & Pdelete) {
- sendClientMessage(c->window, wm_protocols, wm_delete, CurrentTime);
- } else {
- XKillClient(dpy, c->window);
- }
+ if (c == 0) return;
+ if (Client_HasFlags(c, F_EWMH_DELETE)) {
+ sendClientMessage(c->window, wm_protocols, wm_delete, CurrentTime);
+ } else {
+ XKillClient(dpy, c->window);
+ }
}
void
Client_SetState(Client *c, int state) {
- long data[2];
+ long data[2];
- data[0] = (long) state;
- data[1] = (long) None;
+ data[0] = (long) state;
+ data[1] = (long) None;
- c->state = state;
- XChangeProperty(dpy, c->window, wm_state, wm_state, 32,
- PropModeReplace, (unsigned char *) data, 2);
- ewmh_set_state(c);
-}
-
-static void
-sendClientMessage(Window w, Atom a, long data0, long data1) {
- XEvent ev;
- long mask;
-
- memset(&ev, 0, sizeof(ev));
- ev.xclient.type = ClientMessage;
- ev.xclient.window = w;
- ev.xclient.message_type = a;
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = data0;
- ev.xclient.data.l[1] = data1;
- mask = (getScreenFromRoot(w) != 0) ? SubstructureRedirectMask : 0L;
-
- XSendEvent(dpy, w, False, mask, &ev);
+ c->state = state;
}
extern void
Client_ResetAllCursors(void) {
- Client *c;
- XSetWindowAttributes attr;
-
- for (c = clients; c; c = c->next) {
- if (c->framed != True) continue;
- attr.cursor = c->screen->root_cursor;
- XChangeWindowAttributes(dpy, c->parent,
- CWCursor, &attr);
- c->cursor = ENone;
- }
-}
-
-extern void
-Client_FreeAll(void) {
- Client *c;
- XWindowChanges wc;
-
- for (c = clients; c; c = c->next) {
- int not_mapped = !normal(c);
-
- /* elliott thinks leaving window unmapped causes the x server
- * to lose them when the window manager quits. it doesn't
- * happen to me with XFree86's Xnest, but unmapping the
- * windows stops gtk window generating an extra window when
- * the window manager quits.
- * who is right? only time will tell....
- */
- XUnmapWindow(dpy, c->parent);
- XUnmapWindow(dpy, c->window);
- /* Remap the window if it's hidden.
- if (not_mapped) {
- XMapWindow(dpy, c->parent);
- XMapWindow(dpy, c->window);
- } */
-
- /* Reparent it, and then push it to the bottom if it was hidden. */
- XReparentWindow(dpy, c->window, c->screen->root, c->size.x, c->size.y);
- if (not_mapped)
- XLowerWindow(dpy, c->window);
-
- /* Give it back its initial border width. */
- wc.border_width = c->border;
- XConfigureWindow(dpy, c->window, CWBorderWidth, &wc);
- }
-}
-
-extern void
-Client_ColourMap(XEvent *e) {
- int i;
- Client * c;
-
- for (c = clients; c; c = c->next) {
- for (i = 0; i < c->ncmapwins; i++) {
- if (c->cmapwins[i] == e->xcolormap.window) {
- c->wmcmaps[i] = e->xcolormap.colormap;
- if (c == current)
- cmapfocus(c);
- return;
- }
- }
- }
+ Client *c;
+ XSetWindowAttributes attr;
+
+ for (c = clients; c; c = c->next) {
+ if (c->framed != True) continue;
+ attr.cursor = c->screen->root_cursor;
+ XChangeWindowAttributes(dpy, c->parent,
+ CWCursor, &attr);
+ c->cursor = ENone;
+ }
}
extern void
Client_ReshapeEdge(Client *c, Edge e) {
- Client_OpaquePrimitive(c, e);
+ Client_OpaquePrimitive(c, e);
}
extern void
Client_Move(Client *c) {
- Client_OpaquePrimitive(c, ENone);
+ Client_OpaquePrimitive(c, ENone);
}
extern int
-hidden(Client *c) {
- return c->state == IconicState;
-}
-
-extern int
-withdrawn(Client *c) {
- return c->state == WithdrawnState;
-}
-
-extern int
-normal(Client *c) {
- return c->state == NormalState;
+Client_IsState(Client *c, int state)
+{
+ return c->state == state;
}
extern void
-Client_EnterFullScreen(Client *c) {
- XWindowChanges fs;
-
- memcpy(&c->return_size, &c->size, sizeof(XSizeHints));
- if (c->framed) {
- c->size.x = fs.x = -border;
- c->size.y = fs.y = -border;
- c->size.width = fs.width =
- c->screen->display_width + 2 * border;
- c->size.height = fs.height =
- c->screen->display_height + 2 * border;
- XConfigureWindow(dpy, c->parent,
- CWX | CWY | CWWidth | CWHeight, &fs);
-
- fs.x = border;
- fs.y = border;
- fs.width = c->screen->display_width;
- fs.height = c->screen->display_height;
- XConfigureWindow(dpy, c->window,
- CWX | CWY | CWWidth | CWHeight, &fs);
- XRaiseWindow(dpy,c->parent);
- } else {
- c->size.x = c->size.y = fs.x = fs.y = 0;
- c->size.width = fs.width = c->screen->display_width;
- c->size.height = fs.height = c->screen->display_height;
- XConfigureWindow(dpy, c->window,
- CWX | CWY | CWWidth | CWHeight, &fs);
- XRaiseWindow(dpy,c->window);
- }
- sendConfigureNotify(c);
+Client_Focus(Client *c, Time time) {
+ if (current) {
+ Client_SetActive(current, 0, 0L);
+ XDeleteProperty(dpy, current->screen->root,
+ ewmh_atom[_NET_ACTIVE_WINDOW]);
+ }
+
+ if (!c && current) {
+ last_focus = current;
+ } else {
+ last_focus = NULL;
+ }
+ current = c;
+ if (c) {
+ Client_SetActive(current, 1, time);
+ XChangeProperty(dpy, current->screen->root,
+ ewmh_atom[_NET_ACTIVE_WINDOW],
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *)¤t->window, 1);
+ }
}
extern void
-Client_ExitFullScreen(Client *c) {
- XWindowChanges fs;
-
- memcpy(&c->size, &c->return_size, sizeof(XSizeHints));
- if (c->framed == True) {
- fs.x = c->size.x;
- fs.y = c->size.y - titleHeight();
- fs.width = c->size.width;
- fs.height = c->size.height + titleHeight();
- XConfigureWindow(dpy, c->parent,
- CWX | CWY | CWWidth | CWHeight, &fs);
-
- fs.x = border;
- fs.y = border + titleHeight();
- fs.width = c->size.width -(2 * border);
- fs.height = c->size.height -(2 * border);
- XConfigureWindow(dpy, c->window,
- CWX | CWY | CWWidth | CWHeight, &fs);
- } else {
- fs.x = c->size.x;
- fs.y = c->size.y;
- fs.width = c->size.width;
- fs.height = c->size.height;
- XConfigureWindow(dpy, c->window,
- CWX | CWY | CWWidth | CWHeight, &fs);
- }
- sendConfigureNotify(c);
+Client_Name(Client *c, const char *name) {
+ if (c->name) free(c->name);
+ c->name = strdup((char *) name);
+ c->namelen = strlen(c->name);
}
-extern void
-Client_Focus(Client *c, Time time) {
- if (current) {
- setactive(current, 0, 0L);
- XDeleteProperty(dpy, current->screen->root,
- ewmh_atom[_NET_ACTIVE_WINDOW]);
- }
-
- if (!c && current) {
- last_focus = current;
- } else {
- last_focus = NULL;
- }
- current = c;
- if (c) {
- setactive(current, 1, time);
- XChangeProperty(dpy, current->screen->root,
- ewmh_atom[_NET_ACTIVE_WINDOW],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *)¤t->window, 1);
- }
-
- if (focus_mode == focus_click)
- Client_Raise(c);
+int Client_HasFlags(Client* c, int flags) {
+ return ((c->flags & flags) == flags);
}
-extern void
-Client_Name(Client *c, const char *name, Bool is_utf8) {
- int tx;
- static const char dots[] = " [...] ";
- int cut;
-
- if (c->name) free(c->name);
- c->name = strdup((char *) name);
- c->namelen = strlen(c->name);
- c->name_utf8 = is_utf8;
-
- if (c->menu_name) free(c->menu_name);
- c->menu_name = 0;
- tx = titleWidth(popup_font_set, c);
- if (tx <= (c->screen->display_width - (c->screen->display_width / 10)))
- return;
-
- /* the menu entry for this client will not fit on the display
- * (minus 10% for saftey), so produced a truncated version...
- */
- cut = 5;
- do {
- if (c->menu_name) {
- free(c->menu_name);
- c->menu_name = 0;
- }
- if (cut >= (strlen(c->name) / 2)) break;
- c->menu_name = strdup(c->name);
- /* FIXME: this is not UTF-8 safe! */
- sprintf(&c->menu_name[(strlen(c->name) / 2) - cut], dots);
- strcat(c->menu_name,
- &c->name[(strlen(c->name) / 2) + cut]);
- c->menu_namelen = strlen(c->menu_name);
- cut++;
- tx = titleWidth(popup_font_set, c);
- if (!tx) break;
- } while (tx >
- (c->screen->display_width - (c->screen->display_width / 10)));
+static void
+sendClientMessage(Window w, Atom a, long data0, long data1) {
+ XEvent ev;
+ long mask;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = w;
+ ev.xclient.message_type = a;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = data0;
+ ev.xclient.data.l[1] = data1;
+ mask = (getScreenFromRoot(w) != 0) ? SubstructureRedirectMask : 0L;
+
+ XSendEvent(dpy, w, False, mask, &ev);
}
+
typedef struct CursorMapping CursorMapping;
struct CursorMapping {
- Edge edge;
- int font_char;
+ Edge edge;
+ int font_char;
};
static CursorMapping cursor_map[] = {
- {ETopLeft, XC_top_left_corner},
- {ETop, XC_top_side},
- {ETopRight, XC_top_right_corner},
- {ERight, XC_right_side},
- {ENone, XC_fleur},
- {ELeft, XC_left_side},
- {EBottomLeft, XC_bottom_left_corner},
- {EBottom, XC_bottom_side},
- {EBottomRight, XC_bottom_right_corner},
- {ENone, 0},
+ {ETopLeft, XC_top_left_corner},
+ {ETop, XC_top_side},
+ {ETopRight, XC_top_right_corner},
+ {ERight, XC_right_side},
+ {ENone, XC_fleur},
+ {ELeft, XC_left_side},
+ {EBottomLeft, XC_bottom_left_corner},
+ {EBottom, XC_bottom_side},
+ {EBottomRight, XC_bottom_right_corner},
+ {ENone, 0},
};
extern void
initialiseCursors(int screen) {
- XColor red, white, exact;
- Colormap cmp;
- int i;
+ XColor red, white, exact;
+ Colormap cmp;
+ int i;
- cmp = DefaultColormap(dpy, screen);
+ cmp = DefaultColormap(dpy, screen);
- XAllocNamedColor(dpy, cmp, "red", &red, &exact);
- XAllocNamedColor(dpy, cmp, "white", &white, &exact);
+ XAllocNamedColor(dpy, cmp, "red", &red, &exact);
+ XAllocNamedColor(dpy, cmp, "white", &white, &exact);
- screens[screen].root_cursor = XCreateFontCursor(dpy, XC_left_ptr);
- XRecolorCursor(dpy, screens[screen].root_cursor, &red, &white);
+ screens[screen].root_cursor = XCreateFontCursor(dpy, XC_left_ptr);
+ XRecolorCursor(dpy, screens[screen].root_cursor, &red, &white);
- screens[screen].box_cursor = XCreateFontCursor(dpy, XC_draped_box);
- XRecolorCursor(dpy, screens[screen].box_cursor, &red, &white);
+ screens[screen].box_cursor = XCreateFontCursor(dpy, XC_draped_box);
+ XRecolorCursor(dpy, screens[screen].box_cursor, &red, &white);
- for (i = 0; cursor_map[i].font_char != 0; i++) {
- Edge e = cursor_map[i].edge;
- screens[screen].cursor_map[e] =
- XCreateFontCursor(dpy, cursor_map[i].font_char);
- XRecolorCursor(dpy, screens[screen].cursor_map[e],
- &red, &white);
- }
+ for (i = 0; cursor_map[i].font_char != 0; i++) {
+ Edge e = cursor_map[i].edge;
+ screens[screen].cursor_map[e] =
+ XCreateFontCursor(dpy, cursor_map[i].font_char);
+ XRecolorCursor(dpy, screens[screen].cursor_map[e],
+ &red, &white);
+ }
}
extern Cursor
getEdgeCursor(Edge edge) {
- return screens[0].cursor_map[edge];
+ return screens[0].cursor_map[edge];
}
#include "ewmh.h"
/*
- * Dispatcher for main event loop.
+ * Dispatcher for main event loop.
*/
typedef struct Disp Disp;
struct Disp {
- int type;
- void (*handler)(XEvent *);
+ int type;
+ void (*handler)(XEvent *);
};
static void expose(XEvent *);
static void buttonpress(XEvent *);
-static void buttonrelease(XEvent *);
+static void buttonrelease(XEvent *ev);
static void focuschange(XEvent *);
static void maprequest(XEvent *);
static void configurereq(XEvent *);
static void unmap(XEvent *);
static void destroy(XEvent *);
static void clientmessage(XEvent *);
-static void colormap(XEvent *);
static void property(XEvent *);
static void reparent(XEvent *);
static void enter(XEvent *);
static void circulaterequest(XEvent *);
static void motionnotify(XEvent *);
-
-void reshaping_motionnotify(XEvent *);
+static void reshaping_motionnotify(XEvent *);
static Disp disps[] =
{
- {Expose, expose},
- {MotionNotify, motionnotify},
- {ButtonPress, buttonpress},
- {ButtonRelease, buttonrelease},
- {FocusIn, focuschange},
- {FocusOut, focuschange},
- {MapRequest, maprequest},
- {ConfigureRequest, configurereq},
- {UnmapNotify, unmap},
- {DestroyNotify, destroy},
- {ClientMessage, clientmessage},
- {ColormapNotify, colormap},
- {PropertyNotify, property},
- {ReparentNotify, reparent},
- {EnterNotify, enter},
- {CirculateRequest, circulaterequest},
- {LeaveNotify, 0},
- {ConfigureNotify, 0},
- {CreateNotify, 0},
- {GravityNotify, 0},
- {MapNotify, 0},
- {MappingNotify, 0},
- {SelectionClear, 0},
- {SelectionNotify, 0},
- {SelectionRequest, 0},
- {NoExpose, 0},
+ {Expose, expose},
+ {MotionNotify, motionnotify},
+ {ButtonPress, buttonpress},
+ {ButtonRelease, buttonrelease},
+ {FocusIn, focuschange},
+ {FocusOut, focuschange},
+ {MapRequest, maprequest},
+ {ConfigureRequest, configurereq},
+ {UnmapNotify, unmap},
+ {DestroyNotify, destroy},
+ {ClientMessage, clientmessage},
+ {PropertyNotify, property},
+ {ReparentNotify, reparent},
+ {EnterNotify, enter},
+ {CirculateRequest, circulaterequest},
+ {LeaveNotify, 0},
+ {ConfigureNotify, 0},
+ {CreateNotify, 0},
+ {GravityNotify, 0},
+ {MapNotify, 0},
+ {MappingNotify, 0},
+ {SelectionClear, 0},
+ {SelectionNotify, 0},
+ {SelectionRequest, 0},
+ {NoExpose, 0},
};
/**
extern void
dispatch(XEvent * ev) {
- Disp * p;
-
- for (p = disps; p < disps + sizeof(disps)/sizeof(disps[0]); p++) {
- if (p->type == ev->type) {
- if (p->handler != 0)
- p->handler(ev);
- return;
- }
- }
-
- if (!shapeEvent(ev))
- fprintf(stderr, "%s: unknown event %d\n", argv0, ev->type);
+ Disp * p;
+
+ for (p = disps; p < disps + sizeof(disps)/sizeof(disps[0]); p++) {
+ if (p->type == ev->type) {
+ if (p->handler != 0)
+ p->handler(ev);
+ return;
+ }
+ }
+
+ fprintf(stderr, "%s: unknown event %d\n", argv0, ev->type);
}
static void
expose(XEvent * ev) {
- Client * c;
- Window w; /* Window the expose event is for. */
-
- /* Only handle the last in a group of Expose events. */
- if (ev->xexpose.count != 0) return;
-
- w = ev->xexpose.window;
-
- /*
- * We don't draw on the root window so that people can have
- * their favourite Spice Girls backdrop...
- */
- if (getScreenFromRoot(w) != 0)
- return;
-
- /* Decide what needs redrawing: window frame or menu? */
- if (current_screen && w == current_screen->popup) {
- if (mode == wm_reshaping && current != 0)
- size_expose();
- } else {
- c = Client_Get(w);
- if (c != 0) {
- Client_DrawBorder(c, c == current);
- }
- }
+ Client * c;
+ Window w; /* Window the expose event is for. */
+
+ /* Only handle the last in a group of Expose events. */
+ if (ev->xexpose.count != 0) return;
+
+ w = ev->xexpose.window;
+
+ /*
+ * We don't draw on the root window so that people can have
+ * their favourite Spice Girls backdrop...
+ */
+ if (getScreenFromRoot(w) != 0)
+ return;
+
+ /* redraw window frame */
+ c = Client_Get(w);
+ if (c != 0) {
+ Client_DrawFrame(c, c == current);
+ }
}
static void
buttonpress(XEvent *ev) {
- Client *c;
- XButtonEvent *e = &ev->xbutton;
- int quarter;
-
- /* If we're getting it already, we're not in the market for more. */
- if (mode != wm_idle) {
- /* but allow a button press to cancel a move/resize,
- * to satify the EWMH advisory to allow a second mechanism
- * of completing move/resize operations, due to a race.
- * (section 4.3) sucky!
- */
- if (mode == wm_reshaping) {
- mode = wm_idle;
- }
- return;
- }
-
- c = Client_Get(e->window);
-
- if (c && c != current && focus_mode == focus_click) {
- /* Click is not on current window,
- * and in click-to-focus mode, so change focus
- */
- Client_Focus(c, e->time);
- }
-
- /*move this test up to disable scroll to focus*/
- if (e->button >= 4 && e->button <= 7) {
- return;
- }
-
- if (c && c == current && (e->window == c->parent)) {
- /* Click went to our frame around a client. */
-
- /* The ``box''. */
- quarter = (border + titleHeight()) / 4;
- if (e->x > (quarter + 2) && e->x < (3 + 3*quarter) && e->y > quarter && e->y <= 3*quarter) {
- /*Client_Close(c);*/
- pending = c;
- mode = wm_closing_window;
- return;
- }
-
- /* Somewhere in the rest of the frame. */
- if (e->button == HIDE_BUTTON) {
- pending = c;
- mode = wm_hiding_window;
- return;
- }
- if (e->button == MOVE_BUTTON) {
- Client_Move(c);
- return;
- }
- if (e->button == RESHAPE_BUTTON) {
- XMapWindow(dpy, c->parent);
- Client_Raise(c);
-
- /* Lasciate ogni speranza voi ch'entrate... */
-
- if (e->x <= border && e->y <= border) {
- Client_ReshapeEdge(c, ETopLeft);
- } else if (e->x >= (c->size.width - border) && e->y <= border) {
- Client_ReshapeEdge(c, ETopRight);
- } else if (e->x >= (c->size.width - border) && e->y >= (c->size.height + titleHeight() - border)) {
- Client_ReshapeEdge(c, EBottomRight);
- } else if (e->x <= border && e->y >= (c->size.height + titleHeight() - border)) {
- Client_ReshapeEdge(c, EBottomLeft);
- } else if (e->x > border && e->x < (c->size.width - border) && e->y < border) {
- Client_ReshapeEdge(c, ETop);
- } else if (e->x > border && e->x < (c->size.width - border) && e->y >= border && e->y < (titleHeight() + border)) {
- Client_Move(c);
- } else if (e->x > (c->size.width - border) && e->y > border && e->y < (c->size.height + titleHeight() - border)) {
- Client_ReshapeEdge(c, ERight);
- } else if (e->x > border && e->x < (c->size.width - border) && e->y > (c->size.height - border)) {
- Client_ReshapeEdge(c, EBottom);
- } else if (e->x < border && e->y > border && e->y < (c->size.height + titleHeight() - border)) {
- Client_ReshapeEdge(c, ELeft);
- }
- return;
- }
- return;
- }
-
- /* Deal with root window button presses. */
- if (e->window == e->root) {
- if (e->button == Button3) {
- cmapfocus(0);
- } else {
- shell(getScreenFromRoot(e->root), e->button, e->x, e->y);
- }
- }
+ Client *c;
+ XButtonEvent *e = &ev->xbutton;
+ int quarter;
+
+ /* If we're getting it already, we're not in the market for more. */
+ if (mode != wm_idle) {
+ /* but allow a button press to cancel a move/resize,
+ * to satify the EWMH advisory to allow a second mechanism
+ * of completing move/resize operations, due to a race.
+ * (section 4.3) sucky!
+ */
+ if (mode == wm_reshaping) {
+ mode = wm_idle;
+ }
+ return;
+ }
+
+ c = Client_Get(e->window);
+
+ /*move this test up to disable scroll to focus*/
+ if (e->button >= 4 && e->button <= 7) {
+ return;
+ }
+
+ if (c && c == current && (e->window == c->parent)) {
+ /* Click went to our frame around a client. */
+ if (e->button == Button1) {
+ XMapWindow(dpy, c->parent);
+ Client_Raise(c);
+ if (e->x <= border && e->y <= border) {
+ Client_ReshapeEdge(c, ETopLeft);
+ } else if (e->x >= (c->size.width - border) && e->y <= border) {
+ Client_ReshapeEdge(c, ETopRight);
+ } else if (e->x >= (c->size.width - border) && e->y >= (c->size.height + titleHeight() - border)) {
+ Client_ReshapeEdge(c, EBottomRight);
+ } else if (e->x <= border && e->y >= (c->size.height + titleHeight() - border)) {
+ Client_ReshapeEdge(c, EBottomLeft);
+ } else if (e->x > border && e->x < (c->size.width - border) && e->y < border) {
+ Client_ReshapeEdge(c, ETop);
+ } else if (e->x > border && e->x < (c->size.width - border) && e->y >= border && e->y < (titleHeight() + border)) {
+ Client_Move(c);
+ } else if (e->x > (c->size.width - border) && e->y > border && e->y < (c->size.height + titleHeight() - border)) {
+ Client_ReshapeEdge(c, ERight);
+ } else if (e->x > border && e->x < (c->size.width - border) && e->y > (c->size.height - border)) {
+ Client_ReshapeEdge(c, EBottom);
+ } else if (e->x < border && e->y > border && e->y < (c->size.height + titleHeight() - border)) {
+ Client_ReshapeEdge(c, ELeft);
+ }
+ return;
+ } else if (e->button == Button2) {
+ Client_Close(c);
+ }
+ return;
+ }
}
static void
buttonrelease(XEvent *ev) {
- XButtonEvent *e = &ev->xbutton;
- int quarter;
-
- if (mode == wm_reshaping)
- XUnmapWindow(dpy, current_screen->popup);
- else if (mode == wm_closing_window) {
- /* was the button released within the window's box?*/
- quarter = (border + titleHeight()) / 4;
- if (pending != NULL &&
- (e->window == pending->parent) &&
- (e->x > (quarter + 2) &&
- e->x < (3 + 3*quarter) &&
- e->y > quarter && e->y <= 3*quarter))
- Client_Close(pending);
- pending = NULL;
- } else if (mode == wm_hiding_window) {
- /* was the button release within the window's frame? */
- if (pending != NULL &&
- (e->window == pending->parent) &&
- (e->x >= 0) && (e->y >= 0) &&
- (e->x <= pending->size.width) &&
- (e->y <= (pending->size.height + titleHeight()))) {
- if (e->state & ShiftMask) {
- Client_Lower(pending);
- }
- }
- pending = NULL;
- }
-
- mode = wm_idle;
+ mode = wm_idle;
}
static void circulaterequest(XEvent *ev) {
- XCirculateRequestEvent * e = &ev->xcirculaterequest;
- Client * c;
-
- c = Client_Get(e->window);
-
- if (c == 0) {
- if (e->place == PlaceOnTop) {
- XRaiseWindow(e->display, e->window);
- } else {
- XLowerWindow(e->display, e->window);
- }
- } else {
- if (e->place == PlaceOnTop) {
- Client_Raise(c);
- } else {
- Client_Lower(c);
- }
- }
+ XCirculateRequestEvent * e = &ev->xcirculaterequest;
+ Client * c = Client_Get(e->window);
+
+ if (c == 0) {
+ if (e->place == PlaceOnTop) {
+ XRaiseWindow(e->display, e->window);
+ } else {
+ XLowerWindow(e->display, e->window);
+ }
+ } else {
+ if (e->place == PlaceOnTop) {
+ Client_Raise(c);
+ } else {
+ Client_Lower(c);
+ }
+ }
}
static void
maprequest(XEvent *ev) {
- Client * c;
- XMapRequestEvent * e = &ev->xmaprequest;
-
- c = Client_Get(e->window);
-
- if (c == 0 || c->window != e->window) {
- int screen;
- for (screen = 0; screen < screen_count; screen++)
- scanWindowTree(screen);
- c = Client_Get(e->window);
- if (c == 0 || c->window != e->window) {
- fprintf(stderr, "MapRequest for non-existent window!\n");
- return;
- }
- }
-
- switch (c->state) {
- case WithdrawnState:
- if (getScreenFromRoot(c->parent) != 0) {
- manage(c, 0);
- break;
- }
- if (c->framed == True) {
- XReparentWindow(dpy, c->window, c->parent, border,
- border + titleHeight());
- } else {
- XReparentWindow(dpy, c->window, c->parent,
- c->size.x, c->size.y);
- }
- XAddToSaveSet(dpy, c->window);
- /*FALLTHROUGH*/
- case NormalState:
- XMapWindow(dpy, c->parent);
- XMapWindow(dpy, c->window);
- Client_Raise(c);
- Client_SetState(c, NormalState);
- break;
- }
- ewmh_set_client_list(c->screen);
+ Client * c;
+ XMapRequestEvent * e = &ev->xmaprequest;
+
+ c = Client_Get(e->window);
+
+ if (c == 0 || c->window != e->window) {
+ int screen;
+ for (screen = 0; screen < screen_count; screen++)
+ scanWindowTree(screen);
+ c = Client_Get(e->window);
+ if (c == 0 || c->window != e->window) {
+ fprintf(stderr, "MapRequest for non-existent window!\n");
+ return;
+ }
+ }
+
+ switch (c->state) {
+ case WithdrawnState:
+ if (getScreenFromRoot(c->parent) != 0) {
+ manage(c, 0);
+ break;
+ }
+ if (c->framed == True) {
+ XReparentWindow(dpy, c->window, c->parent, border,
+ border + titleHeight());
+ } else {
+ XReparentWindow(dpy, c->window, c->parent,
+ c->size.x, c->size.y);
+ }
+ XAddToSaveSet(dpy, c->window);
+ /*FALLTHROUGH*/
+ case NormalState:
+ XMapWindow(dpy, c->parent);
+ XMapWindow(dpy, c->window);
+ Client_Raise(c);
+ Client_SetState(c, NormalState);
+ break;
+ }
+ ewmh_set_client_list(c->screen);
}
static void
unmap(XEvent *ev) {
- Client *c;
- XUnmapEvent *e = &ev->xunmap;
-
- c = Client_Get(e->window);
- if (c == 0) return;
-
- /*
- * In the description of the ReparentWindow request we read: "If the window
- * is mapped, an UnmapWindow request is performed automatically first". This
- * might seem stupid, but it's the way it is. While a reparenting is pending
- * we ignore UnmapWindow requests.
- */
- if (c->internal_state == IPendingReparenting) {
- c->internal_state = INormal;
- return;
- }
-
- /* "This time it's the real thing." */
-
- if (c->state == IconicState) {
- /*
- * Is this a hidden window disappearing? If not, then we
- * aren't interested because it's an unmap request caused
- * by our hiding a window.
- */
- } else {
- /* This is a plain unmap, so withdraw the window. */
- withdraw(c);
- }
-
- c->internal_state = INormal;
+ Client *c;
+ XUnmapEvent *e = &ev->xunmap;
+
+ c = Client_Get(e->window);
+ if (c == 0) return;
+
+ /*
+ * In the description of the ReparentWindow request we read: "If the window
+ * is mapped, an UnmapWindow request is performed automatically first". This
+ * might seem stupid, but it's the way it is. While a reparenting is pending
+ * we ignore UnmapWindow requests.
+ */
+ if (c->internal_state == IPendingReparenting) {
+ c->internal_state = INormal;
+ return;
+ }
+
+ /* This is a plain unmap, so withdraw the window. */
+ withdraw(c);
+
+ c->internal_state = INormal;
}
static void
configurereq(XEvent *ev) {
- XWindowChanges wc;
- Client *c;
- XConfigureRequestEvent *e = &ev->xconfigurerequest;
-
- c = Client_Get(e->window);
-
-
- if (c && c->window == e->window) {
- /*
- * ICCCM section 4.1.5 says that the x and y coordinates here
- * will have been "adjusted for the border width".
- * NOTE: this may not be the only place to bear this in mind.
- */
- if (e->value_mask & CWBorderWidth) {
- e->x -= e->border_width;
- e->y -= e->border_width;
- } else {
- /*
- * The ICCCM also says that clients should always set the
- * border width in a configure request. As usual, many don't.
- */
- /* adding one seems a bit arbitrary and makes edit
- drift by one pixel*/
- /*e->x--;*/
- /*e->y--;*/
- }
-
- if (e->value_mask & CWX) {
- c->size.x = e->x;
- }
- if (e->value_mask & CWY) {
- c->size.y = e->y;
- if (c->framed == True)
- c->size.y += titleHeight();
- }
- if (e->value_mask & CWWidth) {
- c->size.width = e->width;
- if (c->framed == True)
- c->size.width += 2 * border;
- }
- if (e->value_mask & CWHeight) {
- c->size.height = e->height;
- if (c->framed == True)
- c->size.height += 2 * border;
- }
- if (e->value_mask & CWBorderWidth)
- c->border = e->border_width;
-
- if (getScreenFromRoot(c->parent) == 0) {
- wc.x = c->size.x;
- wc.y = c->size.y;
- if (c->framed == True)
- wc.y -= titleHeight();
- wc.width = c->size.width;
- wc.height = c->size.height;
- if (c->framed == True)
- wc.height += titleHeight();
- wc.border_width = 1;
- wc.sibling = e->above;
- wc.stack_mode = e->detail;
-
- XConfigureWindow(dpy, e->parent, e->value_mask, &wc);
- sendConfigureNotify(c);
- }
- }
- if (c && (c->internal_state == INormal) && (c->framed == True)) {
- wc.x = border;
- wc.y = border;
- } else {
- wc.x = e->x;
- wc.y = e->y;
- }
-
- wc.width = e->width;
- wc.height = e->height;
- wc.border_width = 0;
- wc.sibling = e->above;
- wc.stack_mode = e->detail;
- e->value_mask |= CWBorderWidth;
-
- XConfigureWindow(dpy, e->window, e->value_mask, &wc);
-
- if (c) {
- if (c->framed == True) {
- XMoveResizeWindow(dpy, c->parent,
- c->size.x, c->size.y - titleHeight(),
- c->size.width, c->size.height + titleHeight());
- XMoveWindow(dpy, c->window,
- border, border + titleHeight());
- } else {
- XMoveResizeWindow(dpy, c->window,
- c->size.x, c->size.y,
- c->size.width, c->size.height);
- }
- }
+ XWindowChanges wc;
+ Client *c;
+ XConfigureRequestEvent *e = &ev->xconfigurerequest;
+
+ c = Client_Get(e->window);
+
+
+ if (c && c->window == e->window) {
+ /*
+ * ICCCM section 4.1.5 says that the x and y coordinates here
+ * will have been "adjusted for the border width".
+ * NOTE: this may not be the only place to bear this in mind.
+ */
+ if (e->value_mask & CWBorderWidth) {
+ e->x -= e->border_width;
+ e->y -= e->border_width;
+ } else {
+ /*
+ * The ICCCM also says that clients should always set the
+ * border width in a configure request. As usual, many don't.
+ */
+ /* adding one seems a bit arbitrary and makes edit
+ drift by one pixel*/
+ /*e->x--;*/
+ /*e->y--;*/
+ }
+
+ if (e->value_mask & CWX) {
+ c->size.x = e->x;
+ }
+ if (e->value_mask & CWY) {
+ c->size.y = e->y;
+ if (c->framed == True)
+ c->size.y += titleHeight();
+ }
+ if (e->value_mask & CWWidth) {
+ c->size.width = e->width;
+ if (c->framed == True)
+ c->size.width += 2 * border;
+ }
+ if (e->value_mask & CWHeight) {
+ c->size.height = e->height;
+ if (c->framed == True)
+ c->size.height += 2 * border;
+ }
+ if (e->value_mask & CWBorderWidth)
+ c->border = e->border_width;
+
+ if (getScreenFromRoot(c->parent) == 0) {
+ wc.x = c->size.x;
+ wc.y = c->size.y;
+ if (c->framed == True)
+ wc.y -= titleHeight();
+ wc.width = c->size.width;
+ wc.height = c->size.height;
+ if (c->framed == True)
+ wc.height += titleHeight();
+ wc.border_width = 1;
+ wc.sibling = e->above;
+ wc.stack_mode = e->detail;
+
+ XConfigureWindow(dpy, e->parent, e->value_mask, &wc);
+ sendConfigureNotify(c);
+ }
+ }
+ if (c && (c->internal_state == INormal) && (c->framed == True)) {
+ wc.x = border;
+ wc.y = border;
+ } else {
+ wc.x = e->x;
+ wc.y = e->y;
+ }
+
+ wc.width = e->width;
+ wc.height = e->height;
+ wc.border_width = 0;
+ wc.sibling = e->above;
+ wc.stack_mode = e->detail;
+ e->value_mask |= CWBorderWidth;
+
+ XConfigureWindow(dpy, e->window, e->value_mask, &wc);
+
+ if (c) {
+ if (c->framed == True) {
+ XMoveResizeWindow(dpy, c->parent,
+ c->size.x, c->size.y - titleHeight(),
+ c->size.width, c->size.height + titleHeight());
+ XMoveWindow(dpy, c->window,
+ border, border + titleHeight());
+ } else {
+ XMoveResizeWindow(dpy, c->window,
+ c->size.x, c->size.y,
+ c->size.width, c->size.height);
+ }
+ }
}
static void
destroy(XEvent *ev) {
- Client * c;
- Window w = ev->xdestroywindow.window;
+ Client * c;
+ Window w = ev->xdestroywindow.window;
- c = Client_Get(w);
- if (c == 0)
- return;
+ c = Client_Get(w);
+ if (c == 0)
+ return;
- ignore_badwindow = 1;
- Client_Remove(c);
- ignore_badwindow = 0;
+ ignore_badwindow = 1;
+ Client_Remove(c);
+ ignore_badwindow = 0;
}
static void
clientmessage(XEvent *ev) {
- Client * c;
- XClientMessageEvent * e = &ev->xclient;
-
- c = Client_Get(e->window);
- if (c == 0) return;
- if (e->message_type == wm_change_state) {
- return;
- }
- if (e->message_type == ewmh_atom[_NET_WM_STATE] &&
- e->format == 32) {
- ewmh_change_state(c, e->data.l[0], e->data.l[1]);
- ewmh_change_state(c, e->data.l[0], e->data.l[2]);
- return;
- }
- if (e->message_type == ewmh_atom[_NET_ACTIVE_WINDOW] &&
- e->format == 32) {
- /* An EWMH enabled application has asked for this client
- * to be made the active window. The window is raised, and
- * focus given if the focus mode is click (focusing on a
- * window other than the one the pointer is in makes no
- * sense when the focus mode is enter).
- */
- XMapWindow(dpy, c->parent);
- Client_Raise(c);
- if (c != current && focus_mode == focus_click)
- Client_Focus(c, CurrentTime);
- return;
- }
- if (e->message_type == ewmh_atom[_NET_CLOSE_WINDOW] &&
- e->format == 32) {
- Client_Close(c);
- return;
- }
- if (e->message_type == ewmh_atom[_NET_MOVERESIZE_WINDOW] &&
- e->format == 32) {
- XEvent ev;
-
- /* FIXME: ok, so this is a bit of a hack */
- ev.xconfigurerequest.window = e->window;
- ev.xconfigurerequest.x = e->data.l[1];
- ev.xconfigurerequest.y = e->data.l[2];
- ev.xconfigurerequest.width = e->data.l[3];
- ev.xconfigurerequest.height = e->data.l[4];
- ev.xconfigurerequest.value_mask = 0;
- if (e->data.l[0] & (1 << 8))
- ev.xconfigurerequest.value_mask |= CWX;
- if (e->data.l[0] & (1 << 9))
- ev.xconfigurerequest.value_mask |= CWY;
- if (e->data.l[0] & (1 << 10))
- ev.xconfigurerequest.value_mask |= CWWidth;
- if (e->data.l[0] & (1 << 11))
- ev.xconfigurerequest.value_mask |= CWHeight;
- configurereq(&ev);
- return;
- }
- if (e->message_type == ewmh_atom[_NET_WM_MOVERESIZE] &&
- e->format == 32) {
- Edge edge = E_LAST;
- EWMHDirection direction = e->data.l[2];
-/*
- int x_root = e->data.l[0];
- int y_root = e->data.l[1];
-*/
-
-
- /* before we can do any resizing, make the window visible */
- XMapWindow(dpy, c->parent);
- Client_Raise(c);
- /* FIXME: we're ignorning x_root, y_root and button! */
- switch (direction) {
- case DSizeTopLeft:
- edge = ETopLeft;
- break;
- case DSizeTop:
- edge = ETop;
- break;
- case DSizeTopRight:
- edge = ETopRight;
- break;
- case DSizeRight:
- edge = ERight;
- break;
- case DSizeBottomRight:
- edge = EBottomRight;
- break;
- case DSizeBottom:
- edge = EBottom;
- break;
- case DSizeBottomLeft:
- edge = EBottomLeft;
- break;
- case DSizeLeft:
- edge = ELeft;
- break;
- case DMove:
- edge = ENone;
- break;
- case DSizeKeyboard:
- /* FIXME: don't know how to deal with this */
- edge = E_LAST;
- break;
- case DMoveKeyboard:
-#if 0
-/* need to do a release and this is too broken for that */
- /* don't believe i'm doing this. mouse warping
- * sucks!
- */
- XWarpPointer(dpy, c->screen->root, c->window,
- x_root, y_root,
- c->screen->display_width,
- c->screen->display_height,
- c->size.width / 2, c->size.height / 2);
- edge = ENone;
-#endif
- edge = E_LAST;
- break;
- default:
- edge = E_LAST;
- fprintf(stderr, "%s: received _NET_WM_MOVERESIZE"
- " with bad direction", argv0);
- break;
- }
- switch (edge) {
- case E_LAST:
- break;
- case ENone:
- Client_Move(c);
- break;
- default:
- Client_ReshapeEdge(c, edge);
- break;
- }
- }
-}
-
-static void
-colormap(XEvent *ev) {
- Client * c;
- XColormapEvent * e = &ev->xcolormap;
-
- if (e->new) {
- c = Client_Get(e->window);
- if (c) {
- c->cmap = e->colormap;
- if (c == current)
- cmapfocus(c);
- } else {
- Client_ColourMap(ev);
- }
- }
+ Client * c;
+ XClientMessageEvent * e = &ev->xclient;
+
+ c = Client_Get(e->window);
+ if (c == 0) return;
+ if (e->message_type == ewmh_atom[_NET_ACTIVE_WINDOW] &&
+ e->format == 32) {
+ /* An EWMH enabled application has asked for this client
+ * to be made the active window. The window is raised, and
+ * focus given if the focus mode is click (focusing on a
+ * window other than the one the pointer is in makes no
+ * sense when the focus mode is enter).
+ */
+ XMapWindow(dpy, c->parent);
+ Client_Raise(c);
+ return;
+ }
+ if (e->message_type == ewmh_atom[_NET_CLOSE_WINDOW] &&
+ e->format == 32) {
+ Client_Close(c);
+ return;
+ }
+ if (e->message_type == ewmh_atom[_NET_MOVERESIZE_WINDOW] &&
+ e->format == 32) {
+ XEvent ev;
+
+ /* FIXME: ok, so this is a bit of a hack */
+ ev.xconfigurerequest.window = e->window;
+ ev.xconfigurerequest.x = e->data.l[1];
+ ev.xconfigurerequest.y = e->data.l[2];
+ ev.xconfigurerequest.width = e->data.l[3];
+ ev.xconfigurerequest.height = e->data.l[4];
+ ev.xconfigurerequest.value_mask = 0;
+ if (e->data.l[0] & (1 << 8))
+ ev.xconfigurerequest.value_mask |= CWX;
+ if (e->data.l[0] & (1 << 9))
+ ev.xconfigurerequest.value_mask |= CWY;
+ if (e->data.l[0] & (1 << 10))
+ ev.xconfigurerequest.value_mask |= CWWidth;
+ if (e->data.l[0] & (1 << 11))
+ ev.xconfigurerequest.value_mask |= CWHeight;
+ configurereq(&ev);
+ return;
+ }
+ if (e->message_type == ewmh_atom[_NET_WM_MOVERESIZE] &&
+ e->format == 32) {
+ Edge edge = E_LAST;
+ EWMHDirection direction = e->data.l[2];
+
+ /* before we can do any resizing, make the window visible */
+ XMapWindow(dpy, c->parent);
+ Client_Raise(c);
+ /* FIXME: we're ignorning x_root, y_root and button! */
+ switch (direction) {
+ case DSizeTopLeft:
+ edge = ETopLeft;
+ break;
+ case DSizeTop:
+ edge = ETop;
+ break;
+ case DSizeTopRight:
+ edge = ETopRight;
+ break;
+ case DSizeRight:
+ edge = ERight;
+ break;
+ case DSizeBottomRight:
+ edge = EBottomRight;
+ break;
+ case DSizeBottom:
+ edge = EBottom;
+ break;
+ case DSizeBottomLeft:
+ edge = EBottomLeft;
+ break;
+ case DSizeLeft:
+ edge = ELeft;
+ break;
+ case DMove:
+ edge = ENone;
+ break;
+ case DSizeKeyboard:
+ /* FIXME: don't know how to deal with this */
+ edge = E_LAST;
+ break;
+ case DMoveKeyboard:
+ edge = E_LAST;
+ break;
+ default:
+ edge = E_LAST;
+ fprintf(stderr, "%s: received _NET_WM_MOVERESIZE"
+ " with bad direction", argv0);
+ break;
+ }
+ switch (edge) {
+ case E_LAST:
+ break;
+ case ENone:
+ Client_Move(c);
+ break;
+ default:
+ Client_ReshapeEdge(c, edge);
+ break;
+ }
+ }
}
static void
property(XEvent * ev) {
- Client * c;
- XPropertyEvent * e = &ev->xproperty;
-
- c = Client_Get(e->window);
- if (c == 0)
- return;
-
- if (e->atom == _mozilla_url || e->atom == XA_WM_NAME) {
- getWindowName(c);
- setactive(c, c == current, 0L);
- } else if (e->atom == XA_WM_TRANSIENT_FOR) {
- getTransientFor(c);
- } else if (e->atom == XA_WM_NORMAL_HINTS) {
- getNormalHints(c);
- } else if (e->atom == wm_colormaps) {
- getColourmaps(c);
- if (c == current)
- cmapfocus(c);
- } else if (e->atom == ewmh_atom[_NET_WM_STRUT]) {
- ewmh_get_strut(c);
- } else if (e->atom == ewmh_atom[_NET_WM_STATE]) {
- // Received notice that client wants to change its state
- // update internal wstate tracking
- Bool wasFullscreen = c->wstate.fullscreen;
- ewmh_get_state(c);
- // make any changes requested
- if (c->wstate.fullscreen == True && wasFullscreen == False) Client_EnterFullScreen(c);
- else if (c->wstate.fullscreen == False && wasFullscreen == True) Client_ExitFullScreen(c);
- }
+ Client * c;
+ XPropertyEvent * e = &ev->xproperty;
+
+ c = Client_Get(e->window);
+ if (c == 0)
+ return;
+
+ if (e->atom == XA_WM_NAME) {
+ getWindowName(c);
+ Client_SetActive(c, c == current, 0L);
+ } else if (e->atom == XA_WM_TRANSIENT_FOR) {
+ getTransientFor(c);
+ } else if (e->atom == XA_WM_NORMAL_HINTS) {
+ getNormalHints(c);
+ }
}
static void
reparent(XEvent *ev) {
- Client * c;
- XReparentEvent * e = &ev->xreparent;
+ Client * c;
+ XReparentEvent * e = &ev->xreparent;
- if (getScreenFromRoot(e->event) == 0 || e->override_redirect || getScreenFromRoot(e->parent) != 0)
- return;
+ if (getScreenFromRoot(e->event) == 0 || e->override_redirect || getScreenFromRoot(e->parent) != 0)
+ return;
- c = Client_Get(e->window);
- if (c != 0 && (getScreenFromRoot(c->parent) != 0 || withdrawn(c)))
- Client_Remove(c);
+ c = Client_Get(e->window);
+ if (c != 0 && (getScreenFromRoot(c->parent) != 0 || Client_IsState(c, WithdrawnState)))
+ Client_Remove(c);
}
static void
focuschange(XEvent *ev) {
- Client *c;
- Window focus_window;
- int revert_to;
-
- if (ev->type == FocusOut) return;
-
- XGetInputFocus(dpy, &focus_window, &revert_to);
- if (focus_window == PointerRoot || focus_window == None) {
- if (current) Client_Focus(NULL, CurrentTime);
- return;
- }
- c = Client_Get(focus_window);
- if (c && c != current) {
- Client_Focus(c, CurrentTime);
- }
- return;
+ Client *c;
+ Window focus_window;
+ int revert_to;
+
+ if (ev->type == FocusOut) return;
+
+ XGetInputFocus(dpy, &focus_window, &revert_to);
+ if (focus_window == PointerRoot || focus_window == None) {
+ if (current) Client_Focus(NULL, CurrentTime);
+ return;
+ }
+ c = Client_Get(focus_window);
+ if (c && c != current) {
+ Client_Focus(c, CurrentTime);
+ }
+ return;
}
static void
enter(XEvent *ev) {
- Client *c;
-
- c = Client_Get(ev->xcrossing.window);
- if (c == 0 || mode != wm_idle)
- return;
-
- if (c->framed == True) {
- XSetWindowAttributes attr;
-
- attr.cursor = c->screen->root_cursor;
- XChangeWindowAttributes(dpy, c->parent,
- CWCursor, &attr);
- c->cursor = ENone;
- }
- if (c != current && !c->hidden && focus_mode == focus_enter) {
- /* Entering a new window in enter focus mode, so take focus */
- Client_Focus(c, ev->xcrossing.time);
- }
+ Client *c;
+
+ c = Client_Get(ev->xcrossing.window);
+ if (c == 0 || mode != wm_idle)
+ return;
+
+ if (c->framed == True) {
+ XSetWindowAttributes attr;
+
+ attr.cursor = c->screen->root_cursor;
+ XChangeWindowAttributes(dpy, c->parent,
+ CWCursor, &attr);
+ c->cursor = ENone;
+ }
+ if (c != current) {
+ /* Entering a new window in enter focus mode, so take focus */
+ Client_Focus(c, ev->xcrossing.time);
+ }
}
static void
motionnotify(XEvent *ev) {
- if (mode == wm_reshaping)
- reshaping_motionnotify(ev);
- else if (mode == wm_idle) {
- XMotionEvent *e = &ev->xmotion;
- Client *c = Client_Get(e->window);
- Edge edge = ENone;
- int quarter = (border + titleHeight()) / 4;
-
- if (c && (e->window == c->parent) &&
- (e->subwindow != c->window) &&
- mode == wm_idle) {
- /* mouse moved in a frame we manage - check cursor */
- if (e->x > (quarter + 2)
- && e->x < (3 + 3*quarter)
- && e->y > quarter && e->y <= 3*quarter) {
- edge = E_LAST;
- } else if (e->x <= border && e->y <= border) {
- edge = ETopLeft;
- } else if (e->x >= (c->size.width - border)
- && e->y <= border) {
- edge = ETopRight;
- } else if (e->x >= (c->size.width - border)
- && e->y >=
- (c->size.height + titleHeight() - border)) {
- edge = EBottomRight;
- } else if (e->x <= border &&
- e->y >=
- (c->size.height + titleHeight() - border)) {
- edge = EBottomLeft;
- } else if (e->x > border &&
- e->x < (c->size.width - border)
- && e->y < border) {
- edge = ETop;
- } else if (e->x > border &&
- e->x < (c->size.width - border)
- && e->y >= border
- && e->y < (titleHeight() + border)) {
- edge = ENone;
- } else if (e->x > (c->size.width - border)
- && e->y > border
- && e->y <
- (c->size.height + titleHeight() - border)) {
- edge = ERight;
- } else if (e->x > border
- && e->x < (c->size.width - border)
- && e->y > (c->size.height - border)) {
- edge = EBottom;
- } else if (e->x < border
- && e->y > border
- && e->y <
- (c->size.height + titleHeight() - border)) {
- edge = ELeft;
- }
- if (c->cursor != edge) {
- XSetWindowAttributes attr;
-
- if (edge == ENone) {
- attr.cursor =
- c->screen->root_cursor;
- } else if (edge == E_LAST) {
- attr.cursor =
- c->screen->box_cursor;
- } else {
- attr.cursor =
- c->screen->cursor_map[edge];
- }
- XChangeWindowAttributes(dpy, c->parent,
- CWCursor, &attr);
- c->cursor = edge;
- }
- }
- }
+ if (mode == wm_reshaping)
+ reshaping_motionnotify(ev);
+ else if (mode == wm_idle) {
+ XMotionEvent *e = &ev->xmotion;
+ Client *c = Client_Get(e->window);
+ Edge edge = ENone;
+ int quarter = (border + titleHeight()) / 4;
+
+ if (c && (e->window == c->parent) &&
+ (e->subwindow != c->window) &&
+ mode == wm_idle) {
+ /* mouse moved in a frame we manage - check cursor */
+ if (e->x > (quarter + 2)
+ && e->x < (3 + 3*quarter)
+ && e->y > quarter && e->y <= 3*quarter) {
+ edge = E_LAST;
+ } else if (e->x <= border && e->y <= border) {
+ edge = ETopLeft;
+ } else if (e->x >= (c->size.width - border)
+ && e->y <= border) {
+ edge = ETopRight;
+ } else if (e->x >= (c->size.width - border)
+ && e->y >=
+ (c->size.height + titleHeight() - border)) {
+ edge = EBottomRight;
+ } else if (e->x <= border &&
+ e->y >=
+ (c->size.height + titleHeight() - border)) {
+ edge = EBottomLeft;
+ } else if (e->x > border &&
+ e->x < (c->size.width - border)
+ && e->y < border) {
+ edge = ETop;
+ } else if (e->x > border &&
+ e->x < (c->size.width - border)
+ && e->y >= border
+ && e->y < (titleHeight() + border)) {
+ edge = ENone;
+ } else if (e->x > (c->size.width - border)
+ && e->y > border
+ && e->y <
+ (c->size.height + titleHeight() - border)) {
+ edge = ERight;
+ } else if (e->x > border
+ && e->x < (c->size.width - border)
+ && e->y > (c->size.height - border)) {
+ edge = EBottom;
+ } else if (e->x < border
+ && e->y > border
+ && e->y <
+ (c->size.height + titleHeight() - border)) {
+ edge = ELeft;
+ }
+ if (c->cursor != edge) {
+ XSetWindowAttributes attr;
+
+ if (edge == ENone) {
+ attr.cursor = c->screen->root_cursor;
+ } else {
+ attr.cursor = c->screen->cursor_map[edge];
+ }
+ XChangeWindowAttributes(dpy, c->parent,
+ CWCursor, &attr);
+ c->cursor = edge;
+ }
+ }
+ }
}
/*ARGSUSED*/
-void
+static void
reshaping_motionnotify(XEvent* ev) {
- int nx; /* New x. */
- int ny; /* New y. */
- int ox; /* Original x. */
- int oy; /* Original y. */
- int ndx; /* New width. */
- int ndy; /* New height. */
- int odx; /* Original width. */
- int ody; /* Original height. */
- int pointer_x;
- int pointer_y;
-
- if (mode != wm_reshaping || !current) return;
-
- getMousePosition(&pointer_x, &pointer_y);
-
- if (interacting_edge != ENone) {
- nx = ox = current->size.x;
- ny = oy = current->size.y;
- ndx = odx = current->size.width;
- ndy = ody = current->size.height;
-
- /* Vertical. */
- switch (interacting_edge) {
- case ETop:
- case ETopLeft:
- case ETopRight:
- pointer_y += titleHeight();
- ndy += (current->size.y - pointer_y);
- ny = pointer_y;
- break;
- case EBottom:
- case EBottomLeft:
- case EBottomRight:
- ndy = pointer_y - current->size.y;
- break;
- default: break;
- }
-
- /* Horizontal. */
- switch (interacting_edge) {
- case ERight:
- case ETopRight:
- case EBottomRight:
- ndx = pointer_x - current->size.x;
- break;
- case ELeft:
- case ETopLeft:
- case EBottomLeft:
- ndx += (current->size.x - pointer_x);
- nx = pointer_x;
- break;
- default: break;
- }
-
- Client_MakeSane(current, interacting_edge, &nx, &ny, &ndx, &ndy);
- XMoveResizeWindow(dpy, current->parent,
- current->size.x, current->size.y - titleHeight(),
- current->size.width, current->size.height + titleHeight());
- if (current->size.width == odx && current->size.height == ody) {
- if (current->size.x != ox || current->size.y != oy)
- sendConfigureNotify(current);
- } else
- XMoveResizeWindow(dpy, current->window,
- border, border + titleHeight(),
- current->size.width - 2 * border,
- current->size.height - 2 * border);
- } else {
- nx = pointer_x + start_x;
- ny = pointer_y + start_y;
-
- Client_MakeSane(current, interacting_edge, &nx, &ny, 0, 0);
- if (current->framed == True) {
- XMoveWindow(dpy, current->parent,
- current->size.x,
- current->size.y - titleHeight());
- } else {
- XMoveWindow(dpy, current->parent,
- current->size.x, current->size.y);
- }
- sendConfigureNotify(current);
- }
+ int nx; /* New x. */
+ int ny; /* New y. */
+ int ox; /* Original x. */
+ int oy; /* Original y. */
+ int ndx; /* New width. */
+ int ndy; /* New height. */
+ int odx; /* Original width. */
+ int ody; /* Original height. */
+ int pointer_x;
+ int pointer_y;
+
+ if (mode != wm_reshaping || !current) return;
+
+ getMousePosition(&pointer_x, &pointer_y);
+
+ if (interacting_edge != ENone) {
+ nx = ox = current->size.x;
+ ny = oy = current->size.y;
+ ndx = odx = current->size.width;
+ ndy = ody = current->size.height;
+
+ /* Vertical. */
+ switch (interacting_edge) {
+ case ETop:
+ case ETopLeft:
+ case ETopRight:
+ pointer_y += titleHeight();
+ ndy += (current->size.y - pointer_y);
+ ny = pointer_y;
+ break;
+ case EBottom:
+ case EBottomLeft:
+ case EBottomRight:
+ ndy = pointer_y - current->size.y;
+ break;
+ default: break;
+ }
+
+ /* Horizontal. */
+ switch (interacting_edge) {
+ case ERight:
+ case ETopRight:
+ case EBottomRight:
+ ndx = pointer_x - current->size.x;
+ break;
+ case ELeft:
+ case ETopLeft:
+ case EBottomLeft:
+ ndx += (current->size.x - pointer_x);
+ nx = pointer_x;
+ break;
+ default: break;
+ }
+
+ Client_MakeSane(current, interacting_edge, &nx, &ny, &ndx, &ndy);
+ XMoveResizeWindow(dpy, current->parent,
+ current->size.x, current->size.y - titleHeight(),
+ current->size.width, current->size.height + titleHeight());
+ if (current->size.width == odx && current->size.height == ody) {
+ if (current->size.x != ox || current->size.y != oy)
+ sendConfigureNotify(current);
+ } else
+ XMoveResizeWindow(dpy, current->window,
+ border, border + titleHeight(),
+ current->size.width - 2 * border,
+ current->size.height - 2 * border);
+ } else {
+ nx = pointer_x + start_x;
+ ny = pointer_y + start_y;
+
+ Client_MakeSane(current, interacting_edge, &nx, &ny, 0, 0);
+ if (current->framed == True) {
+ XMoveWindow(dpy, current->parent,
+ current->size.x,
+ current->size.y - titleHeight());
+ } else {
+ XMoveWindow(dpy, current->parent,
+ current->size.x, current->size.y);
+ }
+ sendConfigureNotify(current);
+ }
}
/*
* lwm, a window manager for X11
* Copyright (C) 1997-2016 Elliott Hughes, James Carter
- *
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void
ewmh_init(void) {
- /* build half a million EWMH atoms */
- ewmh_atom[_NET_SUPPORTED] =
- XInternAtom(dpy, "_NET_SUPPORTED", False);
- ewmh_atom[_NET_CLIENT_LIST] =
- XInternAtom(dpy, "_NET_CLIENT_LIST", False);
- ewmh_atom[_NET_CLIENT_LIST_STACKING] =
- XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False);
- ewmh_atom[_NET_NUMBER_OF_DESKTOPS] =
- XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
- ewmh_atom[_NET_DESKTOP_GEOMETRY] =
- XInternAtom(dpy, "_NET_DESKTOP_GEOMETRY", False);
- ewmh_atom[_NET_DESKTOP_VIEWPORT] =
- XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False);
- ewmh_atom[_NET_CURRENT_DESKTOP] =
- XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
- ewmh_atom[_NET_ACTIVE_WINDOW] =
- XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- ewmh_atom[_NET_WORKAREA] =
- XInternAtom(dpy, "_NET_WORKAREA", False);
- ewmh_atom[_NET_SUPPORTING_WM_CHECK] =
- XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
- ewmh_atom[_NET_CLOSE_WINDOW] =
- XInternAtom(dpy, "_NET_CLOSE_WINDOW", False);
- ewmh_atom[_NET_MOVERESIZE_WINDOW] =
- XInternAtom(dpy, "_NET_MOVERESIZE_WINDOW", False);
- ewmh_atom[_NET_WM_MOVERESIZE] =
- XInternAtom(dpy, "_NET_WM_MOVERESIZE", False);
- ewmh_atom[_NET_WM_NAME] =
- XInternAtom(dpy, "_NET_WM_NAME", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
- ewmh_atom[_NET_WM_STATE] =
- XInternAtom(dpy, "_NET_WM_STATE", False);
- ewmh_atom[_NET_WM_ALLOWED_ACTIONS] =
- XInternAtom(dpy, "_NET_WM_ALLOWED_ACTIONS", False);
- ewmh_atom[_NET_WM_STRUT] =
- XInternAtom(dpy, "_NET_WM_STRUT", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_DESKTOP] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_DOCK] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_TOOLBAR] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_MENU] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_MENU", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_UTILITY] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_SPLASH] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_DIALOG] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_NORMAL] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False);
- ewmh_atom[_NET_WM_STATE_SKIP_TASKBAR] =
- XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False);
- ewmh_atom[_NET_WM_STATE_SKIP_PAGER] =
- XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False);
- ewmh_atom[_NET_WM_STATE_HIDDEN] =
- XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False);
- ewmh_atom[_NET_WM_STATE_FULLSCREEN] =
- XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
- ewmh_atom[_NET_WM_ACTION_MOVE] =
- XInternAtom(dpy, "_NET_WM_ACTION_MOVE", False);
- ewmh_atom[_NET_WM_ACTION_RESIZE] =
- XInternAtom(dpy, "_NET_WM_ACTION_RESIZE", False);
- ewmh_atom[_NET_WM_ACTION_FULLSCREEN] =
- XInternAtom(dpy, "_NET_WM_ACTION_FULLSCREEN", False);
- ewmh_atom[_NET_WM_ACTION_CLOSE] =
- XInternAtom(dpy, "_NET_WM_ACTION_CLOSE", False);
- utf8_string = XInternAtom(dpy, "UTF8_STRING", False);
+ /* build half a million EWMH atoms */
+ ewmh_atom[_NET_SUPPORTED] =
+ XInternAtom(dpy, "_NET_SUPPORTED", False);
+ ewmh_atom[_NET_CLIENT_LIST] =
+ XInternAtom(dpy, "_NET_CLIENT_LIST", False);
+ ewmh_atom[_NET_CLIENT_LIST_STACKING] =
+ XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False);
+ ewmh_atom[_NET_NUMBER_OF_DESKTOPS] =
+ XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
+ ewmh_atom[_NET_DESKTOP_GEOMETRY] =
+ XInternAtom(dpy, "_NET_DESKTOP_GEOMETRY", False);
+ ewmh_atom[_NET_DESKTOP_VIEWPORT] =
+ XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False);
+ ewmh_atom[_NET_CURRENT_DESKTOP] =
+ XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
+ ewmh_atom[_NET_ACTIVE_WINDOW] =
+ XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
+ ewmh_atom[_NET_WORKAREA] =
+ XInternAtom(dpy, "_NET_WORKAREA", False);
+ ewmh_atom[_NET_SUPPORTING_WM_CHECK] =
+ XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
+ ewmh_atom[_NET_CLOSE_WINDOW] =
+ XInternAtom(dpy, "_NET_CLOSE_WINDOW", False);
+ ewmh_atom[_NET_MOVERESIZE_WINDOW] =
+ XInternAtom(dpy, "_NET_MOVERESIZE_WINDOW", False);
+ ewmh_atom[_NET_WM_MOVERESIZE] =
+ XInternAtom(dpy, "_NET_WM_MOVERESIZE", False);
+ ewmh_atom[_NET_WM_NAME] =
+ XInternAtom(dpy, "_NET_WM_NAME", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
+ ewmh_atom[_NET_WM_STATE] =
+ XInternAtom(dpy, "_NET_WM_STATE", False);
+ ewmh_atom[_NET_WM_ALLOWED_ACTIONS] =
+ XInternAtom(dpy, "_NET_WM_ALLOWED_ACTIONS", False);
+ ewmh_atom[_NET_WM_STRUT] =
+ XInternAtom(dpy, "_NET_WM_STRUT", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE_DESKTOP] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE_DOCK] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE_TOOLBAR] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE_MENU] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_MENU", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE_UTILITY] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE_SPLASH] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE_DIALOG] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+ ewmh_atom[_NET_WM_WINDOW_TYPE_NORMAL] =
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False);
+ ewmh_atom[_NET_WM_STATE_SKIP_TASKBAR] =
+ XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False);
+ ewmh_atom[_NET_WM_STATE_SKIP_PAGER] =
+ XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False);
+ ewmh_atom[_NET_WM_STATE_HIDDEN] =
+ XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False);
+ ewmh_atom[_NET_WM_STATE_FULLSCREEN] =
+ XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
+ ewmh_atom[_NET_WM_ACTION_MOVE] =
+ XInternAtom(dpy, "_NET_WM_ACTION_MOVE", False);
+ ewmh_atom[_NET_WM_ACTION_RESIZE] =
+ XInternAtom(dpy, "_NET_WM_ACTION_RESIZE", False);
+ ewmh_atom[_NET_WM_ACTION_FULLSCREEN] =
+ XInternAtom(dpy, "_NET_WM_ACTION_FULLSCREEN", False);
+ ewmh_atom[_NET_WM_ACTION_CLOSE] =
+ XInternAtom(dpy, "_NET_WM_ACTION_CLOSE", False);
+ utf8_string = XInternAtom(dpy, "UTF8_STRING", False);
}
void
ewmh_init_screens(void) {
- int i;
- unsigned long data[4];
-
- /* announce EWMH compatibility on all acreens */
- for (i = 0; i < screen_count; i++) {
- screens[i].ewmh_set_client_list = False;
- screens[i].ewmh_compat = XCreateSimpleWindow(dpy,
- screens[i].root,
- -200, -200, 1, 1,
- 0, 0, 0);
- XChangeProperty(dpy, screens[i].ewmh_compat,
- ewmh_atom[_NET_WM_NAME],
- utf8_string, 8, PropModeReplace,
- "lwm", 3);
-
- /* set root window properties */
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_SUPPORTED],
- XA_ATOM, 32, PropModeReplace,
- (unsigned char *)ewmh_atom, EWMH_ATOM_LAST);
-
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_SUPPORTING_WM_CHECK],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *)&screens[i].ewmh_compat, 1);
-
- data[0] = 1;
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_NUMBER_OF_DESKTOPS],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 1);
-
- data[0] = screens[i].display_width;
- data[1] = screens[i].display_height;
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_DESKTOP_GEOMETRY],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 2);
-
- data[0] = 0;
- data[1] = 0;
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_DESKTOP_VIEWPORT],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 2);
-
- data[0] = 0;
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_CURRENT_DESKTOP],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 1);
-
- ewmh_set_strut(&screens[i]);
- ewmh_set_client_list(&screens[i]);
- }
+ int i;
+ unsigned long data[4];
+
+ /* announce EWMH compatibility on all acreens */
+ for (i = 0; i < screen_count; i++) {
+ screens[i].ewmh_set_client_list = False;
+ screens[i].ewmh_compat = XCreateSimpleWindow(dpy,
+ screens[i].root,
+ -200, -200, 1, 1,
+ 0, 0, 0);
+ XChangeProperty(dpy, screens[i].ewmh_compat,
+ ewmh_atom[_NET_WM_NAME],
+ utf8_string, 8, PropModeReplace,
+ (unsigned char*)"lwm", 3);
+
+ /* set root window properties */
+ XChangeProperty(dpy, screens[i].root,
+ ewmh_atom[_NET_SUPPORTED],
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *)ewmh_atom, EWMH_ATOM_LAST);
+
+ XChangeProperty(dpy, screens[i].root,
+ ewmh_atom[_NET_SUPPORTING_WM_CHECK],
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *)&screens[i].ewmh_compat, 1);
+
+ data[0] = 1;
+ XChangeProperty(dpy, screens[i].root,
+ ewmh_atom[_NET_NUMBER_OF_DESKTOPS],
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char*)data, 1);
+
+ data[0] = screens[i].display_width;
+ data[1] = screens[i].display_height;
+ XChangeProperty(dpy, screens[i].root,
+ ewmh_atom[_NET_DESKTOP_GEOMETRY],
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char*)data, 2);
+
+ data[0] = 0;
+ data[1] = 0;
+ XChangeProperty(dpy, screens[i].root,
+ ewmh_atom[_NET_DESKTOP_VIEWPORT],
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char*)data, 2);
+
+ data[0] = 0;
+ XChangeProperty(dpy, screens[i].root,
+ ewmh_atom[_NET_CURRENT_DESKTOP],
+ XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char*)data, 1);
+
+ ewmh_set_client_list(&screens[i]);
+ }
}
EWMHWindowType
ewmh_get_window_type(Window w) {
- Atom rt;
- Atom *type;
- int fmt;
- unsigned long n;
- unsigned long extra;
- int i;
- EWMHWindowType ret;
-
- i = XGetWindowProperty(dpy, w,
- ewmh_atom[_NET_WM_WINDOW_TYPE],
- 0, 100, False, XA_ATOM, &rt, &fmt, &n, &extra,
- (unsigned char **)&type);
- if (i != Success || type == NULL)
- return WTypeNone;
- ret = WTypeNone;
- for (; n; n--) {
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_DESKTOP]) {
- ret = WTypeDesktop;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_DOCK]) {
- ret = WTypeDock;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_TOOLBAR]) {
- ret = WTypeToolbar;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_MENU]) {
- ret = WTypeMenu;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_UTILITY]) {
- ret = WTypeUtility;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_SPLASH]) {
- ret = WTypeSplash;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_DIALOG]) {
- ret = WTypeDialog;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_NORMAL]) {
- ret = WTypeNormal;
- break;
- }
- }
- XFree(type);
- return ret;
+ Atom rt;
+ Atom *type;
+ int fmt;
+ unsigned long n;
+ unsigned long extra;
+ int i;
+ EWMHWindowType ret;
+
+ i = XGetWindowProperty(dpy, w,
+ ewmh_atom[_NET_WM_WINDOW_TYPE],
+ 0, 100, False, XA_ATOM, &rt, &fmt, &n, &extra,
+ (unsigned char **)&type);
+ if (i != Success || type == NULL)
+ return WTypeNone;
+ ret = WTypeNone;
+ for (; n; n--) {
+ if (type[n - 1] ==
+ ewmh_atom[_NET_WM_WINDOW_TYPE_DESKTOP]) {
+ ret = WTypeDesktop;
+ break;
+ }
+ if (type[n - 1] ==
+ ewmh_atom[_NET_WM_WINDOW_TYPE_DOCK]) {
+ ret = WTypeDock;
+ break;
+ }
+ if (type[n - 1] ==
+ ewmh_atom[_NET_WM_WINDOW_TYPE_TOOLBAR]) {
+ ret = WTypeToolbar;
+ break;
+ }
+ if (type[n - 1] ==
+ ewmh_atom[_NET_WM_WINDOW_TYPE_MENU]) {
+ ret = WTypeMenu;
+ break;
+ }
+ if (type[n - 1] ==
+ ewmh_atom[_NET_WM_WINDOW_TYPE_UTILITY]) {
+ ret = WTypeUtility;
+ break;
+ }
+ if (type[n - 1] ==
+ ewmh_atom[_NET_WM_WINDOW_TYPE_SPLASH]) {
+ ret = WTypeSplash;
+ break;
+ }
+ if (type[n - 1] ==
+ ewmh_atom[_NET_WM_WINDOW_TYPE_DIALOG]) {
+ ret = WTypeDialog;
+ break;
+ }
+ if (type[n - 1] ==
+ ewmh_atom[_NET_WM_WINDOW_TYPE_NORMAL]) {
+ ret = WTypeNormal;
+ break;
+ }
+ }
+ XFree(type);
+ return ret;
}
Bool ewmh_get_window_name(Client *c) {
-#ifdef X_HAVE_UTF8_STRING
- Atom rt;
- char *name;
- int fmt;
- unsigned long n;
- unsigned long extra;
- int i;
-
- i = XGetWindowProperty(dpy, c->window,
- ewmh_atom[_NET_WM_NAME],
- 0, 100, False, utf8_string, &rt, &fmt, &n, &extra,
- (unsigned char **)&name);
- if (i != Success || name == NULL)
- return False;
- Client_Name(c, name, True);
- XFree(name);
- return True;
-#else
- return False;
-#endif
+ Atom rt;
+ char *name;
+ int fmt;
+ unsigned long n;
+ unsigned long extra;
+ int i;
+
+ i = XGetWindowProperty(dpy, c->window,
+ ewmh_atom[_NET_WM_NAME],
+ 0, 100, False, utf8_string, &rt, &fmt, &n, &extra,
+ (unsigned char **)&name);
+ if (i != Success || name == NULL)
+ return False;
+ Client_Name(c, name);
+ XFree(name);
+ return True;
}
Bool
ewmh_hasframe(Client *c) {
- switch (c->wtype) {
- case WTypeDesktop:
- case WTypeDock:
- case WTypeMenu:
- case WTypeSplash:
- return False;
- default:
- return True;
- }
-}
-
-void
-ewmh_get_state(Client *c) {
- Atom rt;
- Atom *state;
- int fmt;
- unsigned long n;
- unsigned long extra;
- int i;
-
- if (c == NULL) return;
- i = XGetWindowProperty(dpy, c->window,
- ewmh_atom[_NET_WM_STATE],
- 0, 100, False, XA_ATOM, &rt, &fmt, &n, &extra,
- (unsigned char **)&state);
- if (i != Success || state == NULL) return;
- c->wstate.skip_taskbar = False;
- c->wstate.skip_pager = False;
- c->wstate.fullscreen = False;
- c->wstate.above = False;
- c->wstate.below = False;
- for (; n; n--) {
- if (state[n - 1] ==
- ewmh_atom[_NET_WM_STATE_SKIP_TASKBAR])
- c->wstate.skip_taskbar = True;
- if (state[n - 1] ==
- ewmh_atom[_NET_WM_STATE_SKIP_PAGER])
- c->wstate.skip_pager = True;
- if (state[n - 1] ==
- ewmh_atom[_NET_WM_STATE_FULLSCREEN])
- c->wstate.fullscreen = True;
- if (state[n - 1] ==
- ewmh_atom[_NET_WM_STATE_ABOVE])
- c->wstate.above = True;
- if (state[n - 1] ==
- ewmh_atom[_NET_WM_STATE_BELOW])
- c->wstate.below = True;
- }
- XFree(state);
+ switch (c->wtype) {
+ case WTypeDesktop:
+ case WTypeDock:
+ case WTypeMenu:
+ case WTypeSplash:
+ return False;
+ default:
+ return True;
+ }
}
static Bool
new_state(unsigned long action, Bool current)
{
- enum Action {remove, add, toggle};
-
- switch (action) {
- case remove:
- return False;
- case add:
- return True;
- case toggle:
- if (current == True) return False; else return True;
- }
- fprintf(stderr,"%s: bad action in _NET_WM_STATE (%d)\n",
- argv0, (int) action);
- return current;
-}
-
-void
-ewmh_change_state(Client *c, unsigned long action,
- unsigned long atom) {
- Atom *a = (Atom *)&atom;
-
- if (atom == 0) return;
- if (*a == ewmh_atom[_NET_WM_STATE_SKIP_TASKBAR])
- c->wstate.skip_taskbar =
- new_state(action, c->wstate.skip_taskbar);
- if (*a == ewmh_atom[_NET_WM_STATE_SKIP_PAGER])
- c->wstate.skip_pager =
- new_state(action, c->wstate.skip_pager);
- if (*a == ewmh_atom[_NET_WM_STATE_FULLSCREEN]) {
- Bool was_fullscreen = c->wstate.fullscreen;
-
- c->wstate.fullscreen =
- new_state(action, c->wstate.fullscreen);
- if (was_fullscreen == False &&
- c->wstate.fullscreen == True) Client_EnterFullScreen(c);
- if (was_fullscreen == True &&
- c->wstate.fullscreen == False) Client_ExitFullScreen(c);
- }
- if (*a == ewmh_atom[_NET_WM_STATE_ABOVE])
- c->wstate.above =
- new_state(action, c->wstate.above);
- if (*a == ewmh_atom[_NET_WM_STATE_BELOW])
- c->wstate.below =
- new_state(action, c->wstate.below);
- ewmh_set_state(c);
-
- /* may have to shuffle windows in the stack after a change of state */
- ewmh_set_client_list(c->screen);
-}
-
-void
-ewmh_set_state(Client *c) {
- int atoms = 0;
- Atom *a = NULL;
- int i = 0;
-
- if (c == NULL) return;
-
- if (c->state != WithdrawnState) {
- if (c->hidden == True) atoms++;
- if (c->wstate.skip_taskbar == True) atoms++;
- if (c->wstate.skip_pager == True) atoms++;
- if (c->wstate.fullscreen == True) atoms++;
- if (c->wstate.above == True) atoms++;
- if (c->wstate.below == True) atoms++;
- if (atoms > 0) a = malloc(sizeof(Atom) * atoms);
-
- if (c->hidden == True) {
- a[i] = ewmh_atom[_NET_WM_STATE_HIDDEN];
- i++;
- }
- if (c->wstate.skip_taskbar == True) {
- a[i] = ewmh_atom[_NET_WM_STATE_SKIP_TASKBAR];
- i++;
- }
- if (c->wstate.skip_pager == True) {
- a[i] = ewmh_atom[_NET_WM_STATE_SKIP_PAGER];
- i++;
- }
- if (c->wstate.fullscreen == True) {
- a[i] = ewmh_atom[_NET_WM_STATE_FULLSCREEN];
- i++;
- }
- if (c->wstate.above == True) {
- a[i] = ewmh_atom[_NET_WM_STATE_ABOVE];
- i++;
- }
- if (c->wstate.below == True) {
- a[i] = ewmh_atom[_NET_WM_STATE_BELOW];
- i++;
- }
- }
-
- XChangeProperty(dpy, c->window, ewmh_atom[_NET_WM_STATE],
- XA_ATOM, 32, PropModeReplace, (unsigned char *)a, atoms);
- if (a != NULL) free(a);
-
+ enum Action {remove, add, toggle};
+
+ switch (action) {
+ case remove:
+ return False;
+ case add:
+ return True;
+ case toggle:
+ if (current == True) return False; else return True;
+ }
+ fprintf(stderr,"%s: bad action in _NET_WM_STATE (%d)\n",
+ argv0, (int) action);
+ return current;
}
void
/* FIXME: this is dumb - the allowed actions should be calculuated
* but for now, anything goes.
*/
- Atom action[4];
-
- action[0] = ewmh_atom[_NET_WM_ACTION_MOVE];
- action[1] = ewmh_atom[_NET_WM_ACTION_RESIZE];
- action[2] = ewmh_atom[_NET_WM_ACTION_FULLSCREEN];
- action[3] = ewmh_atom[_NET_WM_ACTION_CLOSE];
- XChangeProperty(dpy, c->window, ewmh_atom[_NET_WM_ALLOWED_ACTIONS],
- XA_ATOM, 32, PropModeReplace, (unsigned char *)action, 4);
-}
-
-void
-ewmh_set_strut(ScreenInfo *screen) {
- Client *c;
- EWMHStrut strut;
- unsigned long data[4];
- /* FIXME: add parameter to MakeSane rather than this hack */
- Edge backup;
-
- /* find largest reserved areas */
- strut.left = 0;
- strut.right = 0;
- strut.top = 0;
- strut.bottom = 0;
- for (c = client_head(); c; c = c->next) {
- if (c->screen != screen) continue;
- if (c->strut.left > strut.left) strut.left = c->strut.left;
- if (c->strut.right > strut.right) strut.right = c->strut.right;
- if (c->strut.top > strut.top) strut.top = c->strut.top;
- if (c->strut.bottom > strut.bottom)
- strut.bottom = c->strut.bottom;
- }
-
- /* if the reservered aread have not changed then we're done */
- if ( screen->strut.left == strut.left &&
- screen->strut.right == strut.right &&
- screen->strut.top == strut.top &&
- screen->strut.bottom == strut.bottom) return;
-
- /* apply the new strut */
- screen->strut.left = strut.left;
- screen->strut.right = strut.right;
- screen->strut.top = strut.top;
- screen->strut.bottom = strut.bottom;
-
- /* set the new workarea */
- data[0] = strut.left;
- data[1] = strut.top;
- data[2] = screen->display_width - (strut.left + strut.right);
- data[3] = screen->display_height - (strut.top + strut.bottom);
- XChangeProperty(dpy, screen->root,
- ewmh_atom[_NET_WORKAREA],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 4);
-
- /* ensure no window fully occupy reserved areas */
- for (c = client_head(); c; c = c->next) {
- int x = c->size.x;
- int y = c->size.y;
-
- if (c->wstate.fullscreen == True) continue;
- backup = interacting_edge;
- interacting_edge = ENone;
- Client_MakeSane(c, ENone, &x, &y, 0, 0);
- interacting_edge = backup;
- if (c->framed == True) {
- XMoveWindow(dpy, c->parent,
- c->size.x,
- c->size.y - titleHeight());
- } else {
- XMoveWindow(dpy, c->parent,
- c->size.x, c->size.y);
- }
- sendConfigureNotify(c);
- }
-
-}
-
-/*
- * get _NET_WM_STRUT and if it is available recalulate the screens
- * reserved areas. the EWMH spec isn't clear about what we should do
- * about hidden windows. It seems silly to reserve space for an invisible
- * window, but the spec allows it. Ho Hum... jfc
- */
-void
-ewmh_get_strut(Client *c) {
- Atom rt;
- unsigned long *strut;
- int fmt;
- unsigned long n;
- unsigned long extra;
- int i;
-
- if (c == NULL) return;
- i = XGetWindowProperty(dpy, c->window,
- ewmh_atom[_NET_WM_STRUT],
- 0, 5, False, XA_CARDINAL, &rt, &fmt, &n, &extra,
- (unsigned char **)&strut);
- if (i != Success || strut == NULL || n < 4) return;
- c->strut.left = (unsigned int) strut[0];
- c->strut.right = (unsigned int) strut[1];
- c->strut.top = (unsigned int) strut[2];
- c->strut.bottom = (unsigned int) strut[3];
- ewmh_set_strut(c->screen);
-}
-
-/* fix stack forces each window on the screen to be in the right place in
- * the window stack as indicated in the EWMH spec version 1.2 (section 7.10).
- */
-static void
-fix_stack(ScreenInfo *screen) {
- Client *c;
-
- /* this is pretty dumb. we should query the tree and only move
- * those windows that require it. doing it regardless liek this
- * causes the desktop to flicker
- */
-
- /* first lower clients with _NET_WM_STATE_BELOW */
- for (c = client_head(); c; c = c->next) {
- if (c->wstate.below == False) continue;
- Client_Lower(c);
- }
-
- /* lower desktops - they are always the lowest */
- for (c = client_head(); c; c = c->next) {
- if (c->wtype != WTypeDesktop) continue;
- Client_Lower(c);
- break; /* only one desktop, surely */
- }
-
- /* raise clients with _NET_WM_STATE_ABOVE and docks
- * (unless marked with _NET_WM_STATE_BELOW)
- */
- for (c = client_head(); c; c = c->next) {
- if (!(c->wstate.above == True ||
- (c->wtype == WTypeDock &&
- c->wstate.below == False)))
- continue;
- Client_Raise(c);
- }
-
- /* raise fullscreens - they're always on top */
- /* Misam Saki reports problems with this and believes fullscreens
- * should not be automatically raised.
- *
- * However if the code below is removed then the panel is raised above
- * fullscreens, which is not desirable.
- */
- for (c = client_head(); c; c = c->next) {
- if (c->wstate.fullscreen == False) continue;
- Client_Raise(c);
- }
+ Atom action[4];
+
+ action[0] = ewmh_atom[_NET_WM_ACTION_MOVE];
+ action[1] = ewmh_atom[_NET_WM_ACTION_RESIZE];
+ action[2] = ewmh_atom[_NET_WM_ACTION_FULLSCREEN];
+ action[3] = ewmh_atom[_NET_WM_ACTION_CLOSE];
+ XChangeProperty(dpy, c->window, ewmh_atom[_NET_WM_ALLOWED_ACTIONS],
+ XA_ATOM, 32, PropModeReplace, (unsigned char *)action, 4);
}
-
static Bool
valid_for_client_list(ScreenInfo *screen, Client *c) {
- if (c->screen != screen) return False;
- if (c->state == WithdrawnState) return False;
- return True;
+ if (c->screen != screen) return False;
+ if (c->state == WithdrawnState) return False;
+ return True;
}
/*
*/
void
ewmh_set_client_list(ScreenInfo *screen) {
- int no_clients=0;
- Window *client_list=NULL;
- Window *stacked_client_list=NULL;
- Client *c;
-
- if (screen == NULL || screen->ewmh_set_client_list == True) return;
- screen->ewmh_set_client_list = True;
- fix_stack(screen);
- for (c = client_head(); c; c = c->next) {
- if (valid_for_client_list(screen, c) == True) no_clients++;
- }
- if (no_clients > 0) {
- int i;
- Window dw1;
- Window dw2;
- Window *wins;
- unsigned int win;
- unsigned int nwins;
-
- client_list = malloc(sizeof(Window) * no_clients);
- i = no_clients - 1; /* array starts with oldest */
- for (c = client_head(); c; c = c->next) {
- if (valid_for_client_list(screen, c) == True) {
- client_list[i] = c->window;
- i--;
- if (i < 0) break;
- }
- }
-
- stacked_client_list = malloc(sizeof(Window) * no_clients);
- i = 0;
- XQueryTree(dpy, screen->root, &dw1, &dw2, &wins, &nwins);
- for (win = 0; win < nwins; win++) {
- c = Client_Get(wins[win]);
- if (!c) continue;
- if (valid_for_client_list(screen, c) == True) {
- stacked_client_list[i] = c->window;
- i++;
- if (i >= no_clients) break;
- }
- }
- if ( nwins > 0 ) XFree(wins);
-
- }
- XChangeProperty(dpy, screen->root,
- ewmh_atom[_NET_CLIENT_LIST],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char*)client_list, no_clients);
- XChangeProperty(dpy, screen->root,
- ewmh_atom[_NET_CLIENT_LIST_STACKING],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char*)stacked_client_list, no_clients);
- if (no_clients > 0 ) {
- free(client_list);
- free(stacked_client_list);
- }
- screen->ewmh_set_client_list = False;
+ int no_clients=0;
+ Window *client_list=NULL;
+ Window *stacked_client_list=NULL;
+ Client *c;
+
+ if (screen == NULL || screen->ewmh_set_client_list == True) return;
+ screen->ewmh_set_client_list = True;
+ for (c = Client_List(); c; c = c->next) {
+ if (valid_for_client_list(screen, c) == True) no_clients++;
+ }
+ if (no_clients > 0) {
+ int i;
+ Window dw1;
+ Window dw2;
+ Window *wins;
+ unsigned int win;
+ unsigned int nwins;
+
+ client_list = malloc(sizeof(Window) * no_clients);
+ i = no_clients - 1; /* array starts with oldest */
+ for (c = Client_List(); c; c = c->next) {
+ if (valid_for_client_list(screen, c) == True) {
+ client_list[i] = c->window;
+ i--;
+ if (i < 0) break;
+ }
+ }
+
+ stacked_client_list = malloc(sizeof(Window) * no_clients);
+ i = 0;
+ XQueryTree(dpy, screen->root, &dw1, &dw2, &wins, &nwins);
+ for (win = 0; win < nwins; win++) {
+ c = Client_Get(wins[win]);
+ if (!c) continue;
+ if (valid_for_client_list(screen, c) == True) {
+ stacked_client_list[i] = c->window;
+ i++;
+ if (i >= no_clients) break;
+ }
+ }
+ if ( nwins > 0 ) XFree(wins);
+
+ }
+ XChangeProperty(dpy, screen->root,
+ ewmh_atom[_NET_CLIENT_LIST],
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char*)client_list, no_clients);
+ XChangeProperty(dpy, screen->root,
+ ewmh_atom[_NET_CLIENT_LIST_STACKING],
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char*)stacked_client_list, no_clients);
+ if (no_clients > 0 ) {
+ free(client_list);
+ free(stacked_client_list);
+ }
+ screen->ewmh_set_client_list = False;
}
#include "lwm.h"
-Mode mode; /* The window manager's mode. (See "lwm.h".) */
-int start_x; /* The X position where the mode changed. */
-int start_y; /* The Y position where the mode changed. */
-
-Display * dpy; /* The connection to the X server. */
-int screen_count; /* The number of screens. */
-ScreenInfo * screens; /* Information about these screens. */
+char *font_name = DEFAULT_TITLE_FONT; /* User's choice of titlebar font. */
+int border = DEFAULT_BORDER; /* User's choice of border size. */
+Mode mode; /* The window manager's mode. (See "lwm.h".) */
+int start_x; /* The X position where the mode changed. */
+int start_y; /* The Y position where the mode changed. */
+
+Display * dpy; /* The connection to the X server. */
+int screen_count; /* The number of screens. */
+ScreenInfo * screens; /* Information about these screens. */
ScreenInfo * current_screen;
-XFontSet font_set = NULL; /* Font set for title var */
+XFontSet font_set = NULL; /* Font set for title var */
XFontSetExtents *font_set_ext = NULL;
-XFontSet popup_font_set = NULL; /* Font set for popups */
-XFontSetExtents *popup_font_set_ext = NULL;
-
-Bool shape; /* Does server have Shape Window extension? */
-int shape_event; /* ShapeEvent event type. */
/* Atoms we're interested in. See the ICCCM for more information. */
Atom wm_state;
Atom wm_colormaps;
Atom compound_text;
-/** Netscape uses this to give information about the URL it's displaying. */
-Atom _mozilla_url;
-
-/*
- * if we're really short of a clue we might look at motif hints, and
- * we're not going to link with motif, so we'll have to do it by hand
- */
-Atom motif_wm_hints;
-
char *argv0;
static void initScreens(void);
static void initScreen(int);
-char *font_name; /* User's choice of titlebar font. */
-char *popup_font_name; /* User's choice of menu font. */
-char *btn1_command; /* User's choice of button 1 command. */
-char *btn2_command; /* User's choice of button 2 command. */
-int border; /* User's choice of border size. */
-FocusMode focus_mode; /* User's choice of focus mode (default enter) */
-
-void getMousePosition(int * x, int * y) {
- Window root, child;
- int t1, t2;
- unsigned int b;
-
- /* It doesn't matter which root window we give this call. */
- XQueryPointer(dpy, screens[0].root, &root, &child, x, y, &t1, &t2, &b);
- current_screen = getScreenFromRoot(root);
-}
-
-void parseResources(void) {
- /* Set our fall-back defaults. */
- font_name = DEFAULT_TITLE_FONT;
- popup_font_name = DEFAULT_POPUP_FONT;
- border = DEFAULT_BORDER;
- btn1_command = 0;
- btn2_command = DEFAULT_TERMINAL;
- focus_mode = focus_enter;
-}
-
-int main(int argc, char *argv[]) {
- XEvent ev;
- struct sigaction sa;
- int dpy_fd, max_fd;
-
- argv0 = argv[0];
-
- mode = wm_initialising;
-
- /* Open a connection to the X server. */
- dpy = XOpenDisplay(NULL);
- if (dpy == 0)
- panic("can't open display.");
-
- parseResources();
-
- /* Set up an error handler. */
- XSetErrorHandler(errorHandler);
-
- /* Set up signal handlers. */
- signal(SIGTERM, Terminate);
- signal(SIGINT, Terminate);
- signal(SIGHUP, Terminate);
-
- /* Ignore SIGCHLD. */
- sa.sa_handler = SIG_IGN;
-#ifdef SA_NOCLDWAIT
- sa.sa_flags = SA_NOCLDWAIT;
-#else
- sa.sa_flags = 0;
-#endif
- sigemptyset(&sa.sa_mask);
- sigaction(SIGCHLD, &sa, 0);
-
- /* Internalize useful atoms. */
- wm_state = XInternAtom(dpy, "WM_STATE", False);
- wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False);
- wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
- wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
- wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
- wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
- compound_text = XInternAtom(dpy, "COMPOUND_TEXT", False);
-
- _mozilla_url = XInternAtom(dpy, "_MOZILLA_URL", False);
-
- motif_wm_hints = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
-
- ewmh_init();
-
- /*
- * Get fonts for our titlebar and our popup window. We try to
- * get Lucida, but if we can't we make do with fixed because everyone
- * has that.
- */
- {
- /* FIXME: do these need to be freed? */
- char **missing;
- char *def;
- int missing_count;
-
- font_set = XCreateFontSet(dpy, font_name,
- &missing, &missing_count, &def);
- if (font_set == NULL)
- font_set = XCreateFontSet(dpy, "fixed",
- &missing, &missing_count, &def);
- if (font_set == NULL)
- panic("unable to create font set for title font");
- if (missing_count > 0)
- fprintf(stderr,"%s: warning: missing %d charset"
- "%s for title font\n", argv0, missing_count,
- (missing_count == 1)?"":"s");
- font_set_ext = XExtentsOfFontSet(font_set);
-
- popup_font_set = XCreateFontSet(dpy, popup_font_name,
- &missing, &missing_count, &def);
- if (popup_font_set == NULL)
- popup_font_set = XCreateFontSet(dpy, "fixed",
- &missing, &missing_count, &def);
- if (popup_font_set == NULL)
- panic("unable to create font set for popup font");
- if (missing_count > 0)
- fprintf(stderr,"%s: warning: missing %d charset"
- "%s for popup font\n", argv0, missing_count,
- (missing_count == 1)?"":"s");
- popup_font_set_ext = XExtentsOfFontSet(popup_font_set);
- }
-
- initScreens();
- ewmh_init_screens();
-
- /* See if the server has the Shape Window extension. */
- shape = serverSupportsShapes();
-
- /*
- * Initialisation is finished, but we start off not interacting with the
- * user.
- */
- mode = wm_idle;
-
- /*
- * The main event loop.
- */
- dpy_fd = ConnectionNumber(dpy);
- max_fd = dpy_fd + 1;
- for (;;) {
- fd_set readfds;
-
- FD_ZERO(&readfds);
- FD_SET(dpy_fd, &readfds);
- if (select(max_fd, &readfds, NULL, NULL, NULL) > -1) {
- if (FD_ISSET(dpy_fd, &readfds)) {
- while (XPending(dpy)) {
- XNextEvent(dpy, &ev);
- dispatch(&ev);
- }
- }
- }
- }
+/*ARGSUSED*/
+extern int
+main(int argc, char *argv[]) {
+ XEvent ev;
+ argv0 = argv[0];
+ mode = wm_initialising;
+
+ /* Open a connection to the X server. */
+ dpy = XOpenDisplay(NULL);
+ if (dpy == 0)
+ panic("can't open display.");
+
+ /* Set up an error handler. */
+ XSetErrorHandler(errorHandler);
+
+ /* Internalize useful atoms. */
+ wm_state = XInternAtom(dpy, "WM_STATE", False);
+ wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False);
+ wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
+ wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
+ wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
+ compound_text = XInternAtom(dpy, "COMPOUND_TEXT", False);
+ ewmh_init();
+
+ /*
+ * Get fonts for our titlebar and our popup window. We try to
+ * get Lucida, but if we can't we make do with fixed because everyone
+ * has that.
+ */
+ {
+ /* FIXME: do these need to be freed? */
+ char **missing;
+ char *def;
+ int missing_count;
+
+ font_set = XCreateFontSet(dpy, font_name,
+ &missing, &missing_count, &def);
+ if (font_set == NULL)
+ font_set = XCreateFontSet(dpy, "fixed",
+ &missing, &missing_count, &def);
+ if (font_set == NULL)
+ panic("unable to create font set for title font");
+ if (missing_count > 0)
+ fprintf(stderr,"%s: warning: missing %d charset"
+ "%s for title font\n", argv0, missing_count,
+ (missing_count == 1)?"":"s");
+ font_set_ext = XExtentsOfFontSet(font_set);
+ }
+
+ initScreens();
+ ewmh_init_screens();
+
+ /*
+ * Initialisation is finished, but we start off not interacting with the
+ * user.
+ */
+ mode = wm_idle;
+
+ /*
+ * The main event loop.
+ */
+ for (;;)
+ {
+ XNextEvent(dpy, &ev);
+ dispatch(&ev);
+ }
}
void
sendConfigureNotify(Client *c) {
- XConfigureEvent ce;
-
- ce.type = ConfigureNotify;
- ce.event = c->window;
- ce.window = c->window;
- if (c->framed == True) {
- ce.x = c->size.x + border;
- ce.y = c->size.y + border;
- ce.width = c->size.width - 2 * border;
- ce.height = c->size.height - 2 * border;
- ce.border_width = c->border;
- } else {
- ce.x = c->size.x;
- ce.y = c->size.y;
- ce.width = c->size.width;
- ce.height = c->size.height;
- ce.border_width = c->border;
- }
- ce.above = None;
- ce.override_redirect = 0;
- XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent *) &ce);
+ XConfigureEvent ce;
+ ce.type = ConfigureNotify;
+ ce.event = c->window;
+ ce.window = c->window;
+ if (c->framed == True) {
+ ce.x = c->size.x + border;
+ ce.y = c->size.y + border;
+ ce.width = c->size.width - 2 * border;
+ ce.height = c->size.height - 2 * border;
+ ce.border_width = c->border;
+ } else {
+ ce.x = c->size.x;
+ ce.y = c->size.y;
+ ce.width = c->size.width;
+ ce.height = c->size.height;
+ ce.border_width = c->border;
+ }
+ ce.above = None;
+ ce.override_redirect = 0;
+ XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent *) &ce);
}
extern void
scanWindowTree(int screen) {
- unsigned int i;
- unsigned int nwins;
- Client * c;
- Window dw1;
- Window dw2;
- Window * wins;
- XWindowAttributes attr;
-
- XQueryTree(dpy, screens[screen].root, &dw1, &dw2, &wins, &nwins);
- for (i = 0; i < nwins; i++) {
- XGetWindowAttributes(dpy, wins[i], &attr);
- if (attr.override_redirect /*|| isShaped(wins[i])*/ || wins[i] == screens[screen].popup)
- continue;
- c = Client_Add(wins[i], screens[screen].root);
- if (c != 0 && c->window == wins[i]) {
- c->screen = &screens[screen];
- c->size.x = attr.x;
- c->size.y = attr.y;
-/* we'll leave it until it's managed
- if (c->framed == True) {
- c->size.x -= border;
- c->size.y -= border;
- }
-*/
- c->size.width = attr.width;
- c->size.height = attr.height;
-/* we'll leave it until it's managed
- if (c->framed == True) {
- c->size.width += 2 * border;
- c->size.height += 2 * border;
- }
-*/
- c->border = attr.border_width;
- if (attr.map_state == IsViewable) {
- c->internal_state = IPendingReparenting;
- manage(c, 1);
- }
- }
- }
- XFree(wins);
-}
-
-/*ARGSUSED*/
-extern void
-shell(ScreenInfo * screen, int button, int x, int y) {
- char * command = NULL;
- char * sh;
-
- /* Get the command we're to execute. Give up if there isn't one. */
- if (button == Button1)
- command = btn1_command;
- if (button == Button2)
- command = btn2_command;
- if (command == NULL)
- return;
-
- sh = getenv("SHELL");
- if (sh == 0)
- sh = "/bin/sh";
-
- switch (fork()) {
- case 0: /* Child. */
- close(ConnectionNumber(dpy));
- if (screen && screen->display_spec != 0)
- putenv(screen->display_spec);
- execl(sh, sh, "-c", command, NULL);
- fprintf(stderr, "%s: can't exec \"%s -c %s\"\n", argv0, sh,
- command);
- execlp("xterm", "xterm", NULL);
- exit(EXIT_FAILURE);
- case -1: /* Error. */
- fprintf(stderr, "%s: couldn't fork\n", argv0);
- break;
- }
+ unsigned int i;
+ unsigned int nwins;
+ Client * c;
+ Window dw1;
+ Window dw2;
+ Window * wins;
+ XWindowAttributes attr;
+
+ XQueryTree(dpy, screens[screen].root, &dw1, &dw2, &wins, &nwins);
+ for (i = 0; i < nwins; i++) {
+ XGetWindowAttributes(dpy, wins[i], &attr);
+ if (attr.override_redirect)
+ continue;
+ c = Client_Add(wins[i], screens[screen].root);
+ if (c != 0 && c->window == wins[i]) {
+ c->screen = &screens[screen];
+ c->size.x = attr.x;
+ c->size.y = attr.y;
+ c->size.width = attr.width;
+ c->size.height = attr.height;
+ c->border = attr.border_width;
+ if (attr.map_state == IsViewable) {
+ c->internal_state = IPendingReparenting;
+ manage(c, 1);
+ }
+ }
+ }
+ XFree(wins);
}
extern int
titleHeight(void) {
- return font_set_ext->max_logical_extent.height;
+ return font_set_ext->max_logical_extent.height;
}
extern int
ascent(XFontSetExtents *font_set_ext) {
- return abs(font_set_ext->max_logical_extent.y);
-}
-
-extern int
-popupHeight(void) {
- return popup_font_set_ext->max_logical_extent.height;
+ return abs(font_set_ext->max_logical_extent.y);
}
extern int
titleWidth(XFontSet font_set, Client *c) {
- XRectangle ink;
- XRectangle logical;
- char *name;
- int namelen;
-
- if (c == NULL) return 0;
- if (c->menu_name == NULL) {
- name = c->name;
- namelen = c->namelen;
- } else {
- name = c->menu_name;
- namelen = c->menu_namelen;
- }
- if (name == NULL) return 0;
-#ifdef X_HAVE_UTF8_STRING
- if (c->name_utf8 == True)
- Xutf8TextExtents(font_set, name, namelen,
- &ink, &logical);
- else
-#endif
- XmbTextExtents(font_set, name, namelen,
- &ink, &logical);
-
- return logical.width;
-}
-
-extern int
-popupWidth(char *string, int string_length) {
- XRectangle ink;
- XRectangle logical;
-
- XmbTextExtents(popup_font_set, string, string_length,
- &ink, &logical);
-
- return logical.width;
+ XRectangle ink;
+ XRectangle logical;
+ char *name;
+ int namelen;
+
+ if (c == NULL) return 0;
+ name = c->name;
+ namelen = c->namelen;
+ if (name == NULL) return 0;
+ Xutf8TextExtents(font_set, name, namelen,
+ &ink, &logical);
+
+ return logical.width;
}
static void
initScreens(void) {
- int screen;
-
- /* Find out how many screens we've got, and allocate space for their info. */
- screen_count = ScreenCount(dpy);
- screens = (ScreenInfo *) malloc(screen_count * sizeof(ScreenInfo));
-
- /* Go through the screens one-by-one, initialising them. */
- for (screen = 0; screen < screen_count; screen++) {
- initialiseCursors(screen);
- initScreen(screen);
- scanWindowTree(screen);
- }
+ int screen;
+
+ /* Find out how many screens we've got, and allocate space for their info. */
+ screen_count = ScreenCount(dpy);
+ screens = (ScreenInfo *) malloc(screen_count * sizeof(ScreenInfo));
+
+ /* Go through the screens one-by-one, initialising them. */
+ for (screen = 0; screen < screen_count; screen++) {
+ initialiseCursors(screen);
+ initScreen(screen);
+ scanWindowTree(screen);
+ }
}
static void
initScreen(int screen) {
- XGCValues gv;
- XSetWindowAttributes attr;
- XColor colour, exact;
- int len;
- char * display_string = DisplayString(dpy);
- char * colon = strrchr(display_string, ':');
- char * dot = NULL;
-
- /* Set the DISPLAY specification. */
- if (colon) {
- dot = strrchr(colon, '.');
- len = 9 + strlen(display_string) + ((dot == 0) ? 2 : 0) + 10;
- screens[screen].display_spec = (char *) malloc(len);
- sprintf(screens[screen].display_spec, "DISPLAY=%s", display_string);
- if (dot == 0) dot = screens[screen].display_spec + len - 3;
- else dot = strrchr(screens[screen].display_spec, '.');
- sprintf(dot, ".%i", screen);
- } else {
- screens[screen].display_spec = 0;
- }
-
- /* Find the root window. */
- screens[screen].root = RootWindow(dpy, screen);
- screens[screen].display_width = DisplayWidth(dpy, screen);
- screens[screen].display_height = DisplayHeight(dpy, screen);
- screens[screen].strut.left = 0;
- screens[screen].strut.right = 0;
- screens[screen].strut.top = 0;
- screens[screen].strut.bottom = 0;
-
- /* Get the pixel values of the only two colours we use. */
- screens[screen].black = BlackPixel(dpy, screen);
- screens[screen].white = WhitePixel(dpy, screen);
- XAllocNamedColor(dpy, DefaultColormap(dpy, screen), "DimGray", &colour, &exact);
- screens[screen].gray = colour.pixel;
-
- /* Set up root (frame) GC's. */
- gv.foreground = screens[screen].black ^ screens[screen].white;
- gv.background = screens[screen].white;
- gv.function = GXxor;
- gv.line_width = 1;
- gv.subwindow_mode = IncludeInferiors;
- screens[screen].gc_thin = XCreateGC(dpy, screens[screen].root,
- GCForeground | GCBackground | GCFunction |
- GCLineWidth | GCSubwindowMode, &gv);
-
- gv.line_width = 2;
- screens[screen].gc = XCreateGC(dpy, screens[screen].root,
- GCForeground | GCBackground | GCFunction |
- GCLineWidth | GCSubwindowMode, &gv);
-
- /* Create a window for our popup. */
- screens[screen].popup = XCreateSimpleWindow(dpy, screens[screen].root,
- 0, 0, 1, 1, 1, screens[screen].black, screens[screen].white);
- attr.event_mask = ButtonMask | ButtonMotionMask | ExposureMask;
- XChangeWindowAttributes(dpy, screens[screen].popup, CWEventMask, &attr);
-
- /* Create menu GC. */
- gv.line_width = 1;
- screens[screen].menu_gc = XCreateGC(dpy, screens[screen].popup,
- GCForeground | GCBackground | GCFunction |
- GCLineWidth | GCSubwindowMode, &gv);
-
- /* Create size indicator GC. */
- gv.foreground = screens[screen].black;
- gv.function = GXcopy;
- screens[screen].size_gc = XCreateGC(dpy, screens[screen].popup,
- GCForeground | GCBackground | GCFunction |
- GCLineWidth | GCSubwindowMode, &gv);
-
- /* Announce our interest in the root window. */
- attr.cursor = screens[screen].root_cursor;
- attr.event_mask = SubstructureRedirectMask | SubstructureNotifyMask |
- ColormapChangeMask | ButtonPressMask | PropertyChangeMask |
- EnterWindowMask;
- XChangeWindowAttributes(dpy, screens[screen].root, CWCursor |
- CWEventMask, &attr);
-
- /* Make sure all our communication to the server got through. */
- XSync(dpy, False);
+ XGCValues gv;
+ XSetWindowAttributes attr;
+ XColor colour, exact;
+ int len;
+ char * display_string = DisplayString(dpy);
+ char * colon = strrchr(display_string, ':');
+ char * dot = NULL;
+
+ /* Set the DISPLAY specification. */
+ if (colon) {
+ dot = strrchr(colon, '.');
+ len = 9 + strlen(display_string) + ((dot == 0) ? 2 : 0) + 10;
+ screens[screen].display_spec = (char *) malloc(len);
+ sprintf(screens[screen].display_spec, "DISPLAY=%s", display_string);
+ if (dot == 0) dot = screens[screen].display_spec + len - 3;
+ else dot = strrchr(screens[screen].display_spec, '.');
+ sprintf(dot, ".%i", screen);
+ } else {
+ screens[screen].display_spec = 0;
+ }
+
+ /* Find the root window. */
+ screens[screen].root = RootWindow(dpy, screen);
+ screens[screen].display_width = DisplayWidth(dpy, screen);
+ screens[screen].display_height = DisplayHeight(dpy, screen);
+
+ /* Get the pixel values of the only two colours we use. */
+ screens[screen].black = BlackPixel(dpy, screen);
+ screens[screen].white = WhitePixel(dpy, screen);
+ XAllocNamedColor(dpy, DefaultColormap(dpy, screen), "DimGray", &colour, &exact);
+ screens[screen].gray = colour.pixel;
+
+ /* Set up root (frame) GC's. */
+ gv.foreground = screens[screen].black ^ screens[screen].white;
+ gv.background = screens[screen].white;
+ gv.function = GXxor;
+ gv.line_width = 1;
+ gv.subwindow_mode = IncludeInferiors;
+
+ gv.line_width = 2;
+ screens[screen].gc = XCreateGC(dpy, screens[screen].root,
+ GCForeground | GCBackground | GCFunction |
+ GCLineWidth | GCSubwindowMode, &gv);
+
+ /* Announce our interest in the root window. */
+ attr.cursor = screens[screen].root_cursor;
+ attr.event_mask = SubstructureRedirectMask | SubstructureNotifyMask |
+ ColormapChangeMask | ButtonPressMask | PropertyChangeMask |
+ EnterWindowMask;
+ XChangeWindowAttributes(dpy, screens[screen].root, CWCursor |
+ CWEventMask, &attr);
+
+ /* Make sure all our communication to the server got through. */
+ XSync(dpy, False);
}
/**
*/
ScreenInfo *
getScreenFromRoot(Window root) {
- int screen;
+ int screen;
- for (screen = 0; screen < screen_count; screen++)
- if (screens[screen].root == root)
- return &screens[screen];
+ for (screen = 0; screen < screen_count; screen++)
+ if (screens[screen].root == root)
+ return &screens[screen];
- return 0;
+ return 0;
}
/* --- Administrator-configurable defaults. --- */
#define DEFAULT_TITLE_FONT "-*-lucida-bold-r-normal-sans-14-*-*-*-p-*-iso10646-1"
-#define DEFAULT_POPUP_FONT "-*-lucida-medium-r-normal-sans-12-*-*-*-p-*-iso10646-1"
-#define DEFAULT_TERMINAL "xterm"
-#define DEFAULT_BORDER 6
-
-#define HIDE_BUTTON Button3
-#define MOVE_BUTTON Button2
-#define RESHAPE_BUTTON Button1
-
-#define EDGE_RESIST 32
+#define DEFAULT_TERMINAL "xterm"
+#define DEFAULT_BORDER 3
/* --- End of administrator-configurable defaults. --- */
* initialising.
*/
typedef enum {
- wm_initialising,
- wm_idle,
- wm_reshaping,
- wm_menu_up,
- wm_closing_window,
- wm_hiding_window
+ wm_initialising,
+ wm_idle,
+ wm_reshaping,
} Mode;
/** Window internal state. Yuck. */
typedef enum {
- IPendingReparenting, INormal
-} IState ;
-
-
-/**
-* Focus mode, may me (and defaults to) enter where entering a window gives
-* that window input focus, or click where a window must be explicitly clicked
-* to give it the focus.
-*/
-typedef enum {
- focus_enter, focus_click
-} FocusMode;
+ IPendingReparenting, INormal
+} IState;
/**
* Window edge, used in resizing. The `edge' ENone is used to signify a
* this isn't a special case to be treated separately.
*/
typedef enum {
- ETopLeft, ETop, ETopRight,
- ERight, ENone, ELeft,
- EBottomLeft, EBottom, EBottomRight,
- E_LAST
+ ETopLeft, ETop, ETopRight,
+ ERight, ENone, ELeft,
+ EBottomLeft, EBottom, EBottomRight,
+ E_LAST
} Edge ;
/**
* EWMH direction for _NET_WM_MOVERESIZE
*/
typedef enum {
- DSizeTopLeft, DSizeTop, DSizeTopRight,
- DSizeRight, DSizeBottomRight, DSizeBottom,
- DSizeBottomLeft, DSizeLeft, DMove,
- DSizeKeyboard, DMoveKeyboard
+ DSizeTopLeft, DSizeTop, DSizeTopRight,
+ DSizeRight, DSizeBottomRight, DSizeBottom,
+ DSizeBottomLeft, DSizeLeft, DMove,
+ DSizeKeyboard, DMoveKeyboard
} EWMHDirection;
/**
* hints should be used instead.
*/
typedef enum {
- WTypeDesktop, WTypeDock, WTypeToolbar,
- WTypeMenu, WTypeUtility, WTypeSplash,
- WTypeDialog, WTypeNormal, WTypeNone
+ WTypeDesktop, WTypeDock, WTypeToolbar,
+ WTypeMenu, WTypeUtility, WTypeSplash,
+ WTypeDialog, WTypeNormal, WTypeNone
} EWMHWindowType;
-/**
-* EWMH window state, See section 5.7 of the EWMH specification (1.2).
-* lwm does not support all states. _NET_WM_STATE_HIDDEN is taken from
-* Client.hidden.
-*/
-typedef struct {
- Bool skip_taskbar;
- Bool skip_pager;
- Bool fullscreen;
- Bool above;
- Bool below;
-} EWMHWindowState;
-
-/**
-* EWMH "strut", or area on each edge of the screen reserved for docking
-* bars/panels.
-*/
-typedef struct {
- unsigned int left;
- unsigned int right;
- unsigned int top;
- unsigned int bottom;
-} EWMHStrut;
-
/**
* Screen information.
*/
typedef struct ScreenInfo ScreenInfo;
struct ScreenInfo {
- Window root;
- Window popup;
- Window ewmh_compat;
-
- int display_width; /* The width of the screen. */
- int display_height; /* The height of the screen. */
- EWMHStrut strut; /* reserved areas */
-
- GC gc; /* The default GC. */
- GC gc_thin; /* The default GC but with thinner lines. */
- GC menu_gc; /* The GC for the popup window (menu). */
- GC size_gc; /* The GC for the popup window (sizing). */
-
- unsigned long black; /* Black pixel value. */
- unsigned long white; /* White pixel value. */
- unsigned long gray; /* Gray pixel value. */
-
- Cursor root_cursor;
- Cursor box_cursor;
-
- Cursor cursor_map[E_LAST];
-
- Bool ewmh_set_client_list; /* hack to prevent recursion */
-
- char * display_spec;
+ Window root;
+ Window ewmh_compat;
+ int display_width; /* The width of the screen. */
+ int display_height; /* The height of the screen. */
+ GC gc; /* The default GC. */
+ unsigned long black; /* Black pixel value. */
+ unsigned long white; /* White pixel value. */
+ unsigned long gray; /* Gray pixel value. */
+
+ Cursor root_cursor;
+ Cursor box_cursor;
+ Cursor cursor_map[E_LAST];
+ Bool ewmh_set_client_list; /* hack to prevent recursion */
+ char * display_spec;
};
-typedef struct Client Client;
-struct Client {
- Window window; /* Client's window. */
- Window parent; /* Window manager frame. */
- Window trans; /* Window that client is a transient for. */
-
- Bool framed; /* True is lwm is maintaining a frame */
-
- Client * next; /* Next window in client list. */
-
- int border; /* Client's original border width. */
-
- XSizeHints size; /* Client's current geometry information. */
- XSizeHints return_size; /* Client's old geometry information. */
- int state; /* Window state. See ICCCM and <X11/Xutil.h> */
-
- Bool hidden; /* True if this client is hidden. */
- IState internal_state;
- int proto;
-
- int accepts_focus; /* Does this window want keyboard events? */
-
- char * name; /* Name used for title in frame. */
- int namelen;
- char * menu_name; /* Name used in root popup */
- int menu_namelen;
- Bool name_utf8;
-
- ScreenInfo * screen;
-
- Edge cursor; /* indicates which cursor is being used for parent window */
-
- EWMHWindowType wtype;
- EWMHWindowState wstate;
- EWMHStrut strut; /* reserved areas */
-
- /* Colourmap scum. */
- Colormap cmap;
- int ncmapwins;
- Window * cmapwins;
- Colormap * wmcmaps;
-};
-
-
-/*
- * c->proto is a bitarray of these
- */
+/* Client flags for EWMH protocols and window behavior */
enum {
- Pdelete = 1,
- Ptakefocus = 2
+ F_ACCEPT_FOCUS = (1 << 0),
+ F_EWMH_DELETE = (1 << 1),
+ F_EWMH_TAKE_FOCUS = (1 << 2),
};
+typedef struct Client {
+ strcut Client* next; /* Next window in client list. */
+ Window window; /* Client's window. */
+ Window parent; /* Window manager frame. */
+ Window trans; /* Window that client is a transient for. */
+ Bool framed; /* True is lwm is maintaining a frame */
+ int border; /* Client's original border width. */
+ XSizeHints size; /* Client's current geometry information. */
+ int state; /* Window state. See ICCCM and <X11/Xutil.h> */
+ int flags; /* Flags governing client behavior */
+ char * name; /* Name used for title in frame. */
+ int namelen; /* Length of client name */
+ Edge cursor; /* indicates which cursor is being used for parent window */
+ IState internal_state;
+ ScreenInfo * screen;
+ EWMHWindowType wtype;
+} Client;
+
/*
* This should really have been in X.h --- if you select both ButtonPress
* and ButtonRelease events, the server makes an automatic grab on the
*/
#define ButtonMask (ButtonPressMask | ButtonReleaseMask)
-/* lwm.c */
+/* lwm.c */
+extern char *font_name;
+extern int border;
extern Mode mode;
extern int start_x;
extern int start_y;
extern ScreenInfo * current_screen;
extern XFontSet font_set;
extern XFontSetExtents *font_set_ext;
-extern XFontSet popup_font_set;
-extern XFontSetExtents *popup_font_set_ext;
-extern Atom _mozilla_url;
-extern Atom motif_wm_hints;
extern Atom wm_state;
extern Atom wm_change_state;
extern Atom wm_protocols;
extern Atom wm_delete;
extern Atom wm_take_focus;
-extern Atom wm_colormaps;
extern Atom compound_text;
-extern Bool shape;
-extern int shape_event;
extern char *argv0;
-extern void shell(ScreenInfo *, int, int, int);
extern void sendConfigureNotify(Client *);
extern int titleHeight(void);
extern int titleWidth(XFontSet font_set, Client *c);
-extern int popupHeight(void);
-extern int popupWidth(char *string, int string_length);
extern int ascent(XFontSetExtents *font_set_ext);
extern ScreenInfo * getScreenFromRoot(Window);
extern void scanWindowTree(int);
-/* client.c */
-extern Client *client_head(void);
+/* client.c */
extern Edge interacting_edge;
+extern Client *current;
+extern Client *Client_List(void);
extern Client *Client_Get(Window);
extern Client *Client_Add(Window, Window);
extern void Client_MakeSane(Client *, Edge, int *, int *, int *, int *);
-extern void Client_DrawBorder(Client *, int);
-extern void setactive(Client *, int, long);
-extern void size_expose(void);
+extern void Client_DrawFrame(Client *, int);
+extern void Client_SetActive(Client *, int, long);
extern void Client_ReshapeEdge(Client *, Edge);
extern void Client_Move(Client*);
extern void Client_SetState(Client *, int);
extern void Client_Lower(Client *);
extern void Client_Close(Client *);
extern void Client_Remove(Client *);
-extern void Client_FreeAll(void);
-extern void Client_ColourMap(XEvent*);
-extern void Client_EnterFullScreen(Client *c);
-extern void Client_ExitFullScreen(Client *c);
extern void Client_Focus(Client *c, Time time);
extern void Client_ResetAllCursors(void);
-extern void Client_Name(Client *c, const char *name, Bool is_utf8);
-extern int hidden(Client *);
-extern int withdrawn(Client *);
-extern int normal(Client *);
-extern void update_client_list(ScreenInfo *screen);
-extern Client *current;
+extern void Client_Name(Client *c, const char *name);
+extern int Client_IsState(Client*, int);
+extern int Client_HasFlags(Client*, int);
-/* cursor.c */
+/* cursor.c */
extern Cursor getEdgeCursor(Edge edge);
extern void initialiseCursors(int);
-/* disp.c */
+/* disp.c */
extern void dispatch(XEvent *);
-extern void reshaping_motionnotify(XEvent *);
-/* error.c */
+/* error.c */
extern int ignore_badwindow;
extern int errorHandler(Display *, XErrorEvent *);
extern void panic(char*);
-/* manage.c */
+/* manage.c */
extern void getWindowName(Client *);
extern void getNormalHints(Client *);
-extern Bool motifWouldDecorate(Client *);
extern void manage(Client *, int);
extern void withdraw(Client *);
-extern void cmapfocus(Client *);
-extern void getColourmaps(Client *);
extern void getTransientFor(Client *);
-extern void Terminate(int);
-/* mouse.c */
+/* mouse.c */
extern void getMousePosition(int *, int *);
-extern void hide(Client *);
-extern void unhidec(Client *, int);
-extern int menu_whichitem(int, int);
-extern void menuhit(XButtonEvent *);
-extern void unhide(int, int);
-extern void menu_expose(void);
-extern void menu_motionnotify(XEvent *);
-extern void menu_buttonrelease(XEvent *);
-
-/* shape.c */
-extern int shapeEvent(XEvent *);
-extern int serverSupportsShapes(void);
-extern int isShaped(Window);
-extern void setShape(Client *);
-
-/* resource.c */
-extern char *font_name;
-extern char *popup_font_name;
-extern char *btn1_command;
-extern char *btn2_command;
-extern int border;
-extern FocusMode focus_mode;
-extern char * sdup(char *);
-extern void parseResources(void);
-/* ewmh.c */
+/* ewmh.c */
extern Atom ewmh_atom[];
extern void ewmh_init(void);
extern void ewmh_init_screens(void);
extern EWMHWindowType ewmh_get_window_type(Window w);
extern Bool ewmh_get_window_name(Client *c);
extern Bool ewmh_hasframe(Client *c);
-extern void ewmh_set_state(Client *c);
-extern void ewmh_get_state(Client *c);
-extern void ewmh_change_state(Client *c, unsigned long action,
- unsigned long atom);
extern void ewmh_set_allowed(Client *c);
extern void ewmh_set_client_list(ScreenInfo *screen);
-extern void ewmh_get_strut(Client *c);
-extern void ewmh_set_strut(ScreenInfo *screen);
+++ /dev/null
-.\" lwm, a window manager for X11
-.\" Copyright (C) 1997-2016 Elliott Hughes, James Carter
-.\"
-.\" This program is free software; you can redistribute it and/or
-.\" modify it under the terms of the GNU General Public License
-.\" as published by the Free Software Foundation; either version 2
-.\" of the License, or (at your option) any later version.
-.\"
-.\" This program is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public License
-.\" along with this program; if not, write to the Free Software
-.\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-.\"
-.TH LWM 1
-.SH NAME
-lwm \- Lightweight Window Manager for the X Window System
-.SH SYNTAX
-\fBlwm \fP[ \fB\-s\fP \fIsession-id\fP ]
-.SH DESCRIPTION
-\fILwm\fP is a window manager for the X Window System. It provides enough
-features to allow the user to manage their windows, and no more.
-.PP
-Windows are surrounded by a frame with a
-titlebar at the top next to a small box. The frame is a grey colour for
-all windows except that which has the input focus, where it is black.
-.PP
-In the default configuration, \fIlwm\fP uses the enter-to-focus scheme, where
-moving the pointer into a window gives that window the input focus.
-\fILwm\fP may also be configured to use the click-to-focus scheme, where a
-window must be clicked on (with any button) to receive the input focus. Clicking
-on a window in this mode causes the window to be raised. Note that a click
-used to focus a window is always swallowed by \fIlwm\fP, so clicking a
-button in a new window requires two clicks.
-.PP
-A button 1 click on a window frame brings that window to the top. Dragging
-button 1 on the frame of a resizable window repositions that edge of
-the window. If a corner rather than an edge is dragged, then both edges
-forming the corner are repositioned. While you're reshaping a window,
-a little window pops up to show you the window's current size.
-.PP
-In the default configuration, button 1 on the root window does nothing.
-.PP
-Button 2 is used to drag a window by its frame, repositioning the window
-but maintaining its position in the window stack.
-.PP
-In the default configuration, button 2 on the root window brings up a
-new shell.
-.PP
-A button 3 click on a window frame hides that window. Pressing
-button 3 on the root window brings up a menu of all the hidden windows.
-Releasing the button while over an item will unhide the named window.
-.PP
-A button 3 click in the frame while Shift is held down pushes the window
-to the back, under any other windows. (Users with 4-button mice are
-encouraged to use their fourth button for this function.)
-.PP
-A click with any button inside the little white box in a window's frame
-can be used to close the window.
-.SH OPTIONS
-\fILwm\fP accepts the following command line options:
-.PP
-.TP 8
-.B \-s
-specifies a client ID for the X Session Management system, and is used
-exclusively by session managers.
-.SH RESOURCES
-\fILwm\fP understands the following X resources:
-.TP 12
-.B titlefont
-font used in window titles
-.TP 12
-.B popupFont
-font used in popup window (menu/size indicator)
-.TP 12
-.B border
-width in pixels of window borders
-.TP 12
-.B button1
-program spawned when button 1 is clicked on the root window
-.TP 12
-.B button2
-program spawned when button 2 is clicked on the root window
-.TP 12
-.B focus
-focus mode, one of "enter" for enter-to-focus (or sloppy focus), or
-"click" for click-to-focus
-.SH "SEE ALSO"
-.PP
-X(7)
-.SH AUTHORS
-Elliott Hughes <ehughes@bluearc.com>,
-James Carter <james@jfc.org.uk>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
-/* These are Motif definitions from Xm/MwmUtil.h, but Motif isn't available
- everywhere. */
-#define MWM_HINTS_FUNCTIONS (1L << 0)
-#define MWM_HINTS_DECORATIONS (1L << 1)
-#define MWM_HINTS_INPUT_MODE (1L << 2)
-#define MWM_HINTS_STATUS (1L << 3)
-#define MWM_DECOR_ALL (1L << 0)
-#define MWM_DECOR_BORDER (1L << 1)
-#define MWM_DECOR_RESIZEH (1L << 2)
-#define MWM_DECOR_TITLE (1L << 3)
-#define MWM_DECOR_MENU (1L << 4)
-#define MWM_DECOR_MINIMIZE (1L << 5)
-#define MWM_DECOR_MAXIMIZE (1L << 6)
-
#include "lwm.h"
static int getProperty(Window, Atom, Atom, long, unsigned char **);
void
manage(Client * c, int mapped)
{
- int state;
- XWMHints * hints;
- XWindowAttributes current_attr;
- XSetWindowAttributes attr;
-
- /* For WM_PROTOCOLS handling. */
- Atom * protocols;
- int n;
- int p;
-
- /* Where auto-placement is going to put the next window. */
- static int auto_x = 100;
- static int auto_y = 100;
-
- /* get the EWMH window type, as this might overrule some hints */
- c->wtype = ewmh_get_window_type(c->window);
- /* get in the initial EWMH state */
- ewmh_get_state(c);
- /* set EWMH allowable actions, now we intend to manage this window */
- ewmh_set_allowed(c);
- /* is this window to have a frame? */
- if (c->wtype == WTypeNone) {
- /* this breaks the ewmh spec (section 5.6) because in the
- * absence of a _NET_WM_WINDOW_TYPE, _WM_WINDOW_TYPE_NORMAL
- * must be taken. bummer.
- */
- c->framed = motifWouldDecorate(c);
- } else {
- c->framed = ewmh_hasframe(c);
- }
- if (isShaped(c->window)) c->framed = False;
-
- /* get the EWMH strut - if there is one */
- ewmh_get_strut(c);
-
- /*
- * Get the hints, window name, and normal hints (see ICCCM
- * section 4.1.2.3).
- */
- hints = XGetWMHints(dpy, c->window);
-
- getWindowName(c);
- getNormalHints(c);
-
- /*
- * Get the colourmaps associated with this window. Get the window
- * attribute colourmap first, then look to see if the
- * WM_COLORMAP_WINDOWS property has been used to specify
- * windows needing colourmaps that differ from the top-level
- * colourmap. (See ICCCM section 4.1.8.)
- */
- XGetWindowAttributes(dpy, c->window, ¤t_attr);
- c->cmap = current_attr.colormap;
-
- getColourmaps(c);
-
- /*
- * Scan the list of atoms on WM_PROTOCOLS to see which of the
- * protocols that we understand the client is prepared to
- * participate in. (See ICCCM section 4.1.2.7.)
- */
- if (XGetWMProtocols(dpy, c->window, &protocols, &n) != 0) {
- for (p = 0; p < n; p++) {
- if (protocols[p] == wm_delete) {
- c->proto |= Pdelete;
- } else if (protocols[p] == wm_take_focus) {
- c->proto |= Ptakefocus;
- }
- }
-
- XFree(protocols);
- }
-
- /* Get the WM_TRANSIENT_FOR property (see ICCCM section 4.1.2.6). */
- getTransientFor(c);
-
- /* Work out details for the Client structure from the hints. */
- if (hints && (hints->flags & InputHint))
- c->accepts_focus = hints->input;
- if (c->proto | Ptakefocus)
- /* WM_TAKE_FOCUS overrides normal hints */
- c->accepts_focus = True;
-
- if (!getWindowState(c->window, &state))
- state = hints ? hints->initial_state : NormalState;
-
- /*
- * Sort out the window's position.
- */
- {
- Window root_window;
- int x, y;
- unsigned int w, h;
- unsigned int border_width, depth;
-
- XGetGeometry(dpy, c->window, &root_window, &x, &y, &w, &h,
- &border_width, &depth);
-
- /*
- * Do the size first.
- *
- * "The size specifiers refer to the width and height of the
- * client excluding borders" -- ICCCM 4.1.2.3.
- */
- c->size.width = w;
- c->size.height = h;
- if (c->framed == True) {
- c->size.width += 2 * border;
- c->size.height += 2 * border;
- }
-
- /*
- * THIS IS A HACK!
- *
- * OpenGL programs have a habit of appearing smaller than their
- * minimum sizes, which they don't like.
- */
- if (c->size.width < c->size.min_width)
- c->size.width = c->size.min_width;
- if (c->size.height < c->size.min_height)
- c->size.height = c->size.min_height;
-
- /* Do the position next. */
-
- /*
- * If we have a user-specified position for a top-level window,
- * or a program-specified position for a dialogue box, we'll
- * take it. We'll also just take it during initialisation,
- * since the previous manage probably placed its windows
- * sensibly.
- */
- if (c->trans != None && c->size.flags & PPosition) {
- /* It's a "dialogue box". Trust it. */
- c->size.x = x;
- c->size.y = y;
- } else if ((c->size.flags & USPosition) ||
- c->framed == False || mode == wm_initialising ) {
- /* Use the specified window position. */
- c->size.x = x;
- c->size.y = y;
-
- /*
- * We need to be careful of the right-hand edge and
- * bottom. We can use the window gravity (if specified)
- * to handle this. (See section 4.1.2.3 of the ICCCM.)
- */
- applyGravity(c);
- } else {
- /* No position was specified: use the auto-placement
- * heuristics. */
-
- /* firstly, make sure auto_x and auto_y are outside
- * strut */
- if (auto_x < c->screen->strut.left)
- auto_x = c->screen->strut.left;
- if (auto_y < c->screen->strut.top)
- auto_y = c->screen->strut.top;
-
- if ((auto_x + c->size.width) >
- (c->screen->display_width -
- c->screen->strut.right) &&
- (c->size.width <=
- (c->screen->display_width -
- c->screen->strut.left -
- c->screen->strut.right))) {
- /*
- * If the window wouldn't fit using normal
- * auto-placement but is small enough to fit
- * horizontally, then centre the window
- * horizontally.
- */
- c->size.x = (c->screen->display_width
- - c->size.width) / 2;
- auto_x = c->screen->strut.left + 20;
- } else {
- c->size.x = auto_x;
- auto_x += 10;
- if (auto_x > (c->screen->display_width / 2))
- auto_x = c->screen->strut.left + 20;
- }
-
- if (((auto_y + c->size.height) >
- (c->screen->display_height -
- c->screen->strut.bottom)) &&
- (c->size.height <=
- (c->screen->display_height -
- c->screen->strut.top -
- c->screen->strut.bottom))) {
- /*
- * If the window wouldn't fit using normal
- * auto-placement but is small enough to fit
- * vertically, then centre the window
- * vertically.
- */
- c->size.y = (c->screen->display_height
- - c->size.height) / 2;
- auto_y = c->screen->strut.top + 20;
- } else {
- c->size.y = auto_y;
- auto_y += 10;
- if (auto_y > (c->screen->display_height / 2))
- auto_y = c->screen->strut.top + 20;
- }
- }
- }
-
- if (hints)
- XFree(hints);
-
- /*
- * Do all the reparenting and stuff.
- */
-
- if (c->framed == True) {
- c->parent = XCreateSimpleWindow(dpy, c->screen->root,
- c->size.x, c->size.y - titleHeight(),
- c->size.width, c->size.height + titleHeight(),
- 1, c->screen->black, c->screen->white);
-
- attr.event_mask = ExposureMask | EnterWindowMask | ButtonMask |
- SubstructureRedirectMask | SubstructureNotifyMask |
- PointerMotionMask;
- XChangeWindowAttributes(dpy, c->parent, CWEventMask, &attr);
-
- XResizeWindow(dpy, c->window, c->size.width - 2 * border,
- c->size.height - 2 * border);
- }
-
- /*
- * Stupid X11 doesn't let us change border width in the above
- * call. It's a window attribute, but it's somehow second-class.
- *
- * As pointed out by Adrian Colley, we can't change the window
- * border width at all for InputOnly windows.
- */
- if (current_attr.class != InputOnly)
- XSetWindowBorderWidth(dpy, c->window, 0);
-
- attr.event_mask = ColormapChangeMask | EnterWindowMask |
- PropertyChangeMask | FocusChangeMask;
- attr.win_gravity = StaticGravity;
- attr.do_not_propagate_mask = ButtonMask;
- XChangeWindowAttributes(dpy, c->window,
- CWEventMask | CWWinGravity | CWDontPropagate, &attr);
-
- if (c->framed == True) {
- XReparentWindow(dpy, c->window, c->parent,
- border, border + titleHeight());
- } else {
- XReparentWindow(dpy, c->window, c->parent,
- c->size.x, c->size.y);
- }
-
- setShape(c);
-
- XAddToSaveSet(dpy, c->window);
- if (state == IconicState) {
- } else {
- /* Map the new window in the relevant state. */
- c->hidden = False;
- XMapWindow(dpy, c->parent);
- XMapWindow(dpy, c->window);
- setactive(c, (focus_mode == focus_click) ? 1 : 0, 0L);
- Client_SetState(c, NormalState);
- }
-
- if (c->wstate.fullscreen == True) Client_EnterFullScreen(c);
-
- if (current != c)
- cmapfocus(current);
+ int state;
+ XWMHints * hints;
+ XWindowAttributes current_attr;
+ XSetWindowAttributes attr;
+
+ /* For WM_PROTOCOLS handling. */
+ Atom * protocols;
+ int n;
+ int p;
+
+ /* Where auto-placement is going to put the next window. */
+ static int auto_x = 100;
+ static int auto_y = 100;
+
+ /* get the EWMH window type, as this might overrule some hints */
+ c->wtype = ewmh_get_window_type(c->window);
+ /* set EWMH allowable actions, now we intend to manage this window */
+ ewmh_set_allowed(c);
+ /* is this window to have a frame? */
+ c->framed = ewmh_hasframe(c);
+
+ /*
+ * Get the hints, window name, and normal hints (see ICCCM
+ * section 4.1.2.3).
+ */
+ hints = XGetWMHints(dpy, c->window);
+
+ getWindowName(c);
+ getNormalHints(c);
+
+ /*
+ * Get the colourmaps associated with this window. Get the window
+ * attribute colourmap first, then look to see if the
+ * WM_COLORMAP_WINDOWS property has been used to specify
+ * windows needing colourmaps that differ from the top-level
+ * colourmap. (See ICCCM section 4.1.8.)
+ */
+ XGetWindowAttributes(dpy, c->window, ¤t_attr);
+
+ /*
+ * Scan the list of atoms on WM_PROTOCOLS to see which of the
+ * protocols that we understand the client is prepared to
+ * participate in. (See ICCCM section 4.1.2.7.)
+ */
+ if (XGetWMProtocols(dpy, c->window, &protocols, &n) != 0) {
+ for (p = 0; p < n; p++) {
+ if (protocols[p] == wm_delete) {
+ c->flags |= F_EWMH_DELETE;
+ } else if (protocols[p] == wm_take_focus) {
+ c->flags |= F_EWMH_TAKE_FOCUS;
+ }
+ }
+ XFree(protocols);
+ }
+
+ /* Get the WM_TRANSIENT_FOR property (see ICCCM section 4.1.2.6). */
+ getTransientFor(c);
+
+ /* Work out details for the Client structure from the hints. */
+ if (hints && (hints->flags & InputHint))
+ c->flags |= F_ACCEPT_FOCUS;
+ if (Client_HasFlags(c, F_EWMH_TAKE_FOCUS))
+ c->flags |= F_ACCEPT_FOCUS;
+
+ if (!getWindowState(c->window, &state))
+ state = hints ? hints->initial_state : NormalState;
+
+ /*
+ * Sort out the window's position.
+ */
+ {
+ Window root_window;
+ int x, y;
+ unsigned int w, h;
+ unsigned int border_width, depth;
+
+ XGetGeometry(dpy, c->window, &root_window, &x, &y, &w, &h,
+ &border_width, &depth);
+
+ /*
+ * Do the size first.
+ *
+ * "The size specifiers refer to the width and height of the
+ * client excluding borders" -- ICCCM 4.1.2.3.
+ */
+ c->size.width = w;
+ c->size.height = h;
+ if (c->framed == True) {
+ c->size.width += 2 * border;
+ c->size.height += 2 * border;
+ }
+
+ /*
+ * THIS IS A HACK!
+ *
+ * OpenGL programs have a habit of appearing smaller than their
+ * minimum sizes, which they don't like.
+ */
+ if (c->size.width < c->size.min_width)
+ c->size.width = c->size.min_width;
+ if (c->size.height < c->size.min_height)
+ c->size.height = c->size.min_height;
+
+ /* Do the position next. */
+
+ /*
+ * If we have a user-specified position for a top-level window,
+ * or a program-specified position for a dialogue box, we'll
+ * take it. We'll also just take it during initialisation,
+ * since the previous manage probably placed its windows
+ * sensibly.
+ */
+ if (c->trans != None && c->size.flags & PPosition) {
+ /* It's a "dialogue box". Trust it. */
+ c->size.x = x;
+ c->size.y = y;
+ } else if ((c->size.flags & USPosition) ||
+ c->framed == False || mode == wm_initialising ) {
+ /* Use the specified window position. */
+ c->size.x = x;
+ c->size.y = y;
+
+ /*
+ * We need to be careful of the right-hand edge and
+ * bottom. We can use the window gravity (if specified)
+ * to handle this. (See section 4.1.2.3 of the ICCCM.)
+ */
+ applyGravity(c);
+ }
+ }
+
+ if (hints)
+ XFree(hints);
+
+ /*
+ * Do all the reparenting and stuff.
+ */
+
+ if (c->framed == True) {
+ c->parent = XCreateSimpleWindow(dpy, c->screen->root,
+ c->size.x, c->size.y - titleHeight(),
+ c->size.width, c->size.height + titleHeight(),
+ 1, c->screen->black, c->screen->white);
+
+ attr.event_mask = ExposureMask | EnterWindowMask | ButtonMask |
+ SubstructureRedirectMask | SubstructureNotifyMask |
+ PointerMotionMask;
+ XChangeWindowAttributes(dpy, c->parent, CWEventMask, &attr);
+
+ XResizeWindow(dpy, c->window, c->size.width - 2 * border,
+ c->size.height - 2 * border);
+ }
+
+ /*
+ * Stupid X11 doesn't let us change border width in the above
+ * call. It's a window attribute, but it's somehow second-class.
+ *
+ * As pointed out by Adrian Colley, we can't change the window
+ * border width at all for InputOnly windows.
+ */
+ if (current_attr.class != InputOnly)
+ XSetWindowBorderWidth(dpy, c->window, 0);
+
+ attr.event_mask = EnterWindowMask |
+ PropertyChangeMask | FocusChangeMask;
+ attr.win_gravity = StaticGravity;
+ attr.do_not_propagate_mask = ButtonMask;
+ XChangeWindowAttributes(dpy, c->window,
+ CWEventMask | CWWinGravity | CWDontPropagate, &attr);
+
+ if (c->framed == True) {
+ XReparentWindow(dpy, c->window, c->parent,
+ border, border + titleHeight());
+ } else {
+ XReparentWindow(dpy, c->window, c->parent,
+ c->size.x, c->size.y);
+ }
+
+ XAddToSaveSet(dpy, c->window);
+ /* Map the new window in the relevant state. */
+ XMapWindow(dpy, c->parent);
+ XMapWindow(dpy, c->window);
+ Client_SetActive(c, 0, 0L);
+ Client_SetState(c, NormalState);
}
static void
applyGravity(Client *c) {
- if (c->framed == False) return; /* only required for framed windows*/
- if (c->size.flags & PWinGravity) {
- switch (c->size.win_gravity) {
- case NorthEastGravity:
- c->size.x -= 2 * border;
- break;
- case SouthWestGravity:
- c->size.y -= 2 * border;
- break;
- case SouthEastGravity:
- c->size.x -= 2 * border;
- c->size.y -= 2 * border;
- break;
- }
- }
+ if (c->framed == False) return; /* only required for framed windows*/
+ if (c->size.flags & PWinGravity) {
+ switch (c->size.win_gravity) {
+ case NorthEastGravity:
+ c->size.x -= 2 * border;
+ break;
+ case SouthWestGravity:
+ c->size.y -= 2 * border;
+ break;
+ case SouthEastGravity:
+ c->size.x -= 2 * border;
+ c->size.y -= 2 * border;
+ break;
+ }
+ }
}
void
getTransientFor(Client *c) {
- Window trans = None;
+ Window trans = None;
- XGetTransientForHint(dpy, c->window, &trans);
- c->trans = trans;
+ XGetTransientForHint(dpy, c->window, &trans);
+ c->trans = trans;
}
void
withdraw(Client *c) {
- if (c->parent != c->screen->root) {
- XUnmapWindow(dpy, c->parent);
- XReparentWindow(dpy, c->parent, c->screen->root, c->size.x, c->size.y);
- }
-
- XRemoveFromSaveSet(dpy, c->window);
- Client_SetState(c, WithdrawnState);
-
- /*
- * Flush and ignore any errors. X11 sends us an UnmapNotify before it
- * sends us a DestroyNotify. That means we can get here without knowing
- * whether the relevant window still exists.
- */
- ignore_badwindow = 1;
- XSync(dpy, False);
- ignore_badwindow = 0;
-}
-
-static void
-installColourmap(Colormap cmap) {
- if (cmap == None)
- cmap = DefaultColormap(dpy, DefaultScreen(dpy));
- XInstallColormap(dpy, cmap);
-}
-
-void
-cmapfocus(Client * c) {
- int i;
- int found;
- Client *cc;
-
- if (c == 0)
- installColourmap(None);
- else if (c->ncmapwins != 0) {
- found = 0;
- for (i = c->ncmapwins - 1; i >= 0; i--) {
- installColourmap(c->wmcmaps[i]);
- if (c->cmapwins[i] == c->window)
- found++;
- }
- if (!found)
- installColourmap(c->cmap);
- } else if (c->trans != None && (cc = Client_Get(c->trans)) != 0 &&
- cc->ncmapwins != 0)
- cmapfocus(cc);
- else
- installColourmap(c->cmap);
-}
-
-void
-getColourmaps(Client *c) {
- int n;
- int i;
- Window *cw;
- XWindowAttributes attr;
-
- if (c == 0)
- return;
-
- n = getProperty(c->window, wm_colormaps, XA_WINDOW, 100L, (unsigned char **) &cw);
- if (c->ncmapwins != 0) {
- XFree(c->cmapwins);
- free(c->wmcmaps);
- }
- if (n <= 0) {
- c->ncmapwins = 0;
- return;
- }
- c->ncmapwins = n;
- c->cmapwins = cw;
-
- c->wmcmaps = (Colormap *) malloc(n * sizeof(Colormap));
- for (i = 0; i < n; i++) {
- if (cw[i] == c->window) {
- c->wmcmaps[i] = c->cmap;
- } else {
- XSelectInput(dpy, cw[i], ColormapChangeMask);
- XGetWindowAttributes(dpy, cw[i], &attr);
- c->wmcmaps[i] = attr.colormap;
- }
- }
-}
-
-/*ARGSUSED*/
-void
-Terminate(int signal) {
- /* Set all clients free. */
- Client_FreeAll();
-
- /* Give up the input focus and the colourmap. */
- XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
- installColourmap(None);
-
- XCloseDisplay(dpy);
- exit(signal ? EXIT_FAILURE : EXIT_SUCCESS);
+ if (c->parent != c->screen->root) {
+ XUnmapWindow(dpy, c->parent);
+ XReparentWindow(dpy, c->parent, c->screen->root, c->size.x, c->size.y);
+ }
+
+ XRemoveFromSaveSet(dpy, c->window);
+ Client_SetState(c, WithdrawnState);
+
+ /*
+ * Flush and ignore any errors. X11 sends us an UnmapNotify before it
+ * sends us a DestroyNotify. That means we can get here without knowing
+ * whether the relevant window still exists.
+ */
+ ignore_badwindow = 1;
+ XSync(dpy, False);
+ ignore_badwindow = 0;
}
-
static int
getProperty(Window w, Atom a, Atom type, long len, unsigned char **p) {
- Atom real_type;
- int format;
- unsigned long n;
- unsigned long extra;
- int status;
-
- /*
- * len is in 32-bit multiples.
- */
- status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
- if (status != Success || *p == 0)
- return -1;
- if (n == 0)
- XFree(*p);
- /*
- * could check real_type, format, extra here...
- */
- return n;
+ Atom real_type;
+ int format;
+ unsigned long n;
+ unsigned long extra;
+ int status;
+
+ /*
+ * len is in 32-bit multiples.
+ */
+ status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
+ if (status != Success || *p == 0)
+ return -1;
+ if (n == 0)
+ XFree(*p);
+ /*
+ * could check real_type, format, extra here...
+ */
+ return n;
}
void
getWindowName(Client *c) {
- char * name;
- Atom actual_type;
- int format;
- unsigned long n;
- unsigned long extra;
- int was_nameless;
-
- if (c == 0)
- return;
-
- was_nameless = (c->name == 0);
-
- if (ewmh_get_window_name(c) == False &&
- XGetWindowProperty(dpy, c->window, _mozilla_url, 0L, 100L, False, AnyPropertyType, &actual_type, &format, &n, &extra, (unsigned char **) &name) == Success && name && *name != '\0' && n != 0) {
- Client_Name(c, name, False);
- XFree(name);
- } else if (XGetWindowProperty(dpy, c->window, XA_WM_NAME, 0L, 100L, False, AnyPropertyType, &actual_type, &format, &n, &extra, (unsigned char **) &name) == Success && name && *name != '\0' && n != 0) {
- /* That rather unpleasant condition is necessary because xwsh uses
- * COMPOUND_TEXT rather than STRING for its WM_NAME property,
- * and anonymous xwsh windows are annoying.
- */
- if (actual_type == compound_text && memcmp(name, "\x1b\x28\x42", 3) == 0) {
- Client_Name(c, name + 3, False);
- } else {
- Client_Name(c, name, False);
- }
- XFree(name);
- }
-
- if (!was_nameless)
- Client_DrawBorder(c, c == current);
+ char * name;
+ Atom actual_type;
+ int format;
+ unsigned long n;
+ unsigned long extra;
+ int was_nameless;
+
+ if (c == 0)
+ return;
+
+ was_nameless = (c->name == 0);
+
+ if (ewmh_get_window_name(c) == False) {
+ if (XGetWindowProperty(dpy, c->window, XA_WM_NAME, 0L, 100L, False, AnyPropertyType, &actual_type, &format, &n, &extra, (unsigned char **) &name) == Success && name && *name != '\0' && n != 0) {
+ /* That rather unpleasant condition is necessary because xwsh uses
+ * COMPOUND_TEXT rather than STRING for its WM_NAME property,
+ * and anonymous xwsh windows are annoying.
+ */
+ if (actual_type == compound_text && memcmp(name, "\x1b\x28\x42", 3) == 0) {
+ Client_Name(c, name + 3);
+ } else {
+ Client_Name(c, name);
+ }
+ XFree(name);
+ }
+ }
+
+ if (!was_nameless)
+ Client_DrawFrame(c, c == current);
}
void
getNormalHints(Client *c) {
- int x, y, w, h;
- long msize;
-
- /* We have to be a little careful here. The ICCCM says that the x, y
- * and width, height components aren't used. So we use them. That means
- * that we need to save and restore them whenever we fill the size
- * struct. */
- x = c->size.x;
- y = c->size.y;
- w = c->size.width;
- h = c->size.height;
-
- /* Do the get. */
- if (XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0)
- c->size.flags = 0;
-
- if (c->framed == True) {
- /*
- * Correct the minimum allowable size of this client to take
- * account of the window border.
- */
- if (c->size.flags & PMinSize) {
- c->size.min_width += 2 * border;
- c->size.min_height += 2 * border;
- } else {
- c->size.flags |= PMinSize;
- c->size.min_width = 2 * (2 * border);
- if (c->accepts_focus)
- c->size.min_height = 2 * (2*border);
- else
- c->size.min_height = 2 * (2*border);
- }
-
- /*
- * Correct the maximum allowable size of this client to take
- * account of the window border.
- */
- if (c->size.flags & PMaxSize) {
- c->size.max_width += 2 * border;
- c->size.max_height += 2 * border;
- }
- }
-
- /*
- * Ensure that the base width & height and the width & height increments
- * are set correctly so that we don't have to do this in MakeSane.
- */
- if (!(c->size.flags & PBaseSize))
- c->size.base_width = c->size.base_height = 0;
-
- if (!(c->size.flags & PResizeInc))
- c->size.width_inc = c->size.height_inc = 1;
-
- /*
- * If the client gives identical minimum and maximum sizes, we don't
- * want the user to resize in that direction.
- */
- if (c->size.min_width == c->size.max_width)
- c->size.width_inc = 0;
-
- if (c->size.min_height == c->size.max_height)
- c->size.height_inc = 0;
-
- /* Restore the window-manager bits. */
- c->size.x = x;
- c->size.y = y;
- c->size.width = w;
- c->size.height = h;
+ int x, y, w, h;
+ long msize;
+
+ /* We have to be a little careful here. The ICCCM says that the x, y
+ * and width, height components aren't used. So we use them. That means
+ * that we need to save and restore them whenever we fill the size
+ * struct. */
+ x = c->size.x;
+ y = c->size.y;
+ w = c->size.width;
+ h = c->size.height;
+
+ /* Do the get. */
+ if (XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0)
+ c->size.flags = 0;
+
+ if (c->framed == True) {
+ /*
+ * Correct the minimum allowable size of this client to take
+ * account of the window border.
+ */
+ if (c->size.flags & PMinSize) {
+ c->size.min_width += 2 * border;
+ c->size.min_height += 2 * border;
+ } else {
+ c->size.flags |= PMinSize;
+ c->size.min_width = 2 * (2 * border);
+ c->size.min_height = 2 * (2 * border);
+ }
+
+ /*
+ * Correct the maximum allowable size of this client to take
+ * account of the window border.
+ */
+ if (c->size.flags & PMaxSize) {
+ c->size.max_width += 2 * border;
+ c->size.max_height += 2 * border;
+ }
+ }
+
+ /*
+ * Ensure that the base width & height and the width & height increments
+ * are set correctly so that we don't have to do this in MakeSane.
+ */
+ if (!(c->size.flags & PBaseSize))
+ c->size.base_width = c->size.base_height = 0;
+
+ if (!(c->size.flags & PResizeInc))
+ c->size.width_inc = c->size.height_inc = 1;
+
+ /*
+ * If the client gives identical minimum and maximum sizes, we don't
+ * want the user to resize in that direction.
+ */
+ if (c->size.min_width == c->size.max_width)
+ c->size.width_inc = 0;
+
+ if (c->size.min_height == c->size.max_height)
+ c->size.height_inc = 0;
+
+ /* Restore the window-manager bits. */
+ c->size.x = x;
+ c->size.y = y;
+ c->size.width = w;
+ c->size.height = h;
}
static int
getWindowState(Window w, int *state) {
- long *p = 0;
+ long *p = 0;
- if (getProperty(w, wm_state, wm_state, 2L, (unsigned char **) &p) <= 0)
- return 0;
+ if (getProperty(w, wm_state, wm_state, 2L, (unsigned char **) &p) <= 0)
+ return 0;
- *state = (int) *p;
- XFree(p);
- return 1;
+ *state = (int) *p;
+ XFree(p);
+ return 1;
}
-
-extern Bool
-motifWouldDecorate(Client *c) {
- unsigned long *p = 0;
- Bool ret = True; /* if all else fails - decorate */
-
- if (getProperty(c->window, motif_wm_hints, motif_wm_hints,
- 5L, (unsigned char **) &p) <= 0)
- return ret;
-
- if ((p[0] & MWM_HINTS_DECORATIONS) &&
- !(p[2] & (MWM_DECOR_BORDER | MWM_DECOR_ALL)))
- ret = False;
-
- XFree(p);
- return ret;
-}
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <unistd.h>
#include <X11/X.h>
+#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#ifdef SHAPE
-#include <X11/extensions/shape.h>
-#endif
#include "lwm.h"
+#include "ewmh.h"
-/*ARGSUSED*/
-extern void
-setShape(Client *c) {
-}
+void
+getMousePosition(int * x, int * y) {
+ Window root, child;
+ int t1, t2;
+ unsigned int b;
-/*ARGSUSED*/
-extern int
-shapeEvent(XEvent *ev) {
- return 0;
+ /* It doesn't matter which root window we give this call. */
+ XQueryPointer(dpy, screens[0].root, &root, &child, x, y, &t1, &t2, &b);
+ current_screen = getScreenFromRoot(root);
}
-/*ARGSUSED*/
-extern int
-isShaped(Window w) {
- return 0;
-}
-
-extern int
-serverSupportsShapes(void) {
- return 0;
-}
+++ /dev/null
-# Sample Makefile for lwm.
-
-# You ought to be using the Imakefile (xmkmf;make) but
-# if Imake isn't set up properly on your system, this might
-# help you out. I used to use it on an SGI.
-
-# Uncomment these lines to use gcc.
-#CC = gcc
-#CFLAGS = -ansi -pedantic -Wall -DSHAPE
-
-# Uncomment these lines to use SGI cc.
-#CC = cc
-#CFLAGS = -fullwarn -g -DSHAPE
-
-# Uncomment these for Solaris Sun Studio, choose your architecture.
-#CC = cc
-#CFLAGS = -Xa -fast -xarch=v8a
-#CFLAGS = -Xa -fast -xarch=386
-
-DEFINES =
-
-# Bennett Todd (bet@lehman.com) says this helped him compile on
-# Solaris 2.5.1, avoiding a problem with <sys/signal.h>.
-#DEFINES = -D_POSIX_C_SOURCE=2
-
-# Add any strange libraries your system needs here.
-LDFLAGS = -lXext -lX11 -lICE -lSM
-
-# -----------------------------------------------------------------------------
-
-OFILES = client.o cursor.o disp.o error.o ewmh.o lwm.o manage.o mouse.o \
- resource.o session.o shape.o
-HFILES = lwm.h ewmh.h
-
-# -----------------------------------------------------------------------------
-
-all: lwm
-
-lwm: $(OFILES)
- $(CC) $(CFLAGS) $(DEFINES) -o lwm $(OFILES) $(LDFLAGS)
-
-install: lwm
- cp lwm /usr/local/bin
-
-$(OFILES): $(HFILES)
-
-clean:
- rm -f lwm *.o core