-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwindow.c
125 lines (112 loc) · 5.36 KB
/
window.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "window.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
void collide(int16_t *speed, int16_t *pos, int16_t min_pos, int16_t max_pos) {
if (*pos > max_pos) {
*pos = 2 * max_pos - *pos;
*speed *= -1;
} else if (*pos < min_pos) {
*pos = 2 * min_pos - *pos;
*speed *= -1;
}
}
static xcb_window_t window_create(xcb_connection_t *connection,
const xcb_screen_t *screen, uint32_t color,
bool override_redirect, int16_t x, int16_t y,
uint16_t width, uint16_t height) {
const xcb_window_t window = xcb_generate_id(connection);
const uint32_t mask =
XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
const uint32_t values[] = {color, override_redirect,
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_STRUCTURE_NOTIFY};
xcb_create_window(connection, /* connection */
XCB_COPY_FROM_PARENT, /* depth */
window, /* window id */
screen->root, /* parent window */
x, y, /* x, y */
width, height, /* width, height */
0, /* border width */
XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
screen->root_visual, /* visual */
mask, values /* masks */
);
return window;
}
static void window_setup(xcb_connection_t *connection, xcb_window_t window,
xcb_atom_t atoms[], const char *window_name) {
if (atoms[PROTOCOL_ATOM] != XCB_ATOM_NONE &&
atoms[DELETE_WINDOW_ATOM] != XCB_ATOM_NONE) {
xcb_change_property(connection, XCB_PROP_MODE_APPEND, window,
atoms[PROTOCOL_ATOM], XCB_ATOM_ATOM, 32, 1,
&atoms[DELETE_WINDOW_ATOM]);
}
if (atoms[WINDOW_TYPE_ATOM] != XCB_ATOM_NONE &&
atoms[DIALOG_ATOM] != XCB_ATOM_NONE) {
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window,
atoms[WINDOW_TYPE_ATOM], XCB_ATOM_ATOM, 32, 1,
&atoms[DIALOG_ATOM]);
}
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window,
XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(window_name),
window_name);
/* TODO: set the instance name in a better way */
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window,
XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, 18,
"xwinpong\0Xwinpong");
}
struct moving_window moving_window_create(xcb_connection_t *connection,
const xcb_screen_t *screen,
uint32_t color, bool borders,
int16_t x, int16_t y) {
const xcb_window_t window =
window_create(connection, screen, color, false, x, y, 150, 150);
const xcb_window_t other_window =
window_create(connection, screen, color, true, x, y, 150, 150);
return borders ? (struct moving_window){window, other_window, x, y,
150, 150, 0, 0}
: (struct moving_window){other_window, window, x, y,
150, 150, 0, 0};
}
/* Both windows get the atoms set */
void moving_window_setup(const struct moving_window *window,
xcb_connection_t *connection, xcb_atom_t atoms[],
const char *window_name) {
window_setup(connection, window->window, atoms, window_name);
window_setup(connection, window->other_window, atoms, window_name);
}
void moving_window_move(struct moving_window *window,
const xcb_screen_t *screen, double delta) {
const double screen_resolution_multiplier =
(double)screen->width_in_pixels / 1000.;
window->x += window->xspeed * screen_resolution_multiplier * delta;
window->y += window->yspeed * screen_resolution_multiplier * delta;
collide(&window->yspeed, &window->y, 0,
screen->height_in_pixels - window->height);
}
void moving_window_send_position(const struct moving_window *window,
xcb_connection_t *connection) {
const uint32_t coords[] = {window->x, window->y};
xcb_configure_window(connection, window->window,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords);
}
static void moving_window_send_size(const struct moving_window *window,
xcb_connection_t *connection) {
const uint32_t size[] = {window->width, window->height};
xcb_configure_window(connection, window->window,
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
size);
}
void moving_window_swap(struct moving_window *window,
xcb_connection_t *connection) {
xcb_unmap_window(connection, window->window);
xcb_window_t temp = window->window;
window->window = window->other_window;
window->other_window = temp;
moving_window_send_position(window, connection);
moving_window_send_size(window, connection);
xcb_map_window(connection, window->window);
}