edges should hook into number of screens changing, but for now, don't crash at reconf...
[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 /* this could change at runtime, we should hook into that, but for now
15  * don't crash on reconfigure/shutdown */
16 static edge_monitors;
17
18 #ifdef DEBUG
19 #define EDGE_WIDTH 10
20 #define CORNER_SIZE 20
21 #else
22 #define EDGE_WIDTH 1
23 #define CORNER_SIZE 2
24 #endif
25 static void get_position(ObEdgeLocation edge, Rect screen, Rect *rect)
26 {
27     switch (edge) {
28         case OB_EDGE_TOP:
29             RECT_SET(*rect, CORNER_SIZE, 0,
30                      screen.width - 2 * CORNER_SIZE, EDGE_WIDTH);
31             break;
32         case OB_EDGE_TOPRIGHT:
33             RECT_SET(*rect, screen.width - CORNER_SIZE, 0,
34                      CORNER_SIZE, CORNER_SIZE);
35             break;
36         case OB_EDGE_RIGHT:
37             RECT_SET(*rect, screen.width - EDGE_WIDTH, CORNER_SIZE,
38                      EDGE_WIDTH, screen.height - 2 * CORNER_SIZE);
39             break;
40         case OB_EDGE_BOTTOMRIGHT:
41             RECT_SET(*rect, screen.width - CORNER_SIZE,
42                      screen.height - CORNER_SIZE,
43                      CORNER_SIZE, CORNER_SIZE);
44             break;
45         case OB_EDGE_BOTTOM:
46             RECT_SET(*rect, CORNER_SIZE, screen.height - EDGE_WIDTH,
47                      screen.width - 2 * CORNER_SIZE, EDGE_WIDTH);
48             break;
49         case OB_EDGE_BOTTOMLEFT:
50             RECT_SET(*rect, 0, screen.height - CORNER_SIZE,
51                      CORNER_SIZE, CORNER_SIZE);
52             break;
53         case OB_EDGE_LEFT:
54             RECT_SET(*rect, 0, CORNER_SIZE,
55                      EDGE_WIDTH, screen.height - 2 * CORNER_SIZE);
56             break;
57         case OB_EDGE_TOPLEFT:
58             RECT_SET(*rect, 0, 0, CORNER_SIZE, CORNER_SIZE);
59             break;
60     }
61     rect[0].x += screen.x;
62     rect[0].y += screen.y;
63 }
64
65 void edges_startup(gboolean reconfigure)
66 {
67     ObEdgeLocation i;
68     gint m;
69     Rect r;
70     XSetWindowAttributes xswa;
71
72     xswa.override_redirect = True;
73
74     edge_monitors = screen_num_monitors;
75
76     edge = g_slice_alloc(sizeof(ObEdge**) * edge_monitors);
77     for (m = 0; m < edge_monitors; m++) {
78         const Rect *monitor = screen_physical_area_monitor(m);
79         edge[m] = g_slice_alloc(sizeof(ObEdge*) * OB_NUM_EDGES);
80         for (i=0; i < OB_NUM_EDGES; i++) {
81             if (!config_edge_enabled[i])
82                 continue;
83
84             edge[m][i] = g_slice_new(ObEdge);
85             edge[m][i]->obwin.type = OB_WINDOW_CLASS_EDGE;
86             edge[m][i]->location = i;
87
88             get_position(i, *monitor, &r);
89             edge[m][i]->win = XCreateWindow(obt_display, obt_root(ob_screen),
90                                          r.x, r.y, r.width, r.height, 0, 0, InputOnly,
91                                          CopyFromParent, CWOverrideRedirect, &xswa);
92             XSelectInput(obt_display, edge[m][i]->win, ButtonPressMask | ButtonReleaseMask
93                          | EnterWindowMask | LeaveWindowMask);
94             XMapWindow(obt_display, edge[m][i]->win);
95
96             stacking_add(EDGE_AS_WINDOW(edge[m][i]));
97             window_add(&edge[m][i]->win, EDGE_AS_WINDOW(edge[m][i]));
98
99 #ifdef DEBUG
100             ob_debug("mapped edge window %i at %03i %03i %02i %02i", i, r.x, r.y, r.width, r.height);
101 #endif
102         }
103     }
104
105     XFlush(obt_display);
106 }
107
108 void edges_shutdown(gboolean reconfigure)
109 {
110     gint i, m;
111
112     for (m = 0; m < edge_monitors; m++) {
113         for (i = 0; i < OB_NUM_EDGES; i++) {
114             if (!config_edge_enabled[i])
115                 continue;
116
117             window_remove(edge[m][i]->win);
118             stacking_remove(EDGE_AS_WINDOW(edge[m][i]));
119             XDestroyWindow(obt_display, edge[m][i]->win);
120             g_slice_free(ObEdge, edge[m][i]);
121         }
122         g_slice_free1(sizeof(ObEdge*) * OB_NUM_EDGES, edge[m]);
123     }
124     g_slice_free1(sizeof(ObEdge**) * edge_monitors, edge);
125 }