This is lets you bind actions to clicking on screen edges/corners.
Eventually it should also let you bind hovering or entering/leaving and
whatnot.
openbox/debug.h \
openbox/dock.c \
openbox/dock.h \
+ openbox/edges.c \
+ openbox/edges.h \
openbox/event.c \
openbox/event.h \
openbox/focus.c \
--- /dev/null
+#include "openbox.h"
+#include "config.h"
+#include "screen.h"
+#include "edges.h"
+#include "frame.h"
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+#warning Do something clever with xinerama
+ObEdge *edge[OB_NUM_EDGES];
+#warning put in config.c and parse configs of course
+gboolean config_edge_enabled[OB_NUM_EDGES] = {1, 1, 1, 1, 1, 1, 1, 1};
+
+#ifdef DEBUG
+#define EDGE_WIDTH 10
+#define CORNER_SIZE 20
+#else
+#define EDGE_WIDTH 1
+#define CORNER_SIZE 2
+#endif
+static void get_position(ObEdgeLocation edge, Rect screen, Rect *rect)
+{
+ switch (edge) {
+ case OB_EDGE_TOP:
+ RECT_SET(*rect, CORNER_SIZE, 0,
+ screen.width - 2 * CORNER_SIZE, EDGE_WIDTH);
+ break;
+ case OB_EDGE_TOPRIGHT:
+ RECT_SET(*rect, screen.width - CORNER_SIZE, 0,
+ CORNER_SIZE, CORNER_SIZE);
+ break;
+ case OB_EDGE_RIGHT:
+ RECT_SET(*rect, screen.width - EDGE_WIDTH, CORNER_SIZE,
+ EDGE_WIDTH, screen.height - 2 * CORNER_SIZE);
+ break;
+ case OB_EDGE_BOTTOMRIGHT:
+ RECT_SET(*rect, screen.width - CORNER_SIZE,
+ screen.height - CORNER_SIZE,
+ CORNER_SIZE, CORNER_SIZE);
+ break;
+ case OB_EDGE_BOTTOM:
+ RECT_SET(*rect, CORNER_SIZE, screen.height - EDGE_WIDTH,
+ screen.width - 2 * CORNER_SIZE, EDGE_WIDTH);
+ break;
+ case OB_EDGE_BOTTOMLEFT:
+ RECT_SET(*rect, 0, screen.height - CORNER_SIZE,
+ CORNER_SIZE, CORNER_SIZE);
+ break;
+ case OB_EDGE_LEFT:
+ RECT_SET(*rect, 0, CORNER_SIZE,
+ EDGE_WIDTH, screen.height - 2 * CORNER_SIZE);
+ break;
+ case OB_EDGE_TOPLEFT:
+ RECT_SET(*rect, 0, 0, CORNER_SIZE, CORNER_SIZE);
+ break;
+ }
+}
+
+void edges_startup(gboolean reconfigure)
+{
+ ObEdgeLocation i;
+ Rect r;
+ XSetWindowAttributes xswa;
+ const Rect *screen = screen_physical_area_all_monitors();
+
+ xswa.override_redirect = True;
+
+ for (i=0; i < OB_NUM_EDGES; i++) {
+ if (!config_edge_enabled[i])
+ continue;
+
+ edge[i] = g_new(ObEdge, 1);
+ edge[i]->obwin.type = OB_WINDOW_CLASS_EDGE;
+ edge[i]->location = i;
+
+ get_position(i, *screen, &r);
+ edge[i]->win = XCreateWindow(obt_display, obt_root(ob_screen),
+ r.x, r.y, r.width, r.height, 0, 0, InputOnly,
+ CopyFromParent, CWOverrideRedirect, &xswa);
+ XSelectInput(obt_display, edge[i]->win, ButtonPressMask | ButtonReleaseMask
+ | EnterWindowMask | LeaveWindowMask);
+ XMapWindow(obt_display, edge[i]->win);
+
+ stacking_add(EDGE_AS_WINDOW(edge[i]));
+ window_add(&edge[i]->win, EDGE_AS_WINDOW(edge[i]));
+
+#ifdef DEBUG
+ ob_debug("mapped edge window %i at %03i %03i %02i %02i", i, r.x, r.y, r.width, r.height);
+#endif
+ }
+
+ XFlush(obt_display);
+}
+
+void edges_shutdown(gboolean reconfigure)
+{
+ gint i;
+
+ for (i=0; i < OB_NUM_EDGES; i++) {
+ window_remove(edge[i]->win);
+ stacking_remove(EDGE_AS_WINDOW(edge[i]));
+ XDestroyWindow(obt_display, edge[i]->win);
+ g_free(edge[i]);
+ }
+}
--- /dev/null
+#ifndef __edges_h
+#define __edges_h
+
+#include "window.h"
+
+typedef enum
+{
+ OB_EDGE_TOP,
+ OB_EDGE_TOPRIGHT,
+ OB_EDGE_RIGHT,
+ OB_EDGE_BOTTOMRIGHT,
+ OB_EDGE_BOTTOM,
+ OB_EDGE_BOTTOMLEFT,
+ OB_EDGE_LEFT,
+ OB_EDGE_TOPLEFT,
+ OB_NUM_EDGES
+} ObEdgeLocation;
+
+typedef struct _ObEdge ObEdge;
+
+struct _ObEdge
+{
+ ObWindow obwin;
+ Window win;
+ ObEdgeLocation location;
+};
+
+void edges_startup(gboolean reconfigure);
+void edges_shutdown(gboolean reconfigure);
+
+#endif
#include "grab.h"
#include "menu.h"
#include "prompt.h"
+#include "edges.h"
#include "menuframe.h"
#include "keyboard.h"
#include "mouse.h"
case OB_WINDOW_CLASS_MENUFRAME:
menu = WINDOW_AS_MENUFRAME(obwin);
break;
- case OB_WINDOW_CLASS_INTERNAL:
- /* we don't do anything with events directly on these windows */
- break;
case OB_WINDOW_CLASS_PROMPT:
prompt = WINDOW_AS_PROMPT(obwin);
break;
/* ...or it if it was physically on an openbox
internal window... */
((w = window_find(e->xbutton.subwindow)) &&
- (WINDOW_IS_INTERNAL(w) || WINDOW_IS_DOCK(w))))
+ (WINDOW_IS_INTERNAL(w) || WINDOW_IS_DOCK(w) || WINDOW_IS_EDGE(w))))
/* ...then process the event, otherwise ignore it */
{
used = event_handle_user_input(client, e);
#include "focus_cycle_indicator.h"
#include "moveresize.h"
#include "screen.h"
+#include "edges.h"
#include "obrender/theme.h"
#include "obt/display.h"
#include "obt/xqueue.h"
return OB_FRAME_CONTEXT_MOVE_RESIZE;
else if (!g_ascii_strcasecmp("Dock", name))
return OB_FRAME_CONTEXT_DOCK;
+ else if (!g_ascii_strcasecmp("ScreenTop", name))
+ return OB_FRAME_CONTEXT_EDGE_TOP;
+ else if (!g_ascii_strcasecmp("ScreenTopRight", name))
+ return OB_FRAME_CONTEXT_EDGE_TOPRIGHT;
+ else if (!g_ascii_strcasecmp("ScreenRight", name))
+ return OB_FRAME_CONTEXT_EDGE_RIGHT;
+ else if (!g_ascii_strcasecmp("ScreenBottomRight", name))
+ return OB_FRAME_CONTEXT_EDGE_BOTTOMRIGHT;
+ else if (!g_ascii_strcasecmp("ScreenBottom", name))
+ return OB_FRAME_CONTEXT_EDGE_BOTTOM;
+ else if (!g_ascii_strcasecmp("ScreenBottomLeft", name))
+ return OB_FRAME_CONTEXT_EDGE_BOTTOMLEFT;
+ else if (!g_ascii_strcasecmp("ScreenLeft", name))
+ return OB_FRAME_CONTEXT_EDGE_LEFT;
+ else if (!g_ascii_strcasecmp("ScreenTopLeft", name))
+ return OB_FRAME_CONTEXT_EDGE_TOPLEFT;
return OB_FRAME_CONTEXT_NONE;
}
if (moveresize_in_progress)
return OB_FRAME_CONTEXT_MOVE_RESIZE;
-
if (win == obt_root(ob_screen))
return OB_FRAME_CONTEXT_ROOT;
if ((obwin = window_find(win))) {
if (WINDOW_IS_DOCK(obwin)) {
return OB_FRAME_CONTEXT_DOCK;
+ } else if (WINDOW_IS_EDGE(obwin)) {
+ ObEdge *edge = (ObEdge *)obwin;
+ return OB_FRAME_CONTEXT_EDGE_TOP + edge->location;
}
}
if (client == NULL) return OB_FRAME_CONTEXT_NONE;
a move/resize */
OB_FRAME_CONTEXT_MOVE_RESIZE,
OB_FRAME_CONTEXT_DOCK,
+ OB_FRAME_CONTEXT_EDGE_TOP,
+ OB_FRAME_CONTEXT_EDGE_TOPRIGHT,
+ OB_FRAME_CONTEXT_EDGE_RIGHT,
+ OB_FRAME_CONTEXT_EDGE_BOTTOMRIGHT,
+ OB_FRAME_CONTEXT_EDGE_BOTTOM,
+ OB_FRAME_CONTEXT_EDGE_BOTTOMLEFT,
+ OB_FRAME_CONTEXT_EDGE_LEFT,
+ OB_FRAME_CONTEXT_EDGE_TOPLEFT,
OB_FRAME_NUM_CONTEXTS
} ObFrameContext;
#include "openbox.h"
#include "session.h"
#include "dock.h"
+#include "edges.h"
#include "event.h"
#include "menu.h"
#include "client.h"
mouse_startup(reconfigure);
menu_frame_startup(reconfigure);
menu_startup(reconfigure);
+ edges_startup(reconfigure);
prompt_startup(reconfigure);
/* do this after everything is started so no events will get
window_unmanage_all();
prompt_shutdown(reconfigure);
+ edges_shutdown(reconfigure);
menu_shutdown(reconfigure);
menu_frame_shutdown(reconfigure);
mouse_shutdown(reconfigure);
OB_WINDOW_CLASS_DOCK,
OB_WINDOW_CLASS_CLIENT,
OB_WINDOW_CLASS_INTERNAL,
- OB_WINDOW_CLASS_PROMPT
+ OB_WINDOW_CLASS_PROMPT,
+ OB_WINDOW_CLASS_EDGE
} ObWindowClass;
/* In order to be an ObWindow, you need to make this struct the top of your
(((ObWindow*)win)->type == OB_WINDOW_CLASS_INTERNAL)
#define WINDOW_IS_PROMPT(win) \
(((ObWindow*)win)->type == OB_WINDOW_CLASS_PROMPT)
+#define WINDOW_IS_EDGE(win) \
+ (((ObWindow*)win)->type == OB_WINDOW_CLASS_EDGE)
struct _ObMenu;
struct _ObDock;
#define WINDOW_AS_CLIENT(win) ((struct _ObClient*)win)
#define WINDOW_AS_INTERNAL(win) ((struct _ObInternalWindow*)win)
#define WINDOW_AS_PROMPT(win) ((struct _ObPrompt*)win)
+#define WINDOW_AS_EDGE(win) ((struct _ObEdge*)win)
#define MENUFRAME_AS_WINDOW(menu) ((ObWindow*)menu)
#define DOCK_AS_WINDOW(dock) ((ObWindow*)dock)
#define CLIENT_AS_WINDOW(client) ((ObWindow*)client)
#define INTERNAL_AS_WINDOW(intern) ((ObWindow*)intern)
#define PROMPT_AS_WINDOW(prompt) ((ObWindow*)prompt)
+#define EDGE_AS_WINDOW(edge) ((ObWindow*)edge)
void window_startup (gboolean reconfig);
void window_shutdown(gboolean reconfig);