edges: do something clever with xinerama
[mikachu/openbox.git] / openbox / edges.c
1 #include "openbox.h"
2 #include "config.h"
3 #include "screen.h"
4 #include "edges.h"
5 #include "frame.h"
6
7 #include <X11/Xlib.h>
8 #include <glib.h>
9
10 /* Array of array of monitors of edges: edge[monitor 2][top edge] */
11 ObEdge ***edge;
12 #warning put in config.c and parse configs of course
13 gboolean config_edge_enabled[OB_NUM_EDGES] = {1, 1, 1, 1, 1, 1, 1, 1};
14
15 #ifdef DEBUG
16 #define EDGE_WIDTH 10
17 #define CORNER_SIZE 20
18 #else
19 #define EDGE_WIDTH 1
20 #define CORNER_SIZE 2
21 #endif
22 static void get_position(ObEdgeLocation edge, Rect screen, Rect *rect)
23 {
24     switch (edge) {
25         case OB_EDGE_TOP:
26             RECT_SET(*rect, CORNER_SIZE, 0,
27                      screen.width - 2 * CORNER_SIZE, EDGE_WIDTH);
28             break;
29         case OB_EDGE_TOPRIGHT:
30             RECT_SET(*rect, screen.width - CORNER_SIZE, 0,
31                      CORNER_SIZE, CORNER_SIZE);
32             break;
33         case OB_EDGE_RIGHT:
34             RECT_SET(*rect, screen.width - EDGE_WIDTH, CORNER_SIZE,
35                      EDGE_WIDTH, screen.height - 2 * CORNER_SIZE);
36             break;
37         case OB_EDGE_BOTTOMRIGHT:
38             RECT_SET(*rect, screen.width - CORNER_SIZE,
39                      screen.height - CORNER_SIZE,
40                      CORNER_SIZE, CORNER_SIZE);
41             break;
42         case OB_EDGE_BOTTOM:
43             RECT_SET(*rect, CORNER_SIZE, screen.height - EDGE_WIDTH,
44                      screen.width - 2 * CORNER_SIZE, EDGE_WIDTH);
45             break;
46         case OB_EDGE_BOTTOMLEFT:
47             RECT_SET(*rect, 0, screen.height - CORNER_SIZE,
48                      CORNER_SIZE, CORNER_SIZE);
49             break;
50         case OB_EDGE_LEFT:
51             RECT_SET(*rect, 0, CORNER_SIZE,
52                      EDGE_WIDTH, screen.height - 2 * CORNER_SIZE);
53             break;
54         case OB_EDGE_TOPLEFT:
55             RECT_SET(*rect, 0, 0, CORNER_SIZE, CORNER_SIZE);
56             break;
57     }
58     rect[0].x += screen.x;
59     rect[0].y += screen.y;
60 }
61
62 void edges_startup(gboolean reconfigure)
63 {
64     ObEdgeLocation i;
65     gint m;
66     Rect r;
67     XSetWindowAttributes xswa;
68
69     xswa.override_redirect = True;
70
71     edge = g_slice_alloc(sizeof(ObEdge**) * screen_num_monitors);
72     for (m = 0; m < screen_num_monitors; m++) {
73         const Rect *monitor = screen_physical_area_monitor(m);
74         edge[m] = g_slice_alloc(sizeof(ObEdge*) * OB_NUM_EDGES);
75         for (i=0; i < OB_NUM_EDGES; i++) {
76             if (!config_edge_enabled[i])
77                 continue;
78
79             edge[m][i] = g_slice_new(ObEdge);
80             edge[m][i]->obwin.type = OB_WINDOW_CLASS_EDGE;
81             edge[m][i]->location = i;
82
83             get_position(i, *monitor, &r);
84             edge[m][i]->win = XCreateWindow(obt_display, obt_root(ob_screen),
85                                          r.x, r.y, r.width, r.height, 0, 0, InputOnly,
86                                          CopyFromParent, CWOverrideRedirect, &xswa);
87             XSelectInput(obt_display, edge[m][i]->win, ButtonPressMask | ButtonReleaseMask
88                          | EnterWindowMask | LeaveWindowMask);
89             XMapWindow(obt_display, edge[m][i]->win);
90
91             stacking_add(EDGE_AS_WINDOW(edge[m][i]));
92             window_add(&edge[m][i]->win, EDGE_AS_WINDOW(edge[m][i]));
93
94 #ifdef DEBUG
95             ob_debug("mapped edge window %i at %03i %03i %02i %02i", i, r.x, r.y, r.width, r.height);
96 #endif
97         }
98     }
99
100     XFlush(obt_display);
101 }
102
103 void edges_shutdown(gboolean reconfigure)
104 {
105     gint i, m;
106
107     for (m = 0; m < screen_num_monitors; m++) {
108         for (i = 0; i < OB_NUM_EDGES; i++) {
109             window_remove(edge[m][i]->win);
110             stacking_remove(EDGE_AS_WINDOW(edge[m][i]));
111             XDestroyWindow(obt_display, edge[m][i]->win);
112             g_slice_free(ObEdge, edge[m][i]);
113         }
114         g_slice_free1(sizeof(ObEdge*) * OB_NUM_EDGES, edge[m]);
115     }
116     g_slice_free1(sizeof(ObEdge**) * screen_num_monitors, edge);
117 }