diff --git a/Makefile.am b/Makefile.am
index bc0ff88..01bda93 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -205,6 +205,7 @@ openbox_openbox_SOURCES = \
openbox/actions/showdesktop.c \
openbox/actions/showmenu.c \
openbox/actions/unfocus.c \
+ openbox/actions/tiling.c \
openbox/actions.c \
openbox/actions.h \
openbox/client.c \
diff --git a/data/rc.xml b/data/rc.xml
index 04447f3..c7cce57 100644
--- a/data/rc.xml
+++ b/data/rc.xml
@@ -216,6 +216,12 @@
+
+
+
+
+
+
diff --git a/openbox/actions/all.c b/openbox/actions/all.c
index c86c428..dbb1fec 100644
--- a/openbox/actions/all.c
+++ b/openbox/actions/all.c
@@ -39,4 +39,6 @@ void action_all_startup(void)
action_growtoedge_startup();
action_if_startup();
action_focustobottom_startup();
+ action_tiling_startup();
+
}
diff --git a/openbox/actions/all.h b/openbox/actions/all.h
index 909836a..827e81c 100644
--- a/openbox/actions/all.h
+++ b/openbox/actions/all.h
@@ -40,5 +40,6 @@ void action_movetoedge_startup(void);
void action_growtoedge_startup(void);
void action_if_startup(void);
void action_focustobottom_startup(void);
+void action_tiling_startup(void);
#endif
diff --git a/openbox/event.c b/openbox/event.c
index 44b6eb7..7fe0aab 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -761,7 +761,6 @@ static void event_handle_root(XEvent *e)
ob_debug("Another WM has requested to replace us. Exiting.");
ob_exit_replace();
break;
-
case ClientMessage:
if (e->xclient.format != 32) break;
diff --git a/openbox/screen.c b/openbox/screen.c
index 3b9f66f..0f2b9f8 100644
--- a/openbox/screen.c
+++ b/openbox/screen.c
@@ -55,9 +55,13 @@ static gboolean screen_validate_layout(ObDesktopLayout *l);
static gboolean replace_wm(void);
static void screen_tell_ksplash(void);
static void screen_fallback_focus(void);
+static void refresh_tiling_screens();
guint screen_num_desktops;
+
guint screen_num_monitors;
+guint screen_num_monitors_phys;
+
guint screen_desktop;
guint screen_last_desktop;
gboolean screen_showing_desktop;
@@ -71,6 +75,14 @@ static guint screen_old_desktop;
static gboolean screen_desktop_timeout = TRUE;
/*! An array of desktops, holding an array of areas per monitor */
static Rect *monitor_area = NULL;
+/* array holding physical screens, previos one virtual */
+static Rect *monitor_area_phys = NULL;
+static ObTiledScreen *tiled_screens = NULL;
+
+
+static ObTilingLayout TilingLayout = OB_TL_NONE;
+
+
/*! An array of desktops, holding an array of struts */
static GSList *struts_top = NULL;
static GSList *struts_left = NULL;
@@ -1349,14 +1361,25 @@ static void get_xinerama_screens(Rect **xin_areas, guint *nxin)
void screen_update_areas(void)
{
- guint i, j;
- gulong *dims;
- GList *it;
- GSList *sit;
+ ob_debug("screen_update_areas.");
g_free(monitor_area);
get_xinerama_screens(&monitor_area, &screen_num_monitors);
+ refresh_tiling_screens();
+
+ _screen_update_areas();
+}
+void _screen_update_areas(void)
+{
+ guint i, j;
+ gulong *dims;
+ GList *it;
+ GSList *sit;
+
+ ob_debug("_screen_update_areas.");
+
+
/* set up the user-specified margins */
config_margins.top_start = RECT_LEFT(monitor_area[screen_num_monitors]);
config_margins.top_end = RECT_RIGHT(monitor_area[screen_num_monitors]);
@@ -1731,3 +1754,232 @@ gboolean screen_pointer_pos(gint *x, gint *y)
}
return ret;
}
+
+void init_phys_screens()
+{
+ if( monitor_area_phys == NULL )
+ {
+ //not yet initialized
+
+ ob_debug("initialize tiling stuff." );
+
+
+ monitor_area_phys = g_memdup( monitor_area, sizeof(Rect) * (screen_num_monitors + 1) );
+ screen_num_monitors_phys = screen_num_monitors;
+
+ //initialize array with tiled screens, tiled screens array has same dimension as phys screens
+
+ tiled_screens = g_new0(ObTiledScreen, screen_num_monitors_phys);
+ int i;
+ for( i = 0; i < screen_num_monitors_phys; i++ )
+ {
+ tiled_screens[i].used_screens = 1;
+ tiled_screens[i].screens[0] = monitor_area_phys[i];
+ tiled_screens[i].TilingLayout = OB_TL_NONE;
+ }
+ }
+}
+
+gint find_phys_screen( gint _x, gint _y )
+{
+ ob_debug("search phys screen for [%d][%d].", _x, _y );
+
+ init_phys_screens();
+ int i;
+ for( i = 0; i < screen_num_monitors_phys; i++ )
+ {
+ if(
+ monitor_area_phys[i].x <= _x &&
+ monitor_area_phys[i].y <= _y &&
+ ( monitor_area_phys[i].x + monitor_area_phys[i].width ) >= _x &&
+ ( monitor_area_phys[i].y + monitor_area_phys[i].height ) >= _y )
+ {
+ ob_debug("\tfound [%d].", i );
+ return i;
+ }
+ }
+
+ ob_debug("\tnot found [%d].", i );
+ return 0;
+}
+
+void set_tiling_layout_next( gint _x, gint _y )
+{
+ gint phys_screen = find_phys_screen( _x, _y );
+
+ ObTilingLayout ntl;
+
+ if( tiled_screens[phys_screen].TilingLayout == OB_TL_FOUR )
+ {
+ ob_debug("set NONE tiling." );
+ ntl = OB_TL_NONE;
+ }
+ else
+ {
+ ntl = (ObTilingLayout)(tiled_screens[phys_screen].TilingLayout + 1);
+ ob_debug("\tset next layout [%d].", ntl );
+ }
+ set_tiling_layout( _x, _y, ntl );
+
+}
+
+void set_tiling_layout( gint _x, gint _y, ObTilingLayout _tl )
+{
+ ob_debug("set tiling layout [%d][%d][%d].", _x, _y, _tl );
+
+
+ gint phys_screen = find_phys_screen( _x, _y );
+
+ tiled_screens[phys_screen].TilingLayout = _tl;
+
+ gint x = monitor_area_phys[phys_screen].x;
+ gint y = monitor_area_phys[phys_screen].y;
+ gint width = monitor_area_phys[phys_screen].width;
+ gint height = monitor_area_phys[phys_screen].height;
+
+ if( tiled_screens[phys_screen].x == 0 || tiled_screens[phys_screen].y == 0 )
+ {
+ tiled_screens[phys_screen].x = width / 2;
+ tiled_screens[phys_screen].y = height / 2;
+ }
+
+ set_tiling_center( tiled_screens[phys_screen].x + x, tiled_screens[phys_screen].y + y );
+
+}
+
+void generate_virtual_screens()
+{
+ g_free( monitor_area );
+
+ int i,n,k;
+ screen_num_monitors = 0;
+ for( i = 0; i < screen_num_monitors_phys; i++ )
+ screen_num_monitors += tiled_screens[i].used_screens;
+
+ ob_debug("generate virtual screens [%d].", screen_num_monitors );
+
+
+ monitor_area = g_new( Rect, screen_num_monitors + 1 );
+
+ n = 0;
+
+ for( i = 0; i < screen_num_monitors_phys; i++ )
+ {
+ for( k = 0; k < tiled_screens[i].used_screens; k++,n++ )
+ {
+ ob_debug("add virtual screen with dims [%d][%d][%d][%d].",
+ tiled_screens[i].screens[k].x,
+ tiled_screens[i].screens[k].y,
+ tiled_screens[i].screens[k].width,
+ tiled_screens[i].screens[k].height);
+ monitor_area[n] = tiled_screens[i].screens[k];
+ }
+ }
+
+ monitor_area[screen_num_monitors] = monitor_area_phys[screen_num_monitors_phys];
+
+ _screen_update_areas();
+}
+
+//call it every time resolution of screen,display ot what ever has been changed
+static void refresh_tiling_screens()
+{
+ if( monitor_area_phys == NULL )
+ {
+ //seems to is not used untill now
+ return;
+ }
+
+ /* to make it easer, we just drop all tiling infos
+ * but it whould be nice to recalculate all tiling screens
+ * it is not clear how to handle if one of phisycal screns disapears */
+
+ g_free( monitor_area_phys );
+ monitor_area_phys = NULL;
+ g_free( tiled_screens );
+ tiled_screens = NULL;
+ screen_num_monitors_phys = 0;
+
+
+}
+
+#define SETSCREEN(a,b,c,d,e) RECT_SET(tiled_screens[phys_screen].screens[a],x+(b),y+(c),(d),(e))
+#define TSCREEN tiled_screens[phys_screen]
+
+void set_tiling_center( gint _x, gint _y )
+{
+ gint phys_screen = find_phys_screen( _x, _y );
+
+ gint w = monitor_area_phys[phys_screen].width;
+ gint h = monitor_area_phys[phys_screen].height;
+ gint x = monitor_area_phys[phys_screen].x;
+ gint y = monitor_area_phys[phys_screen].y;
+
+ tiled_screens[phys_screen].x = _x - x;
+ tiled_screens[phys_screen].y = _y - y;
+
+ switch( tiled_screens[phys_screen].TilingLayout )
+ {
+ case OB_TL_NONE:
+ SETSCREEN(0, 0, 0, w, h);
+ TSCREEN.used_screens = 1;
+ break;
+ case OB_TL_FOUR:
+ SETSCREEN(0, 0, 0, TSCREEN.x, TSCREEN.y);
+ SETSCREEN(1, TSCREEN.x, 0, w-TSCREEN.x, TSCREEN.y);
+ SETSCREEN(2, 0, TSCREEN.y, TSCREEN.x, h-TSCREEN.y);
+ SETSCREEN(3, TSCREEN.x, TSCREEN.y, w-TSCREEN.x, h-TSCREEN.y);
+ TSCREEN.used_screens = 4;
+ break;
+ case OB_TL_TWO_HORISONTAL:
+ SETSCREEN(0, 0, 0, w, TSCREEN.y);
+ SETSCREEN(1, 0, TSCREEN.y, w, h-TSCREEN.y);
+ TSCREEN.used_screens = 2;
+ break;
+ case OB_TL_TWO_VERTICAL:
+ SETSCREEN(0, 0, 0, TSCREEN.x, h);
+ SETSCREEN(1, TSCREEN.x, 0, w-TSCREEN.x, h);
+ TSCREEN.used_screens = 2;
+ break;
+ case OB_TL_THREE_TOP:
+ SETSCREEN(0, 0, 0, w, TSCREEN.y);
+ SETSCREEN(1, 0, TSCREEN.y, TSCREEN.x, h-TSCREEN.y);
+ SETSCREEN(2, TSCREEN.x, TSCREEN.y, w-TSCREEN.x, h-TSCREEN.y);
+ TSCREEN.used_screens = 3;
+ break;
+ case OB_TL_THREE_BOTTOM:
+ SETSCREEN(0, 0, 0, TSCREEN.x, TSCREEN.y);
+ SETSCREEN(1, TSCREEN.x, 0, w-TSCREEN.x, TSCREEN.y);
+ SETSCREEN(2, 0, TSCREEN.y, w, h-TSCREEN.y);
+ TSCREEN.used_screens = 3;
+ break;
+ case OB_TL_THREE_LEFT:
+ SETSCREEN(0, 0, 0, TSCREEN.x, h);
+ SETSCREEN(1, TSCREEN.x, 0, w-TSCREEN.x, TSCREEN.y);
+ SETSCREEN(2, TSCREEN.x, TSCREEN.y, w-TSCREEN.x, h-TSCREEN.y);
+ TSCREEN.used_screens = 3;
+ break;
+ case OB_TL_THREE_RIGHT:
+ SETSCREEN(0, 0, 0, TSCREEN.x, TSCREEN.y);
+ SETSCREEN(1, 0, TSCREEN.y, TSCREEN.x, h-TSCREEN.y);
+ SETSCREEN(2, TSCREEN.x, 0, w-TSCREEN.x, h);
+ TSCREEN.used_screens = 3;
+ break;
+ }
+
+ generate_virtual_screens();
+}
+
+#undef SETSCREEN
+
+static void allocate_screens( gint _n )
+{
+ if( _n <= 0 ) return;
+
+ g_free( monitor_area );
+
+ screen_num_monitors = _n;
+
+ monitor_area = g_new(Rect, screen_num_monitors + 1 );
+}
+
diff --git a/openbox/screen.h b/openbox/screen.h
index 11915f1..12b637d 100644
--- a/openbox/screen.h
+++ b/openbox/screen.h
@@ -133,4 +133,39 @@ void screen_set_root_cursor(void);
is on this screen and FALSE if it is on another screen. */
gboolean screen_pointer_pos(gint *x, gint *y);
+/* tiling layouts */
+
+typedef enum
+{
+ OB_TL_NONE = 0,
+ /* three areas, one big on top */
+ OB_TL_THREE_TOP,
+ /* three areas, one big on left */
+ OB_TL_THREE_LEFT,
+ OB_TL_THREE_BOTTOM,
+ OB_TL_THREE_RIGHT,
+ /* two areas, splitted vertically */
+ OB_TL_TWO_VERTICAL,
+ /* two areas, splitted horisontally */
+ OB_TL_TWO_HORISONTAL,
+ /* four small areas, do not put anything after this one */
+ OB_TL_FOUR
+} ObTilingLayout;
+
+typedef struct
+{
+ ObTilingLayout TilingLayout;
+ //dimensions of tiles, max 4 supported
+ Rect screens[4];
+ //tiling center
+ gint x;
+ gint y;
+
+ gint used_screens;
+} ObTiledScreen;
+
+void set_tiling_center( gint _x, gint _y );
+void set_tiling_layout( gint _x, gint _y, ObTilingLayout _tl );
+void set_tiling_layout_next( gint _x, gint _y );
+
#endif