Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 62 additions & 8 deletions openbox/actions/if.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "openbox/frame.h"
#include "openbox/screen.h"
#include "openbox/focus.h"
#include "openbox/config.h"
#include <glib.h>

typedef enum {
Expand Down Expand Up @@ -68,9 +69,15 @@ typedef struct {
gboolean omnipresent_off;
gboolean desktop_current;
gboolean desktop_other;
gboolean containsx_check;
gboolean containsy_check;
guint desktop_number;
guint screendesktop_number;
guint client_monitor;
guint xpoint;
guint xpoint_denom;
guint ypoint;
guint ypoint_denom;
TypedMatch title;
TypedMatch class;
TypedMatch name;
Expand All @@ -82,6 +89,8 @@ typedef struct {
GArray *queries;
GSList *thenacts;
GSList *elseacts;
gboolean stacking_order_on;
gboolean stacking_order_reversed;
} Options;

static gpointer setup_func(xmlNodePtr node);
Expand Down Expand Up @@ -174,6 +183,8 @@ static void setup_query(Options* o, xmlNodePtr node, QueryTarget target) {
Query *q = g_slice_new0(Query);
g_array_append_val(o->queries, q);

gchar *s;

q->target = target;

set_bool(node, "shaded", &q->shaded_on, &q->shaded_off);
Expand All @@ -188,7 +199,6 @@ static void setup_query(Options* o, xmlNodePtr node, QueryTarget target) {

xmlNodePtr n;
if ((n = obt_xml_find_node(node, "desktop"))) {
gchar *s;
if ((s = obt_xml_node_string(n))) {
if (!g_ascii_strcasecmp(s, "current"))
q->desktop_current = TRUE;
Expand Down Expand Up @@ -220,6 +230,18 @@ static void setup_query(Options* o, xmlNodePtr node, QueryTarget target) {
if ((n = obt_xml_find_node(node, "monitor"))) {
q->client_monitor = obt_xml_node_int(n);
}
if ((n = obt_xml_find_node(node, "containsxpoint"))) {
s = obt_xml_node_string(n);
config_parse_relative_number(s, &q->xpoint, &q->xpoint_denom);
q->containsx_check = TRUE;
g_free(s);
}
if ((n = obt_xml_find_node(node, "containsypoint"))) {
s = obt_xml_node_string(n);
config_parse_relative_number(s, &q->ypoint, &q->ypoint_denom);
q->containsy_check = TRUE;
g_free(s);
}
}

static gpointer setup_func(xmlNodePtr node)
Expand Down Expand Up @@ -273,6 +295,8 @@ static gpointer setup_func(xmlNodePtr node)
}
}

set_bool(node, "stacking_order", &o->stacking_order_on, &o->stacking_order_reversed);

return o;
}

Expand Down Expand Up @@ -413,6 +437,28 @@ static gboolean run_func_if(ObActionsData *data, gpointer options)
if (q->client_monitor)
is_true &= client_monitor(query_target) == q->client_monitor - 1;

// Since 0,0 is a valid pixel location we need to check separate boolean
if (q->containsx_check) {
gint xpoint = q->xpoint;
// Since the denominator cannot reasonably be zero, this is a valid check
if (q->xpoint_denom) {
const Rect *containing_area = screen_physical_area_monitor(client_monitor(query_target));
xpoint = (q->xpoint * containing_area->width) / q->xpoint_denom;
}
is_true &= xpoint >= RECT_LEFT(query_target->frame->area);
is_true &= xpoint <= RECT_RIGHT(query_target->frame->area);
}
// Since 0,0 is a valid pixel location we need to check separate boolean
if (q->containsy_check) {
gint ypoint = q->ypoint;
// Since the denominator cannot reasonably be zero, this is a valid check
if (q->ypoint_denom) {
const Rect *containing_area = screen_physical_area_monitor(client_monitor(query_target));
ypoint = (q->ypoint * containing_area->height) / q->ypoint_denom;
}
is_true &= ypoint >= RECT_TOP(query_target->frame->area);
is_true &= ypoint <= RECT_BOTTOM(query_target->frame->area);
}
}

GSList *acts;
Expand All @@ -431,15 +477,23 @@ static gboolean run_func_if(ObActionsData *data, gpointer options)
static gboolean run_func_foreach(ObActionsData *data, gpointer options)
{
GList *it;
Options *o = options;

foreach_stop = FALSE;

for (it = client_list; it; it = g_list_next(it)) {
data->client = it->data;
run_func_if(data, options);
if (foreach_stop) {
foreach_stop = FALSE;
break;
it = client_list;
if (o->stacking_order_on)
it = stacking_list;
else if (o->stacking_order_reversed)
it = stacking_list_tail;

for (; it; it = g_list_next(it)) {
if (WINDOW_IS_CLIENT(it->data)) {
data->client = it->data;
run_func_if(data, options);
if (foreach_stop) {
foreach_stop = FALSE;
break;
}
}
}

Expand Down
45 changes: 26 additions & 19 deletions openbox/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -4670,31 +4670,38 @@ void client_find_resize_directional(ObClient *self,
*h -= self->frame->size.top + self->frame->size.bottom;
}

ObClient* client_at_point(gint x, gint y)
{
ObClient *ret = NULL;
GList *it;
for (it = stacking_list; it; it = g_list_next(it)) {
if (WINDOW_IS_CLIENT(it->data)) {
ObClient *c = WINDOW_AS_CLIENT(it->data);
if (c->frame->visible &&
/* check the desktop, this is done during desktop
switching and windows are shown/hidden status is not
reliable */
(c->desktop == screen_desktop ||
c->desktop == DESKTOP_ALL) &&
/* ignore all animating windows */
!frame_iconify_animating(c->frame) &&
RECT_CONTAINS(c->frame->area, x, y))
{
ret = c;
break;
}
}
}
return ret;
}

ObClient* client_under_pointer(void)
{
gint x, y;
GList *it;
ObClient *ret = NULL;

if (screen_pointer_pos(&x, &y)) {
for (it = stacking_list; it; it = g_list_next(it)) {
if (WINDOW_IS_CLIENT(it->data)) {
ObClient *c = WINDOW_AS_CLIENT(it->data);
if (c->frame->visible &&
/* check the desktop, this is done during desktop
switching and windows are shown/hidden status is not
reliable */
(c->desktop == screen_desktop ||
c->desktop == DESKTOP_ALL) &&
/* ignore all animating windows */
!frame_iconify_animating(c->frame) &&
RECT_CONTAINS(c->frame->area, x, y))
{
ret = c;
break;
}
}
}
ret = client_at_point(x, y);
}
return ret;
}
Expand Down
5 changes: 5 additions & 0 deletions openbox/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,11 @@ void client_set_layer(ObClient *self, gint layer);

guint client_monitor(ObClient *self);

/*
Gets the client under the given point, factored out of the client_under_pointer code so it can be re-used
*/
ObClient* client_at_point(gint x, gint y);

ObClient* client_under_pointer(void);

gboolean client_has_group_siblings(ObClient *self);
Expand Down