First approachments in direction of table-based layout
This commit is contained in:
parent
023ec870a2
commit
efb8c11b7f
5
data.h
5
data.h
@ -2,6 +2,7 @@
|
||||
* This file defines all data structures used by i3
|
||||
*
|
||||
*/
|
||||
#include "queue.h"
|
||||
|
||||
/*
|
||||
* Defines a position in the table
|
||||
@ -36,4 +37,8 @@ typedef struct Client {
|
||||
/* XCB contexts */
|
||||
xcb_gcontext_t titlegc;
|
||||
xcb_window_t window;
|
||||
xcb_window_t child;
|
||||
|
||||
/* The following entry provides the necessary list pointers to use Client with LIST_* macros */
|
||||
LIST_ENTRY(Client) clients;
|
||||
} Client;
|
||||
|
154
mainx.c
154
mainx.c
@ -12,19 +12,31 @@
|
||||
#include "xcb_keysyms.h"
|
||||
#include "data.h"
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
Font myfont;
|
||||
|
||||
static const int TOP = 20;
|
||||
static const int LEFT = 5;
|
||||
static const int BOTTOM = 5;
|
||||
static const int RIGHT = 5;
|
||||
|
||||
/* hm, xcb_wm wants us to implement this. */
|
||||
table_t *byChild = 0;
|
||||
table_t *byParent = 0;
|
||||
xcb_window_t root_win;
|
||||
|
||||
int globalc = 0;
|
||||
/* We have a list of Clients, called all_clients */
|
||||
LIST_HEAD(all_clients_head, Client) all_clients;
|
||||
|
||||
Client myc;
|
||||
/* _the_ table. Stores all clients. */
|
||||
Client *table[10][10];
|
||||
|
||||
int current_col = 0;
|
||||
int current_row = 0;
|
||||
|
||||
|
||||
int globalc = 0;
|
||||
|
||||
|
||||
static const char *labelError[] = {
|
||||
@ -278,32 +290,15 @@ void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *c, xcb_win
|
||||
}
|
||||
|
||||
|
||||
static int addClientWindow(xcb_window_t child, xcb_window_t parent, xcb_gcontext_t titlegc)
|
||||
{
|
||||
int success;
|
||||
client_window_t *record = malloc(sizeof(client_window_t));
|
||||
assert(record);
|
||||
record->child = child;
|
||||
record->parent = parent;
|
||||
record->name_len = 0;
|
||||
record->name = 0;
|
||||
record->titlegc = titlegc;
|
||||
success = table_put(byParent, parent, record) &&
|
||||
table_put(byChild, child, record);
|
||||
assert(success);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the colorpixel to use for the given RGB color code
|
||||
*
|
||||
*/
|
||||
uint32_t get_colorpixel(xcb_connection_t *conn, int r, int g, int b) {
|
||||
uint32_t get_colorpixel(xcb_connection_t *conn, xcb_window_t window, int r, int g, int b) {
|
||||
xcb_screen_t *root_screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
|
||||
|
||||
xcb_colormap_t colormapId = xcb_generate_id(conn);
|
||||
/* TODO: we need to get myc.window away here */
|
||||
xcb_create_colormap(conn, XCB_COLORMAP_ALLOC_NONE, colormapId, myc.window, root_screen->root_visual);
|
||||
xcb_create_colormap(conn, XCB_COLORMAP_ALLOC_NONE, colormapId, window, root_screen->root_visual);
|
||||
xcb_alloc_color_reply_t *reply = xcb_alloc_color_reply(conn, xcb_alloc_color(conn, colormapId, r, g, b), NULL);
|
||||
|
||||
if (!reply) {
|
||||
@ -333,16 +328,39 @@ void decorate_window(xcb_connection_t *conn, Client *client) {
|
||||
|
||||
values[0] = root_screen->black_pixel;
|
||||
if (globalc++ > 1)
|
||||
values[1] = get_colorpixel(conn, 65535, 0, 0);
|
||||
else values[1] = get_colorpixel(conn, 0, 0, 65535);
|
||||
values[1] = get_colorpixel(conn, client->window, 65535, 0, 0);
|
||||
else values[1] = get_colorpixel(conn, client->window, 0, 0, 65535);
|
||||
values[2] = font;
|
||||
|
||||
xcb_change_gc(conn, client->titlegc, mask, values);
|
||||
|
||||
|
||||
/* TODO: utf8? */
|
||||
char *label = "i3 rocks :>";
|
||||
xcb_void_cookie_t textCookie = xcb_image_text_8_checked (conn, strlen (label), myc.window, myc.titlegc, 2, 15, label );
|
||||
//char *label = "i3 rocks :>";
|
||||
char *label;
|
||||
asprintf(&label, "gots win %p", client->window);
|
||||
xcb_void_cookie_t textCookie = xcb_image_text_8_checked (conn, strlen (label), client->window, client->titlegc, 2, 15, label );
|
||||
}
|
||||
|
||||
void render_layout(xcb_connection_t *conn) {
|
||||
int cols, rows;
|
||||
int values[4];
|
||||
for (rows = 0; rows < 10; rows++) {
|
||||
for (cols = 0; cols < 10; cols++) {
|
||||
if (table[cols][rows] != NULL) {
|
||||
Client *current = table[cols][rows];
|
||||
/* TODO; just update if necessary */
|
||||
values[0] = cols * 200;
|
||||
values[1] = rows * 200;
|
||||
values[2] = 200;
|
||||
values[3] = 200;
|
||||
xcb_configure_window(conn, current->window, XCB_CONFIG_WINDOW_X |
|
||||
XCB_CONFIG_WINDOW_Y |
|
||||
XCB_CONFIG_WINDOW_WIDTH |
|
||||
XCB_CONFIG_WINDOW_HEIGHT , values);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -353,12 +371,25 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||
xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
|
||||
int16_t x, int16_t y, uint16_t width, uint16_t height)
|
||||
{
|
||||
Client *new = malloc(sizeof(Client));
|
||||
xcb_drawable_t drawable;
|
||||
uint32_t mask = 0;
|
||||
uint32_t values[3];
|
||||
xcb_screen_t *root_screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
|
||||
|
||||
myc.window = xcb_generate_id(conn);
|
||||
/* Insert into the list of all clients */
|
||||
LIST_INSERT_HEAD(&all_clients, new, clients);
|
||||
|
||||
/* Insert into the table */
|
||||
if (table[current_col][current_row] == NULL)
|
||||
table[current_col][current_row] = new;
|
||||
else {
|
||||
current_row++;
|
||||
table[current_col][current_row] = new;
|
||||
}
|
||||
|
||||
new->window = xcb_generate_id(conn);
|
||||
new->child = child;
|
||||
|
||||
/* TODO: what do these mean? */
|
||||
mask |= XCB_CW_BACK_PIXEL;
|
||||
@ -371,12 +402,12 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||
values[2] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
|
||||
| XCB_EVENT_MASK_EXPOSURE /* | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW */;
|
||||
|
||||
printf("Reparenting 0x%08x under 0x%08x.\n", child, myc.window);
|
||||
printf("Reparenting 0x%08x under 0x%08x.\n", child, new->window);
|
||||
|
||||
/* Yo dawg, I heard you like windows, so I create a window around your window… */
|
||||
xcb_create_window(conn,
|
||||
depth,
|
||||
myc.window,
|
||||
new->window,
|
||||
root,
|
||||
x,
|
||||
y,
|
||||
@ -390,22 +421,22 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||
xcb_change_save_set(conn, XCB_SET_MODE_INSERT, child);
|
||||
|
||||
/* Map the window on the screen (= make it visible) */
|
||||
xcb_map_window(conn, myc.window);
|
||||
xcb_map_window(conn, new->window);
|
||||
|
||||
/* Generate a graphics context for the titlebar */
|
||||
myc.titlegc = xcb_generate_id(conn);
|
||||
xcb_create_gc(conn, myc.titlegc, myc.window, 0, 0);
|
||||
new->titlegc = xcb_generate_id(conn);
|
||||
xcb_create_gc(conn, new->titlegc, new->window, 0, 0);
|
||||
|
||||
/* Draw decorations */
|
||||
decorate_window(conn, &myc);
|
||||
decorate_window(conn, new);
|
||||
|
||||
/* add the title context as a child for the window */
|
||||
/* TODO: replace this, it's internal */
|
||||
addClientWindow(child, myc.window, myc.titlegc);
|
||||
/* Put our data structure (Client) into the table */
|
||||
table_put(byParent, new->window, new);
|
||||
table_put(byChild, child, new);
|
||||
|
||||
/* Moves the original window into the new frame we've created for it */
|
||||
/* TODO: hmm, LEFT/TOP needs to go */
|
||||
xcb_reparent_window(conn, child, myc.window, LEFT - 1, TOP - 1);
|
||||
xcb_reparent_window(conn, child, new->window, LEFT - 1, TOP - 1);
|
||||
|
||||
/* We are interested in property changes */
|
||||
mask = XCB_CW_EVENT_MASK;
|
||||
@ -413,27 +444,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||
xcb_change_window_attributes(conn, child, mask, values);
|
||||
|
||||
/* TODO: At the moment, new windows just get focus */
|
||||
|
||||
xcb_get_input_focus_reply_t *reply = xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL);
|
||||
if (reply) {
|
||||
printf("got focus info\n");
|
||||
printf("focus is at %p\n", reply->focus);
|
||||
printf("window is at %p\n", myc.window);
|
||||
|
||||
free(reply);
|
||||
}
|
||||
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_NONE, myc.window, XCB_CURRENT_TIME);
|
||||
|
||||
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, myc.window, XCB_CURRENT_TIME);
|
||||
reply = xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL);
|
||||
if (reply) {
|
||||
printf("got focus info\n");
|
||||
printf("focus is at %p\n", reply->focus);
|
||||
printf("window is at %p\n", myc.window);
|
||||
|
||||
free(reply);
|
||||
}
|
||||
|
||||
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_NONE, new->window, XCB_CURRENT_TIME);
|
||||
|
||||
#if 0
|
||||
|
||||
@ -458,6 +469,7 @@ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_NONE, myc.window, XCB_CURRENT_TIME);
|
||||
&myc.window);
|
||||
#endif
|
||||
|
||||
render_layout(conn);
|
||||
|
||||
xcb_flush(conn);
|
||||
}
|
||||
@ -537,7 +549,7 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_generic_e
|
||||
execve("/usr/bin/xterm", argv, env);
|
||||
}
|
||||
} else if (event->detail == 38) {
|
||||
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, myc.window, XCB_CURRENT_TIME);
|
||||
//xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, myc.window, XCB_CURRENT_TIME);
|
||||
}
|
||||
|
||||
//decorate_window(c, &myc);
|
||||
@ -553,22 +565,25 @@ static int handle_motion(void *ignored, xcb_connection_t *conn, xcb_generic_even
|
||||
|
||||
if (event->root_x < 50) {
|
||||
printf("setting focus\n");
|
||||
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, myc.window, XCB_CURRENT_TIME);
|
||||
//xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, myc.window, XCB_CURRENT_TIME);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void redrawWindow(xcb_connection_t *c, client_window_t *client)
|
||||
static void redrawWindow(xcb_connection_t *c, Client *client)
|
||||
{
|
||||
#if 0
|
||||
printf("redrawing window.\n");
|
||||
xcb_drawable_t d = { client->parent };
|
||||
xcb_drawable_t d = { client->window };
|
||||
if(!client->name_len)
|
||||
return;
|
||||
xcb_clear_area(c, 0, d, 0, 0, 0, 0);
|
||||
xcb_image_text_8(c, client->name_len, d, client->titlegc,
|
||||
LEFT - 1, TOP - 4, client->name);
|
||||
xcb_flush(c);
|
||||
#endif
|
||||
decorate_window(c, client);
|
||||
}
|
||||
|
||||
int handle_map_notify_event(void *prophs, xcb_connection_t *c, xcb_map_notify_event_t *e)
|
||||
@ -582,7 +597,7 @@ int handle_map_notify_event(void *prophs, xcb_connection_t *c, xcb_map_notify_ev
|
||||
|
||||
int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_event_t *e)
|
||||
{
|
||||
client_window_t *client = table_remove(byChild, e->event);
|
||||
Client *client = table_remove(byChild, e->event);
|
||||
xcb_window_t root;
|
||||
printf("UnmapNotify for 0x%08x (received from 0x%08x): ", e->window, e->event);
|
||||
if(!client)
|
||||
@ -592,11 +607,11 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_
|
||||
}
|
||||
|
||||
root = xcb_setup_roots_iterator(xcb_get_setup(c)).data->root;
|
||||
printf("child of 0x%08x.\n", client->parent);
|
||||
printf("child of 0x%08x.\n", client->window);
|
||||
xcb_reparent_window(c, client->child, root, 0, 0);
|
||||
xcb_destroy_window(c, client->parent);
|
||||
xcb_destroy_window(c, client->window);
|
||||
xcb_flush(c);
|
||||
table_remove(byParent, client->parent);
|
||||
table_remove(byParent, client->window);
|
||||
free(client);
|
||||
return 1;
|
||||
}
|
||||
@ -606,7 +621,7 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *c, xcb_unmap_notify_
|
||||
static int handleExposeEvent(void *data, xcb_connection_t *c, xcb_expose_event_t *e)
|
||||
{
|
||||
printf("exposeevent\n");
|
||||
client_window_t *client = table_get(byParent, e->window);
|
||||
Client *client = table_get(byParent, e->window);
|
||||
if(!client || e->count != 0)
|
||||
return 1;
|
||||
redrawWindow(c, client);
|
||||
@ -643,6 +658,12 @@ void manage_existing_windows(xcb_connection_t *c, xcb_property_handlers_t *proph
|
||||
}
|
||||
|
||||
int main() {
|
||||
LIST_INIT(&all_clients);
|
||||
int i, j;
|
||||
for (i = 0; i < 10; i++)
|
||||
for (j = 0; j < 10; j++)
|
||||
table[i][j] = NULL;
|
||||
|
||||
xcb_connection_t *c;
|
||||
xcb_event_handlers_t evenths;
|
||||
xcb_property_handlers_t prophs;
|
||||
@ -676,7 +697,6 @@ myfont.height = reply->font_ascent + reply->font_descent;
|
||||
|
||||
|
||||
xcb_event_handlers_init(c, &evenths);
|
||||
int i;
|
||||
for(i = 2; i < 128; ++i)
|
||||
xcb_event_set_handler(&evenths, i, handleEvent, 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user