WIP version 3 of edges thinger
authorMikael Magnusson <mikachu@comhem.se>
Wed, 5 Sep 2007 01:54:24 +0000 (03:54 +0200)
committerMikael Magnusson <mikachu@gmail.com>
Sat, 11 Oct 2014 00:17:20 +0000 (02:17 +0200)
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.

Makefile.am
openbox/edges.c [new file with mode: 0644]
openbox/edges.h [new file with mode: 0644]
openbox/event.c
openbox/frame.c
openbox/frame.h
openbox/openbox.c
openbox/window.h

index b438904..f1dc5d8 100644 (file)
@@ -251,6 +251,8 @@ openbox_openbox_SOURCES = \
        openbox/debug.h \
        openbox/dock.c \
        openbox/dock.h \
+       openbox/edges.c \
+       openbox/edges.h \
        openbox/event.c \
        openbox/event.h \
        openbox/focus.c \
diff --git a/openbox/edges.c b/openbox/edges.c
new file mode 100644 (file)
index 0000000..744cd97
--- /dev/null
@@ -0,0 +1,106 @@
+#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]);
+    }
+}
diff --git a/openbox/edges.h b/openbox/edges.h
new file mode 100644 (file)
index 0000000..4648404
--- /dev/null
@@ -0,0 +1,31 @@
+#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
index 243f207..59fc21c 100644 (file)
@@ -30,6 +30,7 @@
 #include "grab.h"
 #include "menu.h"
 #include "prompt.h"
+#include "edges.h"
 #include "menuframe.h"
 #include "keyboard.h"
 #include "mouse.h"
@@ -480,9 +481,6 @@ static void event_process(const XEvent *ec, gpointer data)
         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;
@@ -711,7 +709,7 @@ static void event_process(const XEvent *ec, gpointer data)
             /* ...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);
index 3dbcf12..2e36dd6 100644 (file)
@@ -28,6 +28,7 @@
 #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"
@@ -1386,6 +1387,22 @@ ObFrameContext frame_context_from_string(const gchar *name)
         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;
 }
@@ -1397,12 +1414,14 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y)
 
     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;
index 915c08d..275faa7 100644 (file)
@@ -54,6 +54,14 @@ typedef enum {
       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;
 
index cba0499..f901435 100644 (file)
@@ -21,6 +21,7 @@
 #include "openbox.h"
 #include "session.h"
 #include "dock.h"
+#include "edges.h"
 #include "event.h"
 #include "menu.h"
 #include "client.h"
@@ -327,6 +328,7 @@ gint main(gint argc, gchar **argv)
             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
@@ -392,6 +394,7 @@ gint main(gint argc, gchar **argv)
                 window_unmanage_all();
 
             prompt_shutdown(reconfigure);
+            edges_shutdown(reconfigure);
             menu_shutdown(reconfigure);
             menu_frame_shutdown(reconfigure);
             mouse_shutdown(reconfigure);
index 24a7d07..c1402bc 100644 (file)
@@ -32,7 +32,8 @@ typedef enum {
     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
@@ -51,6 +52,8 @@ struct _ObWindow {
     (((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;
@@ -63,12 +66,14 @@ struct _ObPrompt;
 #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);