Merge branch 'backport'
This commit is contained in:
commit
f55ae9e569
37 changed files with 830 additions and 776 deletions
41
CHANGELOG
41
CHANGELOG
|
@ -1,3 +1,44 @@
|
|||
3.4.4:
|
||||
* Updated Traditional Chinese translation
|
||||
* Updated Norwegian translation
|
||||
* Fix for MoveToEdge skipping edges sometimes
|
||||
* Let you specify the vertical and horizontal padding independently in themes
|
||||
* Fix so that if you select an omnipresent window on another desktop in the
|
||||
client list menus, it will go to that desktop
|
||||
* Make the GrowToEdge action shrink once there is no more room to grow,
|
||||
similar to in 3.4.2, but shrinking to edges as well
|
||||
* Move the Send To and Layers submenus to the top of the client menu
|
||||
* Fix race causing omnipresent windows to lose focus when switching desktops
|
||||
very quickly
|
||||
* Don't focus new windows on other desktops if they aren't related to the
|
||||
currently focused window
|
||||
* Add corner resizing areas in the inner client border (Fixes themes such
|
||||
as Onyx)
|
||||
* New focus stealing prevention that is smart and not intrusive and not
|
||||
annoying
|
||||
* Revert a small change in 3.4.3 that caused windows to be placed funny in
|
||||
Smart placement when there was a dock or something on the side of the
|
||||
screen
|
||||
* Show a notification when switching desktops
|
||||
* Fix for delayed focus-follows-mouse interrupting move/resize or menus
|
||||
* Make screen edge warp keep warping without having the move the mouse 1
|
||||
pixel
|
||||
* Fix for resizing terminals in the top/left sides getting a little confused
|
||||
* Fix to keep oldschool (Non-EWMH) fullscreen windows from being moved and
|
||||
resized inside of the struts (Fixes Acroread)
|
||||
* Accept the <command> option for the Restart command, similar to the Execute
|
||||
action
|
||||
* Don't make clicking on dock apps sometimes act like clicking on the root
|
||||
window (Don't propogate button events up)
|
||||
* Fix a bug introduced in 3.4.3 which caused the Windows key as a modifier
|
||||
for bindings to not work properly
|
||||
* Let windows skip across monitors in a Xinerama setup when using MoveToEdge
|
||||
or Shift-arrow in an interactive move
|
||||
* Make move and resize take the dock into account for resistance
|
||||
* Raise new windows when it makes sense, when they aren't being focused
|
||||
* Change default config to use click events for mouse wheel bindings instead
|
||||
of presses
|
||||
|
||||
3.4.3:
|
||||
* Add Ukrainian translation
|
||||
* Updated translations:
|
||||
|
|
|
@ -249,8 +249,6 @@ openbox_openbox_SOURCES = \
|
|||
openbox/popup.h \
|
||||
openbox/prop.c \
|
||||
openbox/prop.h \
|
||||
openbox/propwin.c \
|
||||
openbox/propwin.h \
|
||||
openbox/resist.c \
|
||||
openbox/resist.h \
|
||||
openbox/screen.c \
|
||||
|
|
|
@ -116,6 +116,9 @@
|
|||
<name>desktop 2</name>
|
||||
-->
|
||||
</names>
|
||||
<popupTime>875</popupTime>
|
||||
<!-- The number of milliseconds to show the popup for when switching
|
||||
desktops. Set this to 0 to disable the popup. -->
|
||||
</desktops>
|
||||
|
||||
<resize>
|
||||
|
@ -261,9 +264,9 @@
|
|||
<doubleClickTime>200</doubleClickTime>
|
||||
<!-- in milliseconds (1000 = 1 second) -->
|
||||
<screenEdgeWarpTime>400</screenEdgeWarpTime>
|
||||
<!-- time before changing desktops when the pointer touches the edge of the
|
||||
screen while moving a window, in milliseconds (1000 = 1 second),
|
||||
0 disables warping -->
|
||||
<!-- Time before changing desktops when the pointer touches the edge of the
|
||||
screen while moving a window, in milliseconds (1000 = 1 second).
|
||||
Set this to 0 to disable warping -->
|
||||
|
||||
<context name="Frame">
|
||||
<mousebind button="A-Left" action="Press">
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
<xsd:element maxOccurs="unbounded" name="name" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element minOccurs="0" name="popupTime" type="xsd:integer"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="resize">
|
||||
<xsd:element minOccurs="0" name="drawContents" type="ob:bool"/>
|
||||
|
|
|
@ -132,10 +132,8 @@ static gboolean run_func(ObActionsData *data, gpointer options)
|
|||
d = o->abs.desktop;
|
||||
break;
|
||||
case RELATIVE:
|
||||
d = screen_cycle_desktop(o->rel.dir,
|
||||
o->rel.wrap,
|
||||
o->rel.linear,
|
||||
FALSE, TRUE, FALSE);
|
||||
d = screen_find_desktop(screen_desktop,
|
||||
o->rel.dir, o->rel.wrap, o->rel.linear);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,39 +57,89 @@ static void free_func(gpointer options)
|
|||
g_free(o);
|
||||
}
|
||||
|
||||
static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h)
|
||||
{
|
||||
gint realw, realh, lw, lh;
|
||||
|
||||
realw = w;
|
||||
realh = h;
|
||||
client_try_configure(data->client, &x, &y, &realw, &realh,
|
||||
&lw, &lh, TRUE);
|
||||
/* if it's going to be resized smaller than it intended, don't
|
||||
move the window over */
|
||||
if (x != data->client->area.x) x += w - realw;
|
||||
if (y != data->client->area.y) y += h - realh;
|
||||
|
||||
if (x != data->client->area.x || y != data->client->area.y ||
|
||||
realw != data->client->area.width ||
|
||||
realh != data->client->area.height)
|
||||
{
|
||||
actions_client_move(data, TRUE);
|
||||
client_move_resize(data->client, x, y, realw, realh);
|
||||
actions_client_move(data, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Always return FALSE because its not interactive */
|
||||
static gboolean run_func(ObActionsData *data, gpointer options)
|
||||
{
|
||||
Options *o = options;
|
||||
gint x, y, w, h;
|
||||
ObDirection opp;
|
||||
gint half;
|
||||
|
||||
if (data->client) {
|
||||
gint x, y, w, h, realw, realh, lw, lh;
|
||||
|
||||
if (!data->client ||
|
||||
/* don't allow vertical resize if shaded */
|
||||
if (o->dir != OB_DIRECTION_NORTH || o->dir != OB_DIRECTION_SOUTH ||
|
||||
!data->client->shaded)
|
||||
{
|
||||
client_find_resize_directional(data->client, o->dir, TRUE,
|
||||
&x, &y, &w, &h);
|
||||
realw = w;
|
||||
realh = h;
|
||||
client_try_configure(data->client, &x, &y, &realw, &realh,
|
||||
&lw, &lh, TRUE);
|
||||
/* if it's going to be resized smaller than it intended, don't
|
||||
move the window over */
|
||||
if (x != data->client->area.x) x += w - realw;
|
||||
if (y != data->client->area.y) y += h - realh;
|
||||
|
||||
if (x != data->client->area.x || y != data->client->area.y ||
|
||||
w != data->client->area.width ||
|
||||
h != data->client->area.height)
|
||||
{
|
||||
actions_client_move(data, TRUE);
|
||||
client_move_resize(data->client, x, y, realw, realh);
|
||||
actions_client_move(data, FALSE);
|
||||
}
|
||||
}
|
||||
((o->dir == OB_DIRECTION_NORTH || o->dir == OB_DIRECTION_SOUTH) &&
|
||||
data->client->shaded))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* try grow */
|
||||
client_find_resize_directional(data->client, o->dir, TRUE,
|
||||
&x, &y, &w, &h);
|
||||
if (do_grow(data, x, y, w, h))
|
||||
return FALSE;
|
||||
|
||||
/* we couldn't grow, so try shrink! */
|
||||
opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
|
||||
(o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
|
||||
(o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
|
||||
OB_DIRECTION_EAST)));
|
||||
client_find_resize_directional(data->client, opp, FALSE,
|
||||
&x, &y, &w, &h);
|
||||
switch (opp) {
|
||||
case OB_DIRECTION_NORTH:
|
||||
half = data->client->area.y + data->client->area.height / 2;
|
||||
if (y > half) {
|
||||
h += y - half;
|
||||
y = half;
|
||||
}
|
||||
break;
|
||||
case OB_DIRECTION_SOUTH:
|
||||
half = data->client->area.height / 2;
|
||||
if (h < half)
|
||||
h = half;
|
||||
break;
|
||||
case OB_DIRECTION_WEST:
|
||||
half = data->client->area.x + data->client->area.width / 2;
|
||||
if (x > half) {
|
||||
w += x - half;
|
||||
x = half;
|
||||
}
|
||||
break;
|
||||
case OB_DIRECTION_EAST:
|
||||
half = data->client->area.width / 2;
|
||||
if (w < half)
|
||||
w = half;
|
||||
break;
|
||||
default: g_assert_not_reached();
|
||||
}
|
||||
if (do_grow(data, x, y, w, h))
|
||||
return FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
|
|||
|
||||
o = g_new0(Options, 1);
|
||||
|
||||
if ((n = parse_find_node("execute", node))) {
|
||||
if ((n = parse_find_node("command", node)) ||
|
||||
(n = parse_find_node("execute", node)))
|
||||
{
|
||||
gchar *s = parse_string(doc, n);
|
||||
o->cmd = parse_expand_tilde(s);
|
||||
g_free(s);
|
||||
|
|
|
@ -12,6 +12,6 @@ void action_unfocus_startup()
|
|||
static gboolean run_func(ObActionsData *data, gpointer options)
|
||||
{
|
||||
if (data->client && data->client == focus_client)
|
||||
focus_fallback(FALSE, FALSE, TRUE);
|
||||
focus_fallback(FALSE, FALSE, TRUE, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
284
openbox/client.c
284
openbox/client.c
|
@ -32,7 +32,6 @@
|
|||
#include "event.h"
|
||||
#include "grab.h"
|
||||
#include "focus.h"
|
||||
#include "propwin.h"
|
||||
#include "stacking.h"
|
||||
#include "openbox.h"
|
||||
#include "group.h"
|
||||
|
@ -213,8 +212,9 @@ void client_manage(Window window)
|
|||
XWMHints *wmhint;
|
||||
gboolean activate = FALSE;
|
||||
ObAppSettings *settings;
|
||||
gint placex, placey, placew, placeh;
|
||||
gboolean transient = FALSE;
|
||||
Rect place, *monitor;
|
||||
Time launch_time, map_time;
|
||||
|
||||
grab_server(TRUE);
|
||||
|
||||
|
@ -253,6 +253,8 @@ void client_manage(Window window)
|
|||
|
||||
ob_debug("Managing window: 0x%lx\n", window);
|
||||
|
||||
map_time = event_get_server_time();
|
||||
|
||||
/* choose the events we want to receive on the CLIENT window */
|
||||
attrib_set.event_mask = CLIENT_EVENTMASK;
|
||||
attrib_set.do_not_propagate_mask = CLIENT_NOPROPAGATEMASK;
|
||||
|
@ -269,7 +271,6 @@ void client_manage(Window window)
|
|||
self->wmstate = WithdrawnState; /* make sure it gets updated first time */
|
||||
self->gravity = NorthWestGravity;
|
||||
self->desktop = screen_num_desktops; /* always an invalid value */
|
||||
self->user_time = focus_client ? focus_client->user_time : CurrentTime;
|
||||
|
||||
/* get all the stuff off the window */
|
||||
client_get_all(self, TRUE);
|
||||
|
@ -300,10 +301,8 @@ void client_manage(Window window)
|
|||
/* now we have all of the window's information so we can set this up */
|
||||
client_setup_decor_and_functions(self, FALSE);
|
||||
|
||||
{
|
||||
Time t = sn_app_started(self->startup_id, self->class);
|
||||
if (t) self->user_time = t;
|
||||
}
|
||||
/* tell startup notification that this app started */
|
||||
launch_time = sn_app_started(self->startup_id, self->class);
|
||||
|
||||
/* do this after we have a frame.. it uses the frame to help determine the
|
||||
WM_STATE to apply. */
|
||||
|
@ -337,10 +336,8 @@ void client_manage(Window window)
|
|||
frame_adjust_client_area(self->frame);
|
||||
|
||||
/* where the frame was placed is where the window was originally */
|
||||
placex = self->area.x;
|
||||
placey = self->area.y;
|
||||
placew = self->area.width;
|
||||
placeh = self->area.height;
|
||||
place = self->area;
|
||||
monitor = screen_physical_area_monitor(screen_find_monitor(&place));
|
||||
|
||||
/* figure out placement for the window if the window is new */
|
||||
if (ob_state() == OB_STATE_RUNNING) {
|
||||
|
@ -350,7 +347,7 @@ void client_manage(Window window)
|
|||
(self->positioned == USPosition ? "user specified" :
|
||||
(self->positioned == (PPosition | USPosition) ?
|
||||
"program + user specified" :
|
||||
"BADNESS !?")))), placex, placey);
|
||||
"BADNESS !?")))), place.x, place.y);
|
||||
|
||||
ob_debug("Sized: %s @ %d %d\n",
|
||||
(!self->sized ? "no" :
|
||||
|
@ -358,14 +355,15 @@ void client_manage(Window window)
|
|||
(self->sized == USSize ? "user specified" :
|
||||
(self->sized == (PSize | USSize) ?
|
||||
"program + user specified" :
|
||||
"BADNESS !?")))), placew, placeh);
|
||||
"BADNESS !?")))), place.width, place.height);
|
||||
|
||||
/* splash screens are also returned as TRUE for transient,
|
||||
and so will be forced on screen below */
|
||||
transient = place_client(self, &placex, &placey, settings);
|
||||
transient = place_client(self, &place.x, &place.y, settings);
|
||||
|
||||
/* make sure the window is visible. */
|
||||
client_find_onscreen(self, &placex, &placey, placew, placeh,
|
||||
client_find_onscreen(self, &place.x, &place.y,
|
||||
place.width, place.height,
|
||||
/* non-normal clients has less rules, and
|
||||
windows that are being restored from a
|
||||
session do also. we can assume you want
|
||||
|
@ -385,7 +383,13 @@ void client_manage(Window window)
|
|||
(!((self->positioned & USPosition) ||
|
||||
(settings && settings->pos_given)) &&
|
||||
client_normal(self) &&
|
||||
!self->session)));
|
||||
!self->session &&
|
||||
/* don't move oldschool fullscreen windows to
|
||||
fit inside the struts (fixes Acroread, which
|
||||
makes its fullscreen window fit the screen
|
||||
but it is not USSize'd or USPosition'd) */
|
||||
!(self->decorations == 0 &&
|
||||
RECT_EQUAL(place, *monitor)))));
|
||||
}
|
||||
|
||||
/* if the window isn't user-sized, then make it fit inside
|
||||
|
@ -401,34 +405,34 @@ void client_manage(Window window)
|
|||
(transient ||
|
||||
(!(self->sized & USSize || self->positioned & USPosition) &&
|
||||
client_normal(self) &&
|
||||
!self->session)))
|
||||
!self->session &&
|
||||
/* don't shrink oldschool fullscreen windows to fit inside the
|
||||
struts (fixes Acroread, which makes its fullscreen window
|
||||
fit the screen but it is not USSize'd or USPosition'd) */
|
||||
!(self->decorations == 0 && RECT_EQUAL(place, *monitor)))))
|
||||
{
|
||||
Rect placer;
|
||||
Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &place);
|
||||
|
||||
RECT_SET(placer, placex, placey, placew, placeh);
|
||||
frame_rect_to_frame(self->frame, &placer);
|
||||
|
||||
Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &placer);
|
||||
|
||||
/* shrink by the frame's area */
|
||||
a->width -= self->frame->size.left + self->frame->size.right;
|
||||
a->height -= self->frame->size.top + self->frame->size.bottom;
|
||||
/* get the size of the frame */
|
||||
place.width += self->frame->size.left + self->frame->size.right;
|
||||
place.height += self->frame->size.top + self->frame->size.bottom;
|
||||
|
||||
/* fit the window inside the area */
|
||||
if (placew > a->width || self->area.height > a->height) {
|
||||
placew = MIN(self->area.width, a->width);
|
||||
placeh = MIN(self->area.height, a->height);
|
||||
place.width = MIN(place.width, a->width);
|
||||
place.height = MIN(place.height, a->height);
|
||||
|
||||
ob_debug("setting window size to %dx%d\n", place.width, place.height);
|
||||
|
||||
/* get the size of the client back */
|
||||
place.width -= self->frame->size.left + self->frame->size.right;
|
||||
place.height -= self->frame->size.top + self->frame->size.bottom;
|
||||
|
||||
ob_debug("setting window size to %dx%d\n",
|
||||
self->area.width, self->area.height);
|
||||
}
|
||||
g_free(a);
|
||||
}
|
||||
|
||||
|
||||
ob_debug("placing window 0x%x at %d, %d with size %d x %d. "
|
||||
"some restrictions may apply\n",
|
||||
self->window, placex, placey, placew, placeh);
|
||||
self->window, place.x, place.y, place.width, place.height);
|
||||
if (self->session)
|
||||
ob_debug(" but session requested %d, %d %d x %d instead, "
|
||||
"overriding\n",
|
||||
|
@ -440,20 +444,25 @@ void client_manage(Window window)
|
|||
|
||||
this also places the window
|
||||
*/
|
||||
client_apply_startup_state(self, placex, placey, placew, placeh);
|
||||
client_apply_startup_state(self, place.x, place.y,
|
||||
place.width, place.height);
|
||||
|
||||
g_free(monitor);
|
||||
monitor = NULL;
|
||||
|
||||
if (activate) {
|
||||
guint32 last_time = focus_client ?
|
||||
focus_client->user_time : CurrentTime;
|
||||
gboolean raise = FALSE;
|
||||
|
||||
/* This is focus stealing prevention */
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Want to focus new window 0x%x with time %u "
|
||||
"(last time %u)\n",
|
||||
self->window, self->user_time, last_time);
|
||||
"Want to focus new window 0x%x at time %u "
|
||||
"launched at %u (last user interaction time %u)\n",
|
||||
self->window, map_time, launch_time,
|
||||
event_last_user_time);
|
||||
|
||||
if (menu_frame_visible || moveresize_in_progress) {
|
||||
activate = FALSE;
|
||||
raise = TRUE;
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Not focusing the window because the user is inside "
|
||||
"an Openbox menu or is move/resizing a window and "
|
||||
|
@ -462,12 +471,13 @@ void client_manage(Window window)
|
|||
|
||||
/* if it's on another desktop */
|
||||
else if (!(self->desktop == screen_desktop ||
|
||||
self->desktop == DESKTOP_ALL) &&
|
||||
/* the timestamp is from before you changed desktops */
|
||||
self->user_time && screen_desktop_user_time &&
|
||||
!event_time_after(self->user_time, screen_desktop_user_time))
|
||||
self->desktop == DESKTOP_ALL) &&
|
||||
/* the timestamp is from before you changed desktops */
|
||||
launch_time && screen_desktop_user_time &&
|
||||
!event_time_after(launch_time, screen_desktop_user_time))
|
||||
{
|
||||
activate = FALSE;
|
||||
raise = TRUE;
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Not focusing the window because its on another "
|
||||
"desktop\n");
|
||||
|
@ -476,26 +486,25 @@ void client_manage(Window window)
|
|||
else if (focus_client && client_search_focus_tree_full(self) == NULL &&
|
||||
client_search_focus_group_full(self) == NULL)
|
||||
{
|
||||
/* If time stamp is old, don't steal focus */
|
||||
if (self->user_time && last_time &&
|
||||
!event_time_after(self->user_time, last_time))
|
||||
/* If the user is working in another window right now, then don't
|
||||
steal focus */
|
||||
if (event_last_user_time && launch_time &&
|
||||
event_time_after(event_last_user_time, launch_time) &&
|
||||
event_last_user_time != launch_time &&
|
||||
event_time_after(event_last_user_time,
|
||||
map_time - OB_EVENT_USER_TIME_DELAY))
|
||||
{
|
||||
activate = FALSE;
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Not focusing the window because the time is "
|
||||
"too old\n");
|
||||
"Not focusing the window because the user is "
|
||||
"working in another window\n");
|
||||
}
|
||||
/* If its a transient (and parents aren't focused) and the time
|
||||
is ambiguous (either the current focus target doesn't have
|
||||
a timestamp, or they are the same (we probably inherited it
|
||||
from them) */
|
||||
else if (client_has_parent(self) &&
|
||||
(!last_time || self->user_time == last_time))
|
||||
{
|
||||
/* If its a transient (and its parents aren't focused) */
|
||||
else if (client_has_parent(self)) {
|
||||
activate = FALSE;
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Not focusing the window because it is a "
|
||||
"transient, and the time is very ambiguous\n");
|
||||
"transient, and its relatives aren't focused\n");
|
||||
}
|
||||
/* Don't steal focus from globally active clients.
|
||||
I stole this idea from KWin. It seems nice.
|
||||
|
@ -512,20 +521,33 @@ void client_manage(Window window)
|
|||
anyway */
|
||||
else if (client_focus_target(self) != self) {
|
||||
activate = FALSE;
|
||||
raise = TRUE;
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Not focusing the window because another window "
|
||||
"would get the focus anyway\n");
|
||||
}
|
||||
else if (!(self->desktop == screen_desktop ||
|
||||
self->desktop == DESKTOP_ALL))
|
||||
{
|
||||
activate = FALSE;
|
||||
raise = TRUE;
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Not focusing the window because it is on "
|
||||
"another desktop and no relatives are focused ");
|
||||
}
|
||||
}
|
||||
|
||||
if (!activate) {
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Focus stealing prevention activated for %s with "
|
||||
"time %u (last time %u)\n",
|
||||
self->title, self->user_time, last_time);
|
||||
"Focus stealing prevention activated for %s at "
|
||||
"time %u (last user interactioon time %u)\n",
|
||||
self->title, map_time, event_last_user_time);
|
||||
/* if the client isn't focused, then hilite it so the user
|
||||
knows it is there */
|
||||
client_hilite(self, TRUE);
|
||||
/* we may want to raise it even tho we're not activating it */
|
||||
if (raise && !client_restore_session_stacking(self))
|
||||
stacking_raise(CLIENT_AS_WINDOW(self));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -653,9 +675,6 @@ void client_unmanage(ObClient *self)
|
|||
/* remove the window from our save set */
|
||||
XChangeSaveSet(ob_display, self->window, SetModeDelete);
|
||||
|
||||
/* kill the property windows */
|
||||
propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self);
|
||||
|
||||
/* update the focus lists */
|
||||
focus_order_remove(self);
|
||||
if (client_focused(self)) {
|
||||
|
@ -1095,9 +1114,6 @@ static void client_get_all(ObClient *self, gboolean real)
|
|||
client_get_colormap(self);
|
||||
client_update_strut(self);
|
||||
client_update_icons(self);
|
||||
client_update_user_time_window(self);
|
||||
if (!self->user_time_window) /* check if this would have been called */
|
||||
client_update_user_time(self);
|
||||
client_update_icon_geometry(self);
|
||||
}
|
||||
|
||||
|
@ -2098,62 +2114,6 @@ void client_update_icons(ObClient *self)
|
|||
frame_adjust_icon(self->frame);
|
||||
}
|
||||
|
||||
void client_update_user_time(ObClient *self)
|
||||
{
|
||||
guint32 time;
|
||||
gboolean got = FALSE;
|
||||
|
||||
if (self->user_time_window)
|
||||
got = PROP_GET32(self->user_time_window,
|
||||
net_wm_user_time, cardinal, &time);
|
||||
if (!got)
|
||||
got = PROP_GET32(self->window, net_wm_user_time, cardinal, &time);
|
||||
|
||||
if (got) {
|
||||
/* we set this every time, not just when it grows, because in practice
|
||||
sometimes time goes backwards! (ntpdate.. yay....) so.. if it goes
|
||||
backward we don't want all windows to stop focusing. we'll just
|
||||
assume noone is setting times older than the last one, cuz that
|
||||
would be pretty stupid anyways
|
||||
*/
|
||||
self->user_time = time;
|
||||
|
||||
/*ob_debug("window %s user time %u\n", self->title, time);*/
|
||||
}
|
||||
}
|
||||
|
||||
void client_update_user_time_window(ObClient *self)
|
||||
{
|
||||
guint32 w;
|
||||
|
||||
if (!PROP_GET32(self->window, net_wm_user_time_window, window, &w))
|
||||
w = None;
|
||||
|
||||
if (w != self->user_time_window) {
|
||||
/* remove the old window */
|
||||
propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self);
|
||||
self->user_time_window = None;
|
||||
|
||||
if (self->group && self->group->leader == w) {
|
||||
ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its "
|
||||
"_NET_WM_USER_TYPE_WINDOW to its group leader\n");
|
||||
/* do it anyways..? */
|
||||
}
|
||||
else if (w == self->window) {
|
||||
ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its "
|
||||
"_NET_WM_USER_TIME_WINDOW to itself\n");
|
||||
w = None; /* don't do it */
|
||||
}
|
||||
|
||||
/* add the new window */
|
||||
propwin_add(w, OB_PROPWIN_USER_TIME, self);
|
||||
self->user_time_window = w;
|
||||
|
||||
/* and update from it */
|
||||
client_update_user_time(self);
|
||||
}
|
||||
}
|
||||
|
||||
void client_update_icon_geometry(ObClient *self)
|
||||
{
|
||||
guint num;
|
||||
|
@ -3635,34 +3595,7 @@ static void client_present(ObClient *self, gboolean here, gboolean raise,
|
|||
void client_activate(ObClient *self, gboolean here, gboolean raise,
|
||||
gboolean unshade, gboolean user)
|
||||
{
|
||||
guint32 last_time = focus_client ? focus_client->user_time : CurrentTime;
|
||||
gboolean allow = FALSE;
|
||||
|
||||
/* if the currently focused app doesn't set a user_time, then it can't
|
||||
benefit from any focus stealing prevention.
|
||||
|
||||
if the timestamp is missing in the request then let it go through
|
||||
even if it is source=app, because EVERY APPLICATION DOES THIS because
|
||||
GTK IS VERY BUGGY AND HARDCODES source=application... WHY!?
|
||||
*/
|
||||
if (!last_time || !event_curtime)
|
||||
allow = TRUE;
|
||||
/* otherwise, if they didn't give a time stamp or if it is too old, they
|
||||
don't get focus */
|
||||
else
|
||||
allow = event_time_after(event_curtime, last_time);
|
||||
|
||||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Want to activate window 0x%x with time %u (last time %u), "
|
||||
"source=%s allowing? %d\n",
|
||||
self->window, event_curtime, last_time,
|
||||
(user ? "user" : "application"), allow);
|
||||
|
||||
if (allow)
|
||||
client_present(self, here, raise, unshade);
|
||||
else
|
||||
/* don't focus it but tell the user it wants attention */
|
||||
client_hilite(self, TRUE);
|
||||
client_present(self, here, raise, unshade);
|
||||
}
|
||||
|
||||
static void client_bring_windows_recursive(ObClient *self,
|
||||
|
@ -3872,7 +3805,7 @@ static void detect_edge(Rect area, ObDirection dir,
|
|||
gint edge_start, edge_size, head, tail;
|
||||
gboolean skip_head = FALSE, skip_tail = FALSE;
|
||||
|
||||
switch(dir) {
|
||||
switch (dir) {
|
||||
case OB_DIRECTION_NORTH:
|
||||
case OB_DIRECTION_SOUTH:
|
||||
edge_start = area.x;
|
||||
|
@ -3892,7 +3825,7 @@ static void detect_edge(Rect area, ObDirection dir,
|
|||
edge_start, edge_size))
|
||||
return;
|
||||
|
||||
switch(dir) {
|
||||
switch (dir) {
|
||||
case OB_DIRECTION_NORTH:
|
||||
head = RECT_BOTTOM(area);
|
||||
tail = RECT_TOP(area);
|
||||
|
@ -3901,38 +3834,54 @@ static void detect_edge(Rect area, ObDirection dir,
|
|||
head = RECT_TOP(area);
|
||||
tail = RECT_BOTTOM(area);
|
||||
break;
|
||||
case OB_DIRECTION_EAST:
|
||||
head = RECT_LEFT(area);
|
||||
tail = RECT_RIGHT(area);
|
||||
break;
|
||||
case OB_DIRECTION_WEST:
|
||||
head = RECT_RIGHT(area);
|
||||
tail = RECT_LEFT(area);
|
||||
break;
|
||||
case OB_DIRECTION_EAST:
|
||||
head = RECT_LEFT(area);
|
||||
tail = RECT_RIGHT(area);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
switch(dir) {
|
||||
switch (dir) {
|
||||
case OB_DIRECTION_NORTH:
|
||||
case OB_DIRECTION_WEST:
|
||||
/* check if our window is past the head of this window */
|
||||
if (my_head <= head + 1)
|
||||
skip_head = TRUE;
|
||||
/* check if our window's tail is past the tail of this window */
|
||||
if (my_head + my_size - 1 <= tail)
|
||||
skip_tail = TRUE;
|
||||
if (head < *dest)
|
||||
/* check if the head of this window is closer than the previously
|
||||
chosen edge (take into account that the previously chosen
|
||||
edge might have been a tail, not a head) */
|
||||
if (head + (*near_edge ? 0 : my_size) < *dest)
|
||||
skip_head = TRUE;
|
||||
if (tail - my_size < *dest)
|
||||
/* check if the tail of this window is closer than the previously
|
||||
chosen edge (take into account that the previously chosen
|
||||
edge might have been a head, not a tail) */
|
||||
if (tail - (!*near_edge ? 0 : my_size) < *dest)
|
||||
skip_tail = TRUE;
|
||||
break;
|
||||
case OB_DIRECTION_SOUTH:
|
||||
case OB_DIRECTION_EAST:
|
||||
/* check if our window is past the head of this window */
|
||||
if (my_head >= head - 1)
|
||||
skip_head = TRUE;
|
||||
/* check if our window's tail is past the tail of this window */
|
||||
if (my_head - my_size + 1 >= tail)
|
||||
skip_tail = TRUE;
|
||||
if (head > *dest)
|
||||
/* check if the head of this window is closer than the previously
|
||||
chosen edge (take into account that the previously chosen
|
||||
edge might have been a tail, not a head) */
|
||||
if (head - (*near_edge ? 0 : my_size) > *dest)
|
||||
skip_head = TRUE;
|
||||
if (tail + my_size > *dest)
|
||||
/* check if the tail of this window is closer than the previously
|
||||
chosen edge (take into account that the previously chosen
|
||||
edge might have been a head, not a tail) */
|
||||
if (tail + (!*near_edge ? 0 : my_size) > *dest)
|
||||
skip_tail = TRUE;
|
||||
break;
|
||||
default:
|
||||
|
@ -3951,7 +3900,6 @@ static void detect_edge(Rect area, ObDirection dir,
|
|||
*dest = tail;
|
||||
*near_edge = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void client_find_edge_directional(ObClient *self, ObDirection dir,
|
||||
|
@ -3969,27 +3917,27 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
|
|||
mon = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR,
|
||||
&self->frame->area);
|
||||
|
||||
switch(dir) {
|
||||
switch (dir) {
|
||||
case OB_DIRECTION_NORTH:
|
||||
if (my_head >= RECT_TOP(*mon))
|
||||
if (my_head >= RECT_TOP(*mon) + 1)
|
||||
edge = RECT_TOP(*mon) - 1;
|
||||
else
|
||||
edge = RECT_TOP(*a) - 1;
|
||||
break;
|
||||
case OB_DIRECTION_SOUTH:
|
||||
if (my_head <= RECT_BOTTOM(*mon))
|
||||
if (my_head <= RECT_BOTTOM(*mon) - 1)
|
||||
edge = RECT_BOTTOM(*mon) + 1;
|
||||
else
|
||||
edge = RECT_BOTTOM(*a) + 1;
|
||||
break;
|
||||
case OB_DIRECTION_EAST:
|
||||
if (my_head <= RECT_RIGHT(*mon))
|
||||
if (my_head <= RECT_RIGHT(*mon) - 1)
|
||||
edge = RECT_RIGHT(*mon) + 1;
|
||||
else
|
||||
edge = RECT_RIGHT(*a) + 1;
|
||||
break;
|
||||
case OB_DIRECTION_WEST:
|
||||
if (my_head >= RECT_LEFT(*mon))
|
||||
if (my_head >= RECT_LEFT(*mon) + 1)
|
||||
edge = RECT_LEFT(*mon) - 1;
|
||||
else
|
||||
edge = RECT_LEFT(*a) - 1;
|
||||
|
@ -4001,7 +3949,7 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
|
|||
*dest = edge;
|
||||
*near_edge = TRUE;
|
||||
|
||||
for(it = client_list; it; it = g_list_next(it)) {
|
||||
for (it = client_list; it; it = g_list_next(it)) {
|
||||
ObClient *cur = it->data;
|
||||
|
||||
/* skip windows to not bump into */
|
||||
|
|
|
@ -289,15 +289,9 @@ struct _ObClient
|
|||
|
||||
/*! Where the window should iconify to/from */
|
||||
Rect icon_geometry;
|
||||
|
||||
/*! The time when the client last received user interaction */
|
||||
guint32 user_time;
|
||||
/*! A separate window for the client to update it's user_time on */
|
||||
Window user_time_window;
|
||||
};
|
||||
|
||||
extern GList *client_list;
|
||||
extern GHashTable *client_user_time_window_map;
|
||||
|
||||
void client_startup(gboolean reconfig);
|
||||
void client_shutdown(gboolean reconfig);
|
||||
|
@ -606,10 +600,6 @@ void client_update_title(ObClient *self);
|
|||
void client_update_strut(ObClient *self);
|
||||
/*! Updates the window's icons */
|
||||
void client_update_icons(ObClient *self);
|
||||
/*! Updates the window's user time */
|
||||
void client_update_user_time(ObClient *self);
|
||||
/*! Updates the window's user time window */
|
||||
void client_update_user_time_window(ObClient *self);
|
||||
/*! Updates the window's icon geometry (where to iconify to/from) */
|
||||
void client_update_icon_geometry(ObClient *self);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
ObMenu *combined_menu;
|
||||
|
||||
#define CLIENT -1
|
||||
#define SEPARATOR -1
|
||||
#define ADD_DESKTOP -2
|
||||
#define REMOVE_DESKTOP -3
|
||||
|
||||
|
@ -49,7 +49,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
|
|||
gboolean empty = TRUE;
|
||||
gboolean onlyiconic = TRUE;
|
||||
|
||||
menu_add_separator(menu, CLIENT, screen_desktop_names[desktop]);
|
||||
menu_add_separator(menu, SEPARATOR, screen_desktop_names[desktop]);
|
||||
for (it = focus_order; it; it = g_list_next(it)) {
|
||||
ObClient *c = it->data;
|
||||
if (client_normal(c) && (!c->skip_taskbar || c->iconic) &&
|
||||
|
@ -61,11 +61,11 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
|
|||
|
||||
if (c->iconic) {
|
||||
gchar *title = g_strdup_printf("(%s)", c->icon_title);
|
||||
e = menu_add_normal(menu, CLIENT, title, NULL, FALSE);
|
||||
e = menu_add_normal(menu, desktop, title, NULL, FALSE);
|
||||
g_free(title);
|
||||
} else {
|
||||
onlyiconic = FALSE;
|
||||
e = menu_add_normal(menu, CLIENT, c->title, NULL, FALSE);
|
||||
e = menu_add_normal(menu, desktop, c->title, NULL, FALSE);
|
||||
}
|
||||
|
||||
if (config_menu_client_list_icons
|
||||
|
@ -87,7 +87,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
|
|||
/* no entries or only iconified windows, so add a
|
||||
* way to go to this desktop without uniconifying a window */
|
||||
if (!empty)
|
||||
menu_add_separator(menu, CLIENT, NULL);
|
||||
menu_add_separator(menu, SEPARATOR, NULL);
|
||||
|
||||
e = menu_add_normal(menu, desktop, _("Go there..."), NULL, TRUE);
|
||||
if (desktop == screen_desktop)
|
||||
|
@ -95,7 +95,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
|
|||
}
|
||||
}
|
||||
|
||||
menu_add_separator(menu, CLIENT, _("Manage desktops"));
|
||||
menu_add_separator(menu, SEPARATOR, _("Manage desktops"));
|
||||
menu_add_normal(menu, ADD_DESKTOP, _("_Add new desktop"), NULL, TRUE);
|
||||
menu_add_normal(menu, REMOVE_DESKTOP, _("_Remove last desktop"),
|
||||
NULL, TRUE);
|
||||
|
@ -106,11 +106,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
|
|||
static void menu_execute(ObMenuEntry *self, ObMenuFrame *f,
|
||||
ObClient *c, guint state, gpointer data)
|
||||
{
|
||||
if (self->id == CLIENT) {
|
||||
if (self->data.normal.data) /* it's set to NULL if its destroyed */
|
||||
client_activate(self->data.normal.data, FALSE, TRUE, TRUE, TRUE);
|
||||
}
|
||||
else if (self->id == ADD_DESKTOP) {
|
||||
if (self->id == ADD_DESKTOP) {
|
||||
screen_add_desktop(FALSE);
|
||||
menu_frame_hide_all();
|
||||
}
|
||||
|
@ -118,8 +114,18 @@ static void menu_execute(ObMenuEntry *self, ObMenuFrame *f,
|
|||
screen_remove_desktop(FALSE);
|
||||
menu_frame_hide_all();
|
||||
}
|
||||
else
|
||||
screen_set_desktop(self->id, TRUE);
|
||||
else {
|
||||
ObClient *t = self->data.normal.data;
|
||||
if (t) { /* it's set to NULL if its destroyed */
|
||||
client_activate(t, FALSE, TRUE, TRUE, TRUE);
|
||||
/* if the window is omnipresent then we need to go to its
|
||||
desktop */
|
||||
if (t->desktop == DESKTOP_ALL)
|
||||
screen_set_desktop(self->id, FALSE);
|
||||
}
|
||||
else
|
||||
screen_set_desktop(self->id, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void client_dest(ObClient *client, gpointer data)
|
||||
|
|
|
@ -37,7 +37,7 @@ typedef struct
|
|||
guint desktop;
|
||||
} DesktopData;
|
||||
|
||||
#define CLIENT -1
|
||||
#define SEPARATOR -1
|
||||
#define ADD_DESKTOP -2
|
||||
#define REMOVE_DESKTOP -3
|
||||
|
||||
|
@ -63,11 +63,11 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
|
|||
|
||||
if (c->iconic) {
|
||||
gchar *title = g_strdup_printf("(%s)", c->icon_title);
|
||||
e = menu_add_normal(menu, CLIENT, title, NULL, FALSE);
|
||||
e = menu_add_normal(menu, d->desktop, title, NULL, FALSE);
|
||||
g_free(title);
|
||||
} else {
|
||||
onlyiconic = FALSE;
|
||||
e = menu_add_normal(menu, CLIENT, c->title, NULL, FALSE);
|
||||
e = menu_add_normal(menu, d->desktop, c->title, NULL, FALSE);
|
||||
}
|
||||
|
||||
if (config_menu_client_list_icons
|
||||
|
@ -88,7 +88,7 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
|
|||
/* no entries or only iconified windows, so add a
|
||||
* way to go to this desktop without uniconifying a window */
|
||||
if (!empty)
|
||||
menu_add_separator(menu, CLIENT, NULL);
|
||||
menu_add_separator(menu, SEPARATOR, NULL);
|
||||
|
||||
e = menu_add_normal(menu, d->desktop, _("Go there..."), NULL, TRUE);
|
||||
if (d->desktop == screen_desktop)
|
||||
|
@ -101,9 +101,13 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data)
|
|||
static void desk_menu_execute(ObMenuEntry *self, ObMenuFrame *f,
|
||||
ObClient *c, guint state, gpointer data)
|
||||
{
|
||||
if (self->id == CLIENT) {
|
||||
if (self->data.normal.data) /* it's set to NULL if its destroyed */
|
||||
client_activate(self->data.normal.data, FALSE, TRUE, TRUE, TRUE);
|
||||
ObClient *t = self->data.normal.data;
|
||||
if (t) { /* it's set to NULL if its destroyed */
|
||||
client_activate(t, FALSE, TRUE, TRUE, TRUE);
|
||||
/* if the window is omnipresent then we need to go to its
|
||||
desktop */
|
||||
if (t->desktop == DESKTOP_ALL)
|
||||
screen_set_desktop(self->id, FALSE);
|
||||
}
|
||||
else
|
||||
screen_set_desktop(self->id, TRUE);
|
||||
|
@ -148,7 +152,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data)
|
|||
desktop_menus = g_slist_append(desktop_menus, submenu);
|
||||
}
|
||||
|
||||
menu_add_separator(menu, CLIENT, NULL);
|
||||
menu_add_separator(menu, SEPARATOR, NULL);
|
||||
menu_add_normal(menu, ADD_DESKTOP, _("_Add new desktop"), NULL, TRUE);
|
||||
menu_add_normal(menu, REMOVE_DESKTOP, _("_Remove last desktop"),
|
||||
NULL, TRUE);
|
||||
|
|
|
@ -377,6 +377,10 @@ void client_menu_startup()
|
|||
menu_set_place_func(menu, client_menu_place);
|
||||
menu_set_execute_func(menu, client_menu_execute);
|
||||
|
||||
menu_add_submenu(menu, CLIENT_SEND_TO, SEND_TO_MENU_NAME);
|
||||
|
||||
menu_add_submenu(menu, CLIENT_LAYER, LAYER_MENU_NAME);
|
||||
|
||||
e = menu_add_normal(menu, CLIENT_RESTORE, _("R_estore"), NULL, TRUE);
|
||||
e->data.normal.mask = ob_rr_theme->max_toggled_mask;
|
||||
e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
|
||||
|
@ -411,12 +415,6 @@ void client_menu_startup()
|
|||
|
||||
menu_add_separator(menu, -1, NULL);
|
||||
|
||||
menu_add_submenu(menu, CLIENT_SEND_TO, SEND_TO_MENU_NAME);
|
||||
|
||||
menu_add_submenu(menu, CLIENT_LAYER, LAYER_MENU_NAME);
|
||||
|
||||
menu_add_separator(menu, -1, NULL);
|
||||
|
||||
e = menu_add_normal(menu, CLIENT_CLOSE, _("_Close"), NULL, TRUE);
|
||||
e->data.normal.mask = ob_rr_theme->close_mask;
|
||||
e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
|
||||
|
|
|
@ -57,6 +57,7 @@ RrFont *config_font_osd;
|
|||
gint config_desktops_num;
|
||||
GSList *config_desktops_names;
|
||||
guint config_screen_firstdesk;
|
||||
guint config_desktop_popup_time;
|
||||
|
||||
gboolean config_resize_redraw;
|
||||
gboolean config_resize_four_corners;
|
||||
|
@ -478,7 +479,7 @@ static void parse_focus(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
|||
if ((n = parse_find_node("followMouse", node)))
|
||||
config_focus_follow = parse_bool(doc, n);
|
||||
if ((n = parse_find_node("focusDelay", node)))
|
||||
config_focus_delay = parse_int(doc, n) * 1000;
|
||||
config_focus_delay = parse_int(doc, n);
|
||||
if ((n = parse_find_node("raiseOnFocus", node)))
|
||||
config_focus_raise = parse_bool(doc, n);
|
||||
if ((n = parse_find_node("focusLast", node)))
|
||||
|
@ -634,6 +635,8 @@ static void parse_desktops(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
|||
nname = parse_find_node("name", nname->next);
|
||||
}
|
||||
}
|
||||
if ((n = parse_find_node("popupTime", node)))
|
||||
config_desktop_popup_time = parse_int(doc, n);
|
||||
}
|
||||
|
||||
static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
||||
|
@ -724,9 +727,9 @@ static void parse_dock(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
|||
if ((n = parse_find_node("autoHide", node)))
|
||||
config_dock_hide = parse_bool(doc, n);
|
||||
if ((n = parse_find_node("hideDelay", node)))
|
||||
config_dock_hide_delay = parse_int(doc, n) * 1000;
|
||||
config_dock_hide_delay = parse_int(doc, n);
|
||||
if ((n = parse_find_node("showDelay", node)))
|
||||
config_dock_show_delay = parse_int(doc, n) * 1000;
|
||||
config_dock_show_delay = parse_int(doc, n);
|
||||
if ((n = parse_find_node("moveButton", node))) {
|
||||
gchar *str = parse_string(doc, n);
|
||||
guint b, s;
|
||||
|
@ -900,6 +903,7 @@ void config_startup(ObParseInst *i)
|
|||
config_desktops_num = 4;
|
||||
config_screen_firstdesk = 1;
|
||||
config_desktops_names = NULL;
|
||||
config_desktop_popup_time = 875;
|
||||
|
||||
parse_register(i, "desktops", parse_desktops, NULL);
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ struct _ObAppSettings
|
|||
extern gboolean config_focus_new;
|
||||
/*! Focus windows when the mouse enters them */
|
||||
extern gboolean config_focus_follow;
|
||||
/*! Timeout for focusing windows on focus follows mouse, in microseconds */
|
||||
/*! Timeout for focusing windows on focus follows mouse, in milliseconds */
|
||||
extern guint config_focus_delay;
|
||||
/*! If windows should automatically be raised when they are focused in
|
||||
focus follows mouse */
|
||||
|
@ -109,9 +109,9 @@ extern gint config_dock_y;
|
|||
extern ObOrientation config_dock_orient;
|
||||
/*! Whether to auto-hide the dock when the pointer is not over it */
|
||||
extern gboolean config_dock_hide;
|
||||
/*! The number of microseconds to wait before hiding the dock */
|
||||
/*! The number of milliseconds to wait before hiding the dock */
|
||||
extern guint config_dock_hide_delay;
|
||||
/*! The number of microseconds to wait before showing the dock */
|
||||
/*! The number of milliseconds to wait before showing the dock */
|
||||
extern guint config_dock_show_delay;
|
||||
/*! The mouse button to be used to move dock apps */
|
||||
extern guint config_dock_app_move_button;
|
||||
|
@ -145,6 +145,8 @@ extern gint config_desktops_num;
|
|||
extern guint config_screen_firstdesk;
|
||||
/*! Names for the desktops */
|
||||
extern GSList *config_desktops_names;
|
||||
/*! Amount of time to show the desktop switch dialog */
|
||||
extern guint config_desktop_popup_time;
|
||||
|
||||
/*! The keycode of the key combo which resets the keybaord chains */
|
||||
extern guint config_keyboard_reset_keycode;
|
||||
|
@ -165,11 +167,11 @@ extern gint config_resist_win;
|
|||
/*! Number of pixels to resist while crossing a screen's edge */
|
||||
extern gint config_resist_edge;
|
||||
|
||||
/*! delay for hiding menu when opening */
|
||||
/*! Delay for hiding menu when opening in milliseconds */
|
||||
extern guint config_menu_hide_delay;
|
||||
/*! Center menus vertically about the parent entry */
|
||||
extern gboolean config_menu_middle;
|
||||
/*! delay before opening a submenu */
|
||||
/*! Delay before opening a submenu in milliseconds */
|
||||
extern guint config_submenu_show_delay;
|
||||
/*! show icons in client_list_menu */
|
||||
extern gboolean config_menu_client_list_icons;
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
|
||||
EnterWindowMask | LeaveWindowMask)
|
||||
#define DOCKAPP_EVENT_MASK (StructureNotifyMask)
|
||||
#define DOCK_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \
|
||||
ButtonMotionMask)
|
||||
|
||||
static ObDock *dock;
|
||||
|
||||
|
@ -83,11 +85,13 @@ void dock_startup(gboolean reconfig)
|
|||
|
||||
attrib.event_mask = DOCK_EVENT_MASK;
|
||||
attrib.override_redirect = True;
|
||||
attrib.do_not_propagate_mask = DOCK_NOPROPAGATEMASK;
|
||||
dock->frame = XCreateWindow(ob_display, RootWindow(ob_display, ob_screen),
|
||||
0, 0, 1, 1, 0,
|
||||
RrDepth(ob_rr_inst), InputOutput,
|
||||
RrVisual(ob_rr_inst),
|
||||
CWOverrideRedirect | CWEventMask,
|
||||
CWOverrideRedirect | CWEventMask |
|
||||
CWDontPropagate,
|
||||
&attrib);
|
||||
dock->a_frame = RrAppearanceCopy(ob_rr_theme->osd_hilite_bg);
|
||||
XSetWindowBorder(ob_display, dock->frame,
|
||||
|
@ -624,15 +628,17 @@ void dock_hide(gboolean hide)
|
|||
{
|
||||
if (!hide) {
|
||||
if (dock->hidden && config_dock_hide) {
|
||||
ob_main_loop_timeout_add(ob_main_loop, config_dock_show_delay,
|
||||
show_timeout, NULL, g_direct_equal, NULL);
|
||||
ob_main_loop_timeout_add(ob_main_loop,
|
||||
config_dock_show_delay * 1000,
|
||||
show_timeout, NULL, g_direct_equal, NULL);
|
||||
} else if (!dock->hidden && config_dock_hide) {
|
||||
ob_main_loop_timeout_remove(ob_main_loop, hide_timeout);
|
||||
}
|
||||
} else {
|
||||
if (!dock->hidden && config_dock_hide) {
|
||||
ob_main_loop_timeout_add(ob_main_loop, config_dock_hide_delay,
|
||||
hide_timeout, NULL, g_direct_equal, NULL);
|
||||
ob_main_loop_timeout_add(ob_main_loop,
|
||||
config_dock_hide_delay * 1000,
|
||||
hide_timeout, NULL, g_direct_equal, NULL);
|
||||
} else if (dock->hidden && config_dock_hide) {
|
||||
ob_main_loop_timeout_remove(ob_main_loop, show_timeout);
|
||||
}
|
||||
|
|
116
openbox/event.c
116
openbox/event.c
|
@ -34,7 +34,6 @@
|
|||
#include "menuframe.h"
|
||||
#include "keyboard.h"
|
||||
#include "modkeys.h"
|
||||
#include "propwin.h"
|
||||
#include "mouse.h"
|
||||
#include "mainloop.h"
|
||||
#include "focus.h"
|
||||
|
@ -90,7 +89,6 @@ static gboolean event_handle_menu(XEvent *e);
|
|||
static void event_handle_dock(ObDock *s, XEvent *e);
|
||||
static void event_handle_dockapp(ObDockApp *app, XEvent *e);
|
||||
static void event_handle_client(ObClient *c, XEvent *e);
|
||||
static void event_handle_user_time_window_clients(GSList *l, XEvent *e);
|
||||
static void event_handle_user_input(ObClient *client, XEvent *e);
|
||||
static gboolean is_enter_focus_event_ignored(XEvent *e);
|
||||
|
||||
|
@ -99,8 +97,8 @@ static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);
|
|||
static gboolean focus_delay_func(gpointer data);
|
||||
static void focus_delay_client_dest(ObClient *client, gpointer data);
|
||||
|
||||
/* The time for the current event being processed */
|
||||
Time event_curtime = CurrentTime;
|
||||
Time event_last_user_time = CurrentTime;
|
||||
|
||||
static gboolean focus_left_screen = FALSE;
|
||||
/*! A list of ObSerialRanges which are to be ignored for mouse enter events */
|
||||
|
@ -238,15 +236,17 @@ static void event_set_curtime(XEvent *e)
|
|||
break;
|
||||
}
|
||||
|
||||
/* watch that if we get an event earlier than the last specified user_time,
|
||||
which can happen if the clock goes backwards, we erase the last
|
||||
specified user_time */
|
||||
if (t && event_last_user_time && event_time_after(event_last_user_time, t))
|
||||
event_last_user_time = CurrentTime;
|
||||
|
||||
event_curtime = t;
|
||||
}
|
||||
|
||||
static void event_hack_mods(XEvent *e)
|
||||
{
|
||||
#ifdef XKB
|
||||
XkbStateRec xkb_state;
|
||||
#endif
|
||||
|
||||
switch (e->type) {
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
|
@ -437,7 +437,6 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
ObDock *dock = NULL;
|
||||
ObDockApp *dockapp = NULL;
|
||||
ObWindow *obwin = NULL;
|
||||
GSList *timewinclients = NULL;
|
||||
XEvent ee, *e;
|
||||
ObEventData *ed = data;
|
||||
|
||||
|
@ -446,27 +445,24 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
e = ⅇ
|
||||
|
||||
window = event_get_window(e);
|
||||
if (e->type != PropertyNotify ||
|
||||
!(timewinclients = propwin_get_clients(window,
|
||||
OB_PROPWIN_USER_TIME)))
|
||||
if ((obwin = g_hash_table_lookup(window_map, &window))) {
|
||||
switch (obwin->type) {
|
||||
case Window_Dock:
|
||||
dock = WINDOW_AS_DOCK(obwin);
|
||||
break;
|
||||
case Window_DockApp:
|
||||
dockapp = WINDOW_AS_DOCKAPP(obwin);
|
||||
break;
|
||||
case Window_Client:
|
||||
client = WINDOW_AS_CLIENT(obwin);
|
||||
break;
|
||||
case Window_Menu:
|
||||
case Window_Internal:
|
||||
/* not to be used for events */
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
if ((obwin = g_hash_table_lookup(window_map, &window))) {
|
||||
switch (obwin->type) {
|
||||
case Window_Dock:
|
||||
dock = WINDOW_AS_DOCK(obwin);
|
||||
break;
|
||||
case Window_DockApp:
|
||||
dockapp = WINDOW_AS_DOCKAPP(obwin);
|
||||
break;
|
||||
case Window_Client:
|
||||
client = WINDOW_AS_CLIENT(obwin);
|
||||
break;
|
||||
case Window_Menu:
|
||||
case Window_Internal:
|
||||
/* not to be used for events */
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
event_set_curtime(e);
|
||||
event_hack_mods(e);
|
||||
|
@ -493,7 +489,7 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
|
||||
focus_left_screen = FALSE;
|
||||
|
||||
focus_fallback(FALSE, config_focus_under_mouse, TRUE);
|
||||
focus_fallback(FALSE, config_focus_under_mouse, TRUE, TRUE);
|
||||
|
||||
/* We don't get a FocusOut for this case, because it's just moving
|
||||
from our Inferior up to us. This happens when iconifying a
|
||||
|
@ -502,10 +498,10 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
/* focus_set_client(NULL) has already been called */
|
||||
client_calc_layer(client);
|
||||
}
|
||||
if (e->xfocus.detail == NotifyPointerRoot ||
|
||||
e->xfocus.detail == NotifyDetailNone ||
|
||||
e->xfocus.detail == NotifyInferior ||
|
||||
e->xfocus.detail == NotifyNonlinear)
|
||||
else if (e->xfocus.detail == NotifyPointerRoot ||
|
||||
e->xfocus.detail == NotifyDetailNone ||
|
||||
e->xfocus.detail == NotifyInferior ||
|
||||
e->xfocus.detail == NotifyNonlinear)
|
||||
{
|
||||
XEvent ce;
|
||||
|
||||
|
@ -545,7 +541,8 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
*/
|
||||
|
||||
if (!focus_left_screen)
|
||||
focus_fallback(FALSE, config_focus_under_mouse, TRUE);
|
||||
focus_fallback(FALSE, config_focus_under_mouse,
|
||||
TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
else if (!client)
|
||||
|
@ -601,7 +598,7 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
ob_debug_type(OB_DEBUG_FOCUS,
|
||||
"Focus went to an unmanaged window 0x%x !\n",
|
||||
ce.xfocus.window);
|
||||
focus_fallback(TRUE, config_focus_under_mouse, TRUE);
|
||||
focus_fallback(TRUE, config_focus_under_mouse, TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -611,8 +608,7 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
section or by focus_fallback */
|
||||
client_calc_layer(client);
|
||||
}
|
||||
} else if (timewinclients)
|
||||
event_handle_user_time_window_clients(timewinclients, e);
|
||||
}
|
||||
else if (client)
|
||||
event_handle_client(client, e);
|
||||
else if (dockapp)
|
||||
|
@ -758,7 +754,7 @@ void event_enter_client(ObClient *client)
|
|||
data->time = event_curtime;
|
||||
|
||||
ob_main_loop_timeout_add(ob_main_loop,
|
||||
config_focus_delay,
|
||||
config_focus_delay * 1000,
|
||||
focus_delay_func,
|
||||
data, focus_delay_cmp, focus_delay_dest);
|
||||
} else {
|
||||
|
@ -770,15 +766,6 @@ void event_enter_client(ObClient *client)
|
|||
}
|
||||
}
|
||||
|
||||
static void event_handle_user_time_window_clients(GSList *l, XEvent *e)
|
||||
{
|
||||
g_assert(e->type == PropertyNotify);
|
||||
if (e->xproperty.atom == prop_atoms.net_wm_user_time) {
|
||||
for (; l; l = g_slist_next(l))
|
||||
client_update_user_time(l->data);
|
||||
}
|
||||
}
|
||||
|
||||
static void event_handle_client(ObClient *client, XEvent *e)
|
||||
{
|
||||
XEvent ce;
|
||||
|
@ -1292,8 +1279,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
|||
(e->xclient.data.l[0] == 2 ? "user" : "INVALID"))));
|
||||
/* XXX make use of data.l[2] !? */
|
||||
if (e->xclient.data.l[0] == 1 || e->xclient.data.l[0] == 2) {
|
||||
event_curtime = e->xclient.data.l[1];
|
||||
if (event_curtime == 0)
|
||||
/* don't use the user's timestamp for client_focus, cuz if it's
|
||||
an old broken timestamp (happens all the time) then focus
|
||||
won't move even though we're trying to move it
|
||||
event_curtime = e->xclient.data.l[1];*/
|
||||
if (e->xclient.data.l[1] == 0)
|
||||
ob_debug_type(OB_DEBUG_APP_BUGS,
|
||||
"_NET_ACTIVE_WINDOW message for window %s is"
|
||||
" missing a timestamp\n", client->title);
|
||||
|
@ -1514,10 +1504,15 @@ static void event_handle_client(ObClient *client, XEvent *e)
|
|||
client_update_icon_geometry(client);
|
||||
}
|
||||
else if (msgtype == prop_atoms.net_wm_user_time) {
|
||||
client_update_user_time(client);
|
||||
}
|
||||
else if (msgtype == prop_atoms.net_wm_user_time_window) {
|
||||
client_update_user_time_window(client);
|
||||
guint32 t;
|
||||
if (client == focus_client &&
|
||||
PROP_GET32(client->window, net_wm_user_time, cardinal, &t) &&
|
||||
t && !event_time_after(t, e->xproperty.time) &&
|
||||
(!event_last_user_time ||
|
||||
event_time_after(t, event_last_user_time)))
|
||||
{
|
||||
event_last_user_time = t;
|
||||
}
|
||||
}
|
||||
#ifdef SYNC
|
||||
else if (msgtype == prop_atoms.net_wm_sync_request_counter) {
|
||||
|
@ -1844,6 +1839,9 @@ static gboolean focus_delay_func(gpointer data)
|
|||
ObFocusDelayData *d = data;
|
||||
Time old = event_curtime;
|
||||
|
||||
/* don't move focus and kill the menu or the move/resize */
|
||||
if (menu_frame_visible || moveresize_in_progress) return FALSE;
|
||||
|
||||
event_curtime = d->time;
|
||||
if (focus_client != d->client) {
|
||||
if (client_focus(d->client) && config_focus_raise)
|
||||
|
@ -1957,3 +1955,15 @@ gboolean event_time_after(Time t1, Time t2)
|
|||
/* t2 is in the first half so t1 has to come after it */
|
||||
return t1 >= t2 && t1 < (t2 + TIME_HALF);
|
||||
}
|
||||
|
||||
Time event_get_server_time()
|
||||
{
|
||||
/* Generate a timestamp */
|
||||
XEvent event;
|
||||
|
||||
XChangeProperty(ob_display, screen_support_win,
|
||||
prop_atoms.wm_class, prop_atoms.string,
|
||||
8, PropModeAppend, NULL, 0);
|
||||
XWindowEvent(ob_display, screen_support_win, PropertyChangeMask, &event);
|
||||
return event.xproperty.time;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,14 @@
|
|||
|
||||
struct _ObClient;
|
||||
|
||||
/*! The amount of time before a window appears that is checked for user input
|
||||
to determine if the user is working in another window */
|
||||
#define OB_EVENT_USER_TIME_DELAY (500) /* 0.5 seconds */
|
||||
|
||||
/*! Time at which the last event with a timestamp occured. */
|
||||
extern Time event_curtime;
|
||||
/*! The last user-interaction time, as given by the clients */
|
||||
extern Time event_last_user_time;
|
||||
|
||||
void event_startup(gboolean reconfig);
|
||||
void event_shutdown(gboolean reconfig);
|
||||
|
@ -50,4 +56,6 @@ void event_halt_focus_delay();
|
|||
comes at the same time or later than t2. */
|
||||
gboolean event_time_after(Time t1, Time t2);
|
||||
|
||||
Time event_get_server_time();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -159,7 +159,7 @@ static ObClient* focus_fallback_target(gboolean allow_refocus,
|
|||
}
|
||||
|
||||
ObClient* focus_fallback(gboolean allow_refocus, gboolean allow_pointer,
|
||||
gboolean allow_omnipresent)
|
||||
gboolean allow_omnipresent, gboolean focus_lost)
|
||||
{
|
||||
ObClient *new;
|
||||
ObClient *old = focus_client;
|
||||
|
@ -167,7 +167,8 @@ ObClient* focus_fallback(gboolean allow_refocus, gboolean allow_pointer,
|
|||
/* unfocus any focused clients.. they can be focused by Pointer events
|
||||
and such, and then when we try focus them, we won't get a FocusIn
|
||||
event at all for them. */
|
||||
focus_nothing();
|
||||
if (focus_lost)
|
||||
focus_nothing();
|
||||
|
||||
new = focus_fallback_target(allow_refocus, allow_pointer,
|
||||
allow_omnipresent, old);
|
||||
|
|
|
@ -46,7 +46,8 @@ void focus_nothing();
|
|||
/*! Call this when you need to focus something! */
|
||||
struct _ObClient* focus_fallback(gboolean allow_refocus,
|
||||
gboolean allow_pointer,
|
||||
gboolean allow_omnipresent);
|
||||
gboolean allow_omnipresent,
|
||||
gboolean focus_lost);
|
||||
|
||||
/*! Add a new client into the focus order */
|
||||
void focus_order_add_new(struct _ObClient *c);
|
||||
|
|
|
@ -130,6 +130,11 @@ ObFrame *frame_new(ObClient *client)
|
|||
self->innerright = createWindow(self->window, NULL, mask, &attrib);
|
||||
self->innerbottom = createWindow(self->window, NULL, mask, &attrib);
|
||||
|
||||
self->innerblb = createWindow(self->innerbottom, NULL, mask, &attrib);
|
||||
self->innerbrb = createWindow(self->innerbottom, NULL, mask, &attrib);
|
||||
self->innerbll = createWindow(self->innerleft, NULL, mask, &attrib);
|
||||
self->innerbrr = createWindow(self->innerright, NULL, mask, &attrib);
|
||||
|
||||
self->title = createWindow(self->window, NULL, mask, &attrib);
|
||||
self->titleleft = createWindow(self->window, NULL, mask, &attrib);
|
||||
self->titletop = createWindow(self->window, NULL, mask, &attrib);
|
||||
|
@ -388,6 +393,9 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
|
|||
/* position/size and map/unmap all the windows */
|
||||
|
||||
if (!fake) {
|
||||
gint innercornerheight =
|
||||
ob_rr_theme->grip_width - self->size.bottom;
|
||||
|
||||
if (self->cbwidth_l) {
|
||||
XMoveResizeWindow(ob_display, self->innerleft,
|
||||
self->size.left - self->cbwidth_l,
|
||||
|
@ -398,6 +406,19 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
|
|||
} else
|
||||
XUnmapWindow(ob_display, self->innerleft);
|
||||
|
||||
if (self->cbwidth_l && innercornerheight > 0) {
|
||||
XMoveResizeWindow(ob_display, self->innerbll,
|
||||
0,
|
||||
self->client->area.height -
|
||||
(ob_rr_theme->grip_width -
|
||||
self->size.bottom),
|
||||
self->cbwidth_l,
|
||||
ob_rr_theme->grip_width - self->size.bottom);
|
||||
|
||||
XMapWindow(ob_display, self->innerbll);
|
||||
} else
|
||||
XUnmapWindow(ob_display, self->innerbll);
|
||||
|
||||
if (self->cbwidth_r) {
|
||||
XMoveResizeWindow(ob_display, self->innerright,
|
||||
self->size.left + self->client->area.width,
|
||||
|
@ -408,6 +429,19 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
|
|||
} else
|
||||
XUnmapWindow(ob_display, self->innerright);
|
||||
|
||||
if (self->cbwidth_r && innercornerheight > 0) {
|
||||
XMoveResizeWindow(ob_display, self->innerbrr,
|
||||
0,
|
||||
self->client->area.height -
|
||||
(ob_rr_theme->grip_width -
|
||||
self->size.bottom),
|
||||
self->cbwidth_r,
|
||||
ob_rr_theme->grip_width - self->size.bottom);
|
||||
|
||||
XMapWindow(ob_display, self->innerbrr);
|
||||
} else
|
||||
XUnmapWindow(ob_display, self->innerbrr);
|
||||
|
||||
if (self->cbwidth_t) {
|
||||
XMoveResizeWindow(ob_display, self->innertop,
|
||||
self->size.left - self->cbwidth_l,
|
||||
|
@ -428,9 +462,26 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
|
|||
self->cbwidth_l + self->cbwidth_r,
|
||||
self->cbwidth_b);
|
||||
|
||||
XMoveResizeWindow(ob_display, self->innerblb,
|
||||
0, 0,
|
||||
ob_rr_theme->grip_width + self->bwidth,
|
||||
self->cbwidth_b);
|
||||
XMoveResizeWindow(ob_display, self->innerbrb,
|
||||
self->client->area.width +
|
||||
self->cbwidth_l + self->cbwidth_r -
|
||||
(ob_rr_theme->grip_width + self->bwidth),
|
||||
0,
|
||||
ob_rr_theme->grip_width + self->bwidth,
|
||||
self->cbwidth_b);
|
||||
|
||||
XMapWindow(ob_display, self->innerbottom);
|
||||
} else
|
||||
XMapWindow(ob_display, self->innerblb);
|
||||
XMapWindow(ob_display, self->innerbrb);
|
||||
} else {
|
||||
XUnmapWindow(ob_display, self->innerbottom);
|
||||
XUnmapWindow(ob_display, self->innerblb);
|
||||
XUnmapWindow(ob_display, self->innerbrb);
|
||||
}
|
||||
|
||||
if (self->bwidth) {
|
||||
gint titlesides;
|
||||
|
@ -598,7 +649,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved,
|
|||
self->bwidth);
|
||||
XMoveResizeWindow(ob_display, self->rgripbottom,
|
||||
self->size.left + self->client->area.width +
|
||||
self->size.right - self->bwidth - sidebwidth -
|
||||
self->size.right - self->bwidth - sidebwidth-
|
||||
ob_rr_theme->grip_width,
|
||||
self->size.top + self->client->area.height +
|
||||
self->size.bottom - self->bwidth,
|
||||
|
@ -876,12 +927,16 @@ static void frame_adjust_cursors(ObFrame *self)
|
|||
XChangeWindowAttributes(ob_display, self->lgripleft, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->lgriptop, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->lgripbottom, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->innerbll, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->innerblb, CWCursor, &a);
|
||||
a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHEAST : OB_CURSOR_NONE);
|
||||
XChangeWindowAttributes(ob_display, self->rgrip, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->handleright, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->rgripright, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->rgriptop, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->rgripbottom, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->innerbrr, CWCursor, &a);
|
||||
XChangeWindowAttributes(ob_display, self->innerbrb, CWCursor, &a);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1539,6 +1594,13 @@ void frame_rect_to_frame(ObFrame *self, Rect *r)
|
|||
frame_client_gravity(self, &r->x, &r->y);
|
||||
}
|
||||
|
||||
void frame_rect_to_client(ObFrame *self, Rect *r)
|
||||
{
|
||||
r->width -= self->size.left + self->size.right;
|
||||
r->height -= self->size.top + self->size.bottom;
|
||||
frame_frame_gravity(self, &r->x, &r->y);
|
||||
}
|
||||
|
||||
static void flash_done(gpointer data)
|
||||
{
|
||||
ObFrame *self = data;
|
||||
|
|
|
@ -120,6 +120,10 @@ struct _ObFrame
|
|||
Window innertop; /*!< For drawing the inner client border */
|
||||
Window innerright; /*!< For drawing the inner client border */
|
||||
Window innerbottom; /*!< For drawing the inner client border */
|
||||
Window innerblb;
|
||||
Window innerbll;
|
||||
Window innerbrb;
|
||||
Window innerbrr;
|
||||
Window backback; /*!< A colored window shown while resizing */
|
||||
Window backfront; /*!< An undrawn-in window, to prevent flashing on
|
||||
unmap */
|
||||
|
@ -237,6 +241,10 @@ void frame_frame_gravity(ObFrame *self, gint *x, gint *y);
|
|||
for the frame, given its current decorations sizes */
|
||||
void frame_rect_to_frame(ObFrame *self, Rect *r);
|
||||
|
||||
/*! Convert a rectangle in frame coordinates/sizes to what it would be for the
|
||||
client, given its current decorations sizes */
|
||||
void frame_rect_to_client(ObFrame *self, Rect *r);
|
||||
|
||||
void frame_flash_start(ObFrame *self);
|
||||
void frame_flash_stop(ObFrame *self);
|
||||
|
||||
|
|
|
@ -59,6 +59,14 @@ void framerender_frame(ObFrame *self)
|
|||
XClearWindow(ob_display, self->innerright);
|
||||
XSetWindowBackground(ob_display, self->innerbottom, px);
|
||||
XClearWindow(ob_display, self->innerbottom);
|
||||
XSetWindowBackground(ob_display, self->innerbll, px);
|
||||
XClearWindow(ob_display, self->innerbll);
|
||||
XSetWindowBackground(ob_display, self->innerbrr, px);
|
||||
XClearWindow(ob_display, self->innerbrr);
|
||||
XSetWindowBackground(ob_display, self->innerblb, px);
|
||||
XClearWindow(ob_display, self->innerblb);
|
||||
XSetWindowBackground(ob_display, self->innerbrb, px);
|
||||
XClearWindow(ob_display, self->innerbrb);
|
||||
|
||||
px = (self->focused ?
|
||||
RrColorPixel(ob_rr_theme->frame_focused_border_color) :
|
||||
|
|
|
@ -35,7 +35,21 @@
|
|||
|
||||
static void set_modkey_mask(guchar mask, KeySym sym);
|
||||
|
||||
static XModifierKeymap *modmap;
|
||||
/* This is 8 lists of keycodes that are bound to the given mod mask.
|
||||
If contains more than the one given to us by X cuz XKB is weird apparently.
|
||||
We will look up all keycodes for a given keysym that is bound to the mask,
|
||||
and add them all here.
|
||||
|
||||
With XKB, you can have a keycode bound to a modifier that isn't in the
|
||||
modifier map somehow. So this means that when we try translate from the
|
||||
KeyRelease to a mod mask, we are unable to. So this array stores *all*
|
||||
the KeyCodes for each KeySym for each KeyCode bound to a mod mask.
|
||||
Confused? Haha...
|
||||
|
||||
ModMask -> n KeyCodes -> n*m KeySyms (up to m for each KeyCode) ->
|
||||
n*m*p KeyCodes (up to p for each KeySym)
|
||||
*/
|
||||
static GArray *modmap[NUM_MASKS];
|
||||
static KeySym *keymap;
|
||||
static gint min_keycode, max_keycode, keysyms_per_keycode;
|
||||
/* This is a bitmask of the different masks for each modifier key */
|
||||
|
@ -48,14 +62,15 @@ static gboolean hyper_l = FALSE;
|
|||
|
||||
void modkeys_startup(gboolean reconfigure)
|
||||
{
|
||||
gint i, j, k;
|
||||
static XModifierKeymap *xmodmap;
|
||||
gint i, j, k, l, m;
|
||||
|
||||
/* reset the keys to not be bound to any masks */
|
||||
for (i = 0; i < OB_MODKEY_NUM_KEYS; ++i)
|
||||
modkeys_keys[i] = 0;
|
||||
|
||||
modmap = XGetModifierMapping(ob_display);
|
||||
g_assert(modmap->max_keypermod > 0);
|
||||
xmodmap = XGetModifierMapping(ob_display);
|
||||
g_assert(xmodmap->max_keypermod > 0);
|
||||
|
||||
XDisplayKeycodes(ob_display, &min_keycode, &max_keycode);
|
||||
keymap = XGetKeyboardMapping(ob_display, min_keycode,
|
||||
|
@ -66,17 +81,31 @@ void modkeys_startup(gboolean reconfigure)
|
|||
|
||||
/* go through each of the modifier masks (eg ShiftMask, CapsMask...) */
|
||||
for (i = 0; i < NUM_MASKS; ++i) {
|
||||
/* reset the modmap list */
|
||||
modmap[i] = g_array_new(FALSE, FALSE, sizeof(KeyCode));
|
||||
|
||||
/* go through each keycode that is bound to the mask */
|
||||
for (j = 0; j < modmap->max_keypermod; ++j) {
|
||||
for (j = 0; j < xmodmap->max_keypermod; ++j) {
|
||||
KeySym sym;
|
||||
/* get a keycode that is bound to the mask (i) */
|
||||
KeyCode keycode = modmap->modifiermap[i*modmap->max_keypermod + j];
|
||||
KeyCode keycode = xmodmap->modifiermap[i*xmodmap->max_keypermod+j];
|
||||
if (keycode) {
|
||||
/* go through each keysym bound to the given keycode */
|
||||
for (k = 0; k < keysyms_per_keycode; ++k) {
|
||||
sym = keymap[(keycode-min_keycode) * keysyms_per_keycode +
|
||||
k];
|
||||
if (sym != NoSymbol) {
|
||||
/* find all keycodes for the given keysym */
|
||||
for (l = min_keycode; l <= max_keycode; ++l)
|
||||
for (m = 0; m < keysyms_per_keycode; ++m)
|
||||
if (keymap[(l-min_keycode) *
|
||||
keysyms_per_keycode + m] == sym)
|
||||
{
|
||||
/* add all keycodes for the keysym to our
|
||||
modmap */
|
||||
g_array_append_val(modmap[i], l);
|
||||
}
|
||||
|
||||
/* bind the key to the mask (e.g. Alt_L => Mod1Mask) */
|
||||
set_modkey_mask(nth_mask(i), sym);
|
||||
}
|
||||
|
@ -89,17 +118,22 @@ void modkeys_startup(gboolean reconfigure)
|
|||
modkeys_keys[OB_MODKEY_KEY_CAPSLOCK] = LockMask;
|
||||
modkeys_keys[OB_MODKEY_KEY_SHIFT] = ShiftMask;
|
||||
modkeys_keys[OB_MODKEY_KEY_CONTROL] = ControlMask;
|
||||
|
||||
XFreeModifiermap(xmodmap);
|
||||
}
|
||||
|
||||
void modkeys_shutdown(gboolean reconfigure)
|
||||
{
|
||||
XFreeModifiermap(modmap);
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < NUM_MASKS; ++i)
|
||||
g_array_free(modmap[i], TRUE);
|
||||
XFree(keymap);
|
||||
}
|
||||
|
||||
guint modkeys_keycode_to_mask(guint keycode)
|
||||
{
|
||||
gint i, j;
|
||||
guint i, j;
|
||||
guint mask = 0;
|
||||
|
||||
if (keycode == NoSymbol) return 0;
|
||||
|
@ -107,9 +141,9 @@ guint modkeys_keycode_to_mask(guint keycode)
|
|||
/* go through each of the modifier masks (eg ShiftMask, CapsMask...) */
|
||||
for (i = 0; i < NUM_MASKS; ++i) {
|
||||
/* go through each keycode that is bound to the mask */
|
||||
for (j = 0; j < modmap->max_keypermod; ++j) {
|
||||
for (j = 0; j < modmap[i]->len; ++j) {
|
||||
/* compare with a keycode that is bound to the mask (i) */
|
||||
if (modmap->modifiermap[i*modmap->max_keypermod + j] == keycode)
|
||||
if (g_array_index(modmap[i], KeyCode, j) == keycode)
|
||||
mask |= nth_mask(i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ static gint cur_x, cur_y, cur_w, cur_h;
|
|||
static guint button;
|
||||
static guint32 corner;
|
||||
static ObDirection edge_warp_dir = -1;
|
||||
static gboolean edge_warp_odd = FALSE;
|
||||
static ObDirection key_resize_edge = -1;
|
||||
#ifdef SYNC
|
||||
static gboolean waiting_for_sync;
|
||||
|
@ -120,6 +121,8 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
|
|||
ObCursor cur;
|
||||
gboolean mv = (cnr == prop_atoms.net_wm_moveresize_move ||
|
||||
cnr == prop_atoms.net_wm_moveresize_move_keyboard);
|
||||
gint up = 1;
|
||||
gint left = 1;
|
||||
|
||||
if (moveresize_in_progress || !c->frame->visible ||
|
||||
!(mv ?
|
||||
|
@ -127,23 +130,28 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
|
|||
(c->functions & OB_CLIENT_FUNC_RESIZE)))
|
||||
return;
|
||||
|
||||
if (cnr == prop_atoms.net_wm_moveresize_size_topleft)
|
||||
if (cnr == prop_atoms.net_wm_moveresize_size_topleft) {
|
||||
cur = OB_CURSOR_NORTHWEST;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_top)
|
||||
up = left = -1;
|
||||
} else if (cnr == prop_atoms.net_wm_moveresize_size_top) {
|
||||
cur = OB_CURSOR_NORTH;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_topright)
|
||||
up = -1;
|
||||
} else if (cnr == prop_atoms.net_wm_moveresize_size_topright) {
|
||||
cur = OB_CURSOR_NORTHEAST;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_right)
|
||||
up = -1;
|
||||
} else if (cnr == prop_atoms.net_wm_moveresize_size_right)
|
||||
cur = OB_CURSOR_EAST;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_bottomright)
|
||||
cur = OB_CURSOR_SOUTHEAST;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_bottom)
|
||||
cur = OB_CURSOR_SOUTH;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_bottomleft)
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_bottomleft) {
|
||||
cur = OB_CURSOR_SOUTHWEST;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_left)
|
||||
left = -1;
|
||||
} else if (cnr == prop_atoms.net_wm_moveresize_size_left) {
|
||||
cur = OB_CURSOR_WEST;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_size_keyboard)
|
||||
left = -1;
|
||||
} else if (cnr == prop_atoms.net_wm_moveresize_size_keyboard)
|
||||
cur = OB_CURSOR_SOUTHEAST;
|
||||
else if (cnr == prop_atoms.net_wm_moveresize_move)
|
||||
cur = OB_CURSOR_MOVE;
|
||||
|
@ -172,8 +180,8 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
|
|||
friendly. you essentially start the resize in the middle of the
|
||||
increment instead of at 0, so you have to move half an increment
|
||||
either way instead of a full increment one and 1 px the other. */
|
||||
start_x = x - (mv ? 0 : c->size_inc.width / 2);
|
||||
start_y = y - (mv ? 0 : c->size_inc.height / 2);
|
||||
start_x = x - (mv ? 0 : left * c->size_inc.width / 2);
|
||||
start_y = y - (mv ? 0 : up * c->size_inc.height / 2);
|
||||
corner = cnr;
|
||||
button = b;
|
||||
key_resize_edge = -1;
|
||||
|
@ -476,12 +484,15 @@ static gboolean edge_warp_delay_func(gpointer data)
|
|||
{
|
||||
guint d;
|
||||
|
||||
d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE);
|
||||
if (d != screen_desktop) screen_set_desktop(d, TRUE);
|
||||
/* only fire every second time. so it's fast the first time, but slower
|
||||
after that */
|
||||
if (edge_warp_odd) {
|
||||
d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE);
|
||||
if (d != screen_desktop) screen_set_desktop(d, TRUE);
|
||||
}
|
||||
edge_warp_odd = !edge_warp_odd;
|
||||
|
||||
edge_warp_dir = -1;
|
||||
|
||||
return FALSE; /* don't repeat */
|
||||
return TRUE; /* do repeat ! */
|
||||
}
|
||||
|
||||
static void do_edge_warp(gint x, gint y)
|
||||
|
@ -515,13 +526,14 @@ static void do_edge_warp(gint x, gint y)
|
|||
}
|
||||
|
||||
if (dir != edge_warp_dir) {
|
||||
if (dir == (ObDirection)-1)
|
||||
cancel_edge_warp();
|
||||
else
|
||||
cancel_edge_warp();
|
||||
if (dir != (ObDirection)-1) {
|
||||
edge_warp_odd = TRUE; /* switch on the first timeout */
|
||||
ob_main_loop_timeout_add(ob_main_loop,
|
||||
config_mouse_screenedgetime * 1000,
|
||||
edge_warp_delay_func,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
edge_warp_dir = dir;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "menuframe.h"
|
||||
#include "grab.h"
|
||||
#include "group.h"
|
||||
#include "propwin.h"
|
||||
#include "config.h"
|
||||
#include "mainloop.h"
|
||||
#include "gettext.h"
|
||||
|
@ -301,7 +300,6 @@ gint main(gint argc, gchar **argv)
|
|||
sn_startup(reconfigure);
|
||||
screen_startup(reconfigure);
|
||||
grab_startup(reconfigure);
|
||||
propwin_startup(reconfigure);
|
||||
group_startup(reconfigure);
|
||||
client_startup(reconfigure);
|
||||
dock_startup(reconfigure);
|
||||
|
@ -363,7 +361,6 @@ gint main(gint argc, gchar **argv)
|
|||
dock_shutdown(reconfigure);
|
||||
client_shutdown(reconfigure);
|
||||
group_shutdown(reconfigure);
|
||||
propwin_shutdown(reconfigure);
|
||||
grab_shutdown(reconfigure);
|
||||
screen_shutdown(reconfigure);
|
||||
focus_cycle_popup_shutdown(reconfigure);
|
||||
|
|
|
@ -316,9 +316,9 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y)
|
|||
|
||||
if (r->width >= c->frame->area.width &&
|
||||
r->height >= c->frame->area.height &&
|
||||
r->width > maxsize)
|
||||
r->width * r->height > maxsize)
|
||||
{
|
||||
maxsize = r->width;
|
||||
maxsize = r->width * r->height;
|
||||
maxit = sit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ void prop_startup()
|
|||
/* CREATE(net_wm_pid, "_NET_WM_PID"); */
|
||||
CREATE(net_wm_allowed_actions, "_NET_WM_ALLOWED_ACTIONS");
|
||||
CREATE(net_wm_user_time, "_NET_WM_USER_TIME");
|
||||
CREATE(net_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW");
|
||||
/* CREATE(net_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW"); */
|
||||
CREATE(kde_net_wm_frame_strut, "_KDE_NET_WM_FRAME_STRUT");
|
||||
CREATE(net_frame_extents, "_NET_FRAME_EXTENTS");
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ typedef struct Atoms {
|
|||
/* Atom net_wm_pid; */
|
||||
Atom net_wm_allowed_actions;
|
||||
Atom net_wm_user_time;
|
||||
Atom net_wm_user_time_window;
|
||||
/* Atom net_wm_user_time_window; */
|
||||
Atom net_frame_extents;
|
||||
|
||||
/* application protocols */
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
|
||||
|
||||
propwin.c for the Openbox window manager
|
||||
Copyright (c) 2006 Mikael Magnusson
|
||||
Copyright (c) 2003-2007 Dana Jansens
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
See the COPYING file for a copy of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#include "propwin.h"
|
||||
#include "openbox.h"
|
||||
#include "client.h"
|
||||
#include "debug.h"
|
||||
|
||||
typedef struct _ObPropWin ObPropWin;
|
||||
typedef struct _ObPropWinData ObPropWinData;
|
||||
|
||||
struct _ObPropWinData
|
||||
{
|
||||
GSList *clients;
|
||||
};
|
||||
|
||||
struct _ObPropWin
|
||||
{
|
||||
Window win;
|
||||
ObPropWinData data[OB_NUM_PROPWIN_TYPES];
|
||||
};
|
||||
|
||||
/*! A hash table that maps a window to an ObPropWin */
|
||||
static GHashTable *propwin_map;
|
||||
|
||||
static guint window_hash(Window *w) { return *w; }
|
||||
static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
|
||||
|
||||
void propwin_startup(gboolean reconfig)
|
||||
{
|
||||
if (!reconfig)
|
||||
propwin_map = g_hash_table_new_full((GHashFunc)window_hash,
|
||||
(GEqualFunc)window_comp,
|
||||
NULL,
|
||||
g_free);
|
||||
}
|
||||
|
||||
void propwin_shutdown(gboolean reconfig)
|
||||
{
|
||||
if (!reconfig)
|
||||
g_hash_table_destroy(propwin_map);
|
||||
else
|
||||
g_assert(g_hash_table_size(propwin_map) == 0);
|
||||
}
|
||||
|
||||
void propwin_add(Window win, ObPropWinType type, ObClient *client)
|
||||
{
|
||||
ObPropWin *p;
|
||||
|
||||
if (!win) return;
|
||||
|
||||
g_assert(client);
|
||||
g_assert(type < OB_NUM_PROPWIN_TYPES);
|
||||
|
||||
p = g_hash_table_lookup(propwin_map, &win);
|
||||
if (!p) {
|
||||
p = g_new0(ObPropWin, 1);
|
||||
p->win = win;
|
||||
g_hash_table_insert(propwin_map, &p->win, p);
|
||||
/* get property changes on this window */
|
||||
XSelectInput(ob_display, win, PropertyChangeMask);
|
||||
} else
|
||||
g_assert(g_slist_find(p->data[type].clients, client) == NULL);
|
||||
|
||||
if (p->data[type].clients != NULL)
|
||||
ob_debug("Client %s is using a property window 0x%x that is already "
|
||||
"in use\n", client->title, win);
|
||||
|
||||
/* add it to the clients list */
|
||||
p->data[type].clients = g_slist_prepend(p->data[type].clients, client);
|
||||
}
|
||||
|
||||
void propwin_remove(Window win, ObPropWinType type, ObClient *client)
|
||||
{
|
||||
ObPropWin *p;
|
||||
|
||||
if (!win) return;
|
||||
|
||||
p = g_hash_table_lookup(propwin_map, &win);
|
||||
g_assert(p);
|
||||
|
||||
/* remove it to the clients list */
|
||||
g_assert(g_slist_find(p->data[type].clients, client) != NULL);
|
||||
p->data[type].clients = g_slist_remove(p->data[type].clients, client);
|
||||
|
||||
/* no more clients left for this type */
|
||||
if (p->data[type].clients == NULL) {
|
||||
guint i;
|
||||
gboolean none = TRUE;
|
||||
|
||||
for (i = 0; i < OB_NUM_PROPWIN_TYPES; ++i)
|
||||
if (p->data[i].clients != NULL)
|
||||
none = FALSE; /* another type still has a client for this
|
||||
window */
|
||||
|
||||
if (none) {
|
||||
/* don't get events for this window any more */
|
||||
XSelectInput(ob_display, win, NoEventMask);
|
||||
g_hash_table_remove(propwin_map, &win);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSList* propwin_get_clients(Window win, ObPropWinType type)
|
||||
{
|
||||
ObPropWin *p = g_hash_table_lookup(propwin_map, &win);
|
||||
if (p)
|
||||
return p->data[type].clients;
|
||||
else
|
||||
return NULL;
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
|
||||
|
||||
propwin.h for the Openbox window manager
|
||||
Copyright (c) 2007 Dana Jansens
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
See the COPYING file for a copy of the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef __propwin_h
|
||||
#define __propwin_h
|
||||
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
struct _ObClient;
|
||||
|
||||
typedef enum {
|
||||
OB_PROPWIN_USER_TIME,
|
||||
OB_NUM_PROPWIN_TYPES
|
||||
} ObPropWinType;
|
||||
|
||||
void propwin_startup(gboolean reconfig);
|
||||
void propwin_shutdown(gboolean reconfig);
|
||||
|
||||
void propwin_add(Window win, ObPropWinType type, struct _ObClient *client);
|
||||
void propwin_remove(Window win, ObPropWinType type, struct _ObClient *client);
|
||||
|
||||
GSList* propwin_get_clients(Window win, ObPropWinType type);
|
||||
|
||||
#endif
|
314
openbox/resist.c
314
openbox/resist.c
|
@ -21,97 +21,114 @@
|
|||
#include "frame.h"
|
||||
#include "stacking.h"
|
||||
#include "screen.h"
|
||||
#include "dock.h"
|
||||
#include "config.h"
|
||||
#include "parser/parse.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y)
|
||||
static gboolean resist_move_window(Rect window,
|
||||
Rect target, gint resist,
|
||||
gint *x, gint *y)
|
||||
{
|
||||
GList *it;
|
||||
gint l, t, r, b; /* requested edges */
|
||||
gint cl, ct, cr, cb; /* current edges */
|
||||
gint w, h; /* current size */
|
||||
ObClient *snapx = NULL, *snapy = NULL;
|
||||
gint tl, tt, tr, tb; /* 1 past the target's edges on each side */
|
||||
gboolean snapx = 0, snapy = 0;
|
||||
|
||||
if (!resist) return;
|
||||
|
||||
frame_client_gravity(c->frame, x, y);
|
||||
|
||||
w = c->frame->area.width;
|
||||
h = c->frame->area.height;
|
||||
w = window.width;
|
||||
h = window.height;
|
||||
|
||||
l = *x;
|
||||
t = *y;
|
||||
r = l + w - 1;
|
||||
b = t + h - 1;
|
||||
|
||||
cl = RECT_LEFT(c->frame->area);
|
||||
ct = RECT_TOP(c->frame->area);
|
||||
cr = RECT_RIGHT(c->frame->area);
|
||||
cb = RECT_BOTTOM(c->frame->area);
|
||||
cl = RECT_LEFT(window);
|
||||
ct = RECT_TOP(window);
|
||||
cr = RECT_RIGHT(window);
|
||||
cb = RECT_BOTTOM(window);
|
||||
|
||||
tl = RECT_LEFT(target) - 1;
|
||||
tt = RECT_TOP(target) - 1;
|
||||
tr = RECT_RIGHT(target) + 1;
|
||||
tb = RECT_BOTTOM(target) + 1;
|
||||
|
||||
/* snapx and snapy ensure that the window snaps to the top-most
|
||||
window edge available, without going all the way from
|
||||
bottom-to-top in the stacking list
|
||||
*/
|
||||
if (!snapx) {
|
||||
if (ct < tb && cb > tt) {
|
||||
if (cl >= tr && l < tr && l >= tr - resist)
|
||||
*x = tr, snapx = TRUE;
|
||||
else if (cr <= tl && r > tl &&
|
||||
r <= tl + resist)
|
||||
*x = tl - w + 1, snapx = TRUE;
|
||||
if (snapx) {
|
||||
/* try to corner snap to the window */
|
||||
if (ct > tt && t <= tt &&
|
||||
t > tt - resist)
|
||||
*y = tt + 1, snapy = TRUE;
|
||||
else if (cb < tb && b >= tb &&
|
||||
b < tb + resist)
|
||||
*y = tb - h, snapy = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!snapy) {
|
||||
if (cl < tr && cr > tl) {
|
||||
if (ct >= tb && t < tb && t >= tb - resist)
|
||||
*y = tb, snapy = TRUE;
|
||||
else if (cb <= tt && b > tt &&
|
||||
b <= tt + resist)
|
||||
*y = tt - h + 1, snapy = TRUE;
|
||||
if (snapy) {
|
||||
/* try to corner snap to the window */
|
||||
if (cl > tl && l <= tl &&
|
||||
l > tl - resist)
|
||||
*x = tl + 1, snapx = TRUE;
|
||||
else if (cr < tr && r >= tr &&
|
||||
r < tr + resist)
|
||||
*x = tr - w, snapx = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return snapx && snapy;
|
||||
}
|
||||
|
||||
void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y)
|
||||
{
|
||||
GList *it;
|
||||
Rect dock_area;
|
||||
|
||||
if (!resist) return;
|
||||
|
||||
frame_client_gravity(c->frame, x, y);
|
||||
|
||||
|
||||
for (it = stacking_list; it; it = g_list_next(it)) {
|
||||
ObClient *target;
|
||||
gint tl, tt, tr, tb; /* 1 past the target's edges on each side */
|
||||
|
||||
if (!WINDOW_IS_CLIENT(it->data))
|
||||
continue;
|
||||
target = it->data;
|
||||
|
||||
/* don't snap to self or non-visibles */
|
||||
if (!target->frame->visible || target == c) continue;
|
||||
if (!target->frame->visible || target == c)
|
||||
continue;
|
||||
/* don't snap to windows set to below and skip_taskbar (desklets) */
|
||||
if (target->below && !c->below && target->skip_taskbar) continue;
|
||||
if (target->below && !c->below && target->skip_taskbar)
|
||||
continue;
|
||||
|
||||
tl = RECT_LEFT(target->frame->area) - 1;
|
||||
tt = RECT_TOP(target->frame->area) - 1;
|
||||
tr = RECT_RIGHT(target->frame->area) + 1;
|
||||
tb = RECT_BOTTOM(target->frame->area) + 1;
|
||||
|
||||
/* snapx and snapy ensure that the window snaps to the top-most
|
||||
window edge available, without going all the way from
|
||||
bottom-to-top in the stacking list
|
||||
*/
|
||||
if (snapx == NULL) {
|
||||
if (ct < tb && cb > tt) {
|
||||
if (cl >= tr && l < tr && l >= tr - resist)
|
||||
*x = tr, snapx = target;
|
||||
else if (cr <= tl && r > tl &&
|
||||
r <= tl + resist)
|
||||
*x = tl - w + 1, snapx = target;
|
||||
if (snapx != NULL) {
|
||||
/* try to corner snap to the window */
|
||||
if (ct > tt && t <= tt &&
|
||||
t > tt - resist)
|
||||
*y = tt + 1, snapy = target;
|
||||
else if (cb < tb && b >= tb &&
|
||||
b < tb + resist)
|
||||
*y = tb - h, snapy = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (snapy == NULL) {
|
||||
if (cl < tr && cr > tl) {
|
||||
if (ct >= tb && t < tb && t >= tb - resist)
|
||||
*y = tb, snapy = target;
|
||||
else if (cb <= tt && b > tt &&
|
||||
b <= tt + resist)
|
||||
*y = tt - h + 1, snapy = target;
|
||||
if (snapy != NULL) {
|
||||
/* try to corner snap to the window */
|
||||
if (cl > tl && l <= tl &&
|
||||
l > tl - resist)
|
||||
*x = tl + 1, snapx = target;
|
||||
else if (cr < tr && r >= tr &&
|
||||
r < tr + resist)
|
||||
*x = tr - w, snapx = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (snapx && snapy) break;
|
||||
if (resist_move_window(c->frame->area, target->frame->area,
|
||||
resist, x, y))
|
||||
break;
|
||||
}
|
||||
dock_get_area(&dock_area);
|
||||
resist_move_window(c->frame->area, dock_area, resist, x, y);
|
||||
|
||||
frame_frame_gravity(c->frame, x, y);
|
||||
}
|
||||
|
@ -191,101 +208,116 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
|
|||
frame_frame_gravity(c->frame, x, y);
|
||||
}
|
||||
|
||||
static gboolean resist_size_window(Rect window, Rect target, gint resist,
|
||||
gint *w, gint *h, ObDirection dir)
|
||||
{
|
||||
gint l, t, r, b; /* my left, top, right and bottom sides */
|
||||
gint tl, tt, tr, tb; /* target's left, top, right and bottom bottom sides*/
|
||||
gint dlt, drb; /* my destination left/top and right/bottom sides */
|
||||
gboolean snapx = 0, snapy = 0;
|
||||
gint orgw, orgh;
|
||||
|
||||
l = RECT_LEFT(window);
|
||||
t = RECT_TOP(window);
|
||||
r = RECT_RIGHT(window);
|
||||
b = RECT_BOTTOM(window);
|
||||
|
||||
orgw = window.width;
|
||||
orgh = window.height;
|
||||
|
||||
tl = RECT_LEFT(target);
|
||||
tt = RECT_TOP(target);
|
||||
tr = RECT_RIGHT(target);
|
||||
tb = RECT_BOTTOM(target);
|
||||
|
||||
if (!snapx) {
|
||||
/* horizontal snapping */
|
||||
if (t < tb && b > tt) {
|
||||
switch (dir) {
|
||||
case OB_DIRECTION_EAST:
|
||||
case OB_DIRECTION_NORTHEAST:
|
||||
case OB_DIRECTION_SOUTHEAST:
|
||||
case OB_DIRECTION_NORTH:
|
||||
case OB_DIRECTION_SOUTH:
|
||||
dlt = l;
|
||||
drb = r + *w - orgw;
|
||||
if (r < tl && drb >= tl &&
|
||||
drb < tl + resist)
|
||||
*w = tl - l, snapx = TRUE;
|
||||
break;
|
||||
case OB_DIRECTION_WEST:
|
||||
case OB_DIRECTION_NORTHWEST:
|
||||
case OB_DIRECTION_SOUTHWEST:
|
||||
dlt = l - *w + orgw;
|
||||
drb = r;
|
||||
if (l > tr && dlt <= tr &&
|
||||
dlt > tr - resist)
|
||||
*w = r - tr, snapx = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!snapy) {
|
||||
/* vertical snapping */
|
||||
if (l < tr && r > tl) {
|
||||
switch (dir) {
|
||||
case OB_DIRECTION_SOUTH:
|
||||
case OB_DIRECTION_SOUTHWEST:
|
||||
case OB_DIRECTION_SOUTHEAST:
|
||||
case OB_DIRECTION_EAST:
|
||||
case OB_DIRECTION_WEST:
|
||||
dlt = t;
|
||||
drb = b + *h - orgh;
|
||||
if (b < tt && drb >= tt &&
|
||||
drb < tt + resist)
|
||||
*h = tt - t, snapy = TRUE;
|
||||
break;
|
||||
case OB_DIRECTION_NORTH:
|
||||
case OB_DIRECTION_NORTHWEST:
|
||||
case OB_DIRECTION_NORTHEAST:
|
||||
dlt = t - *h + orgh;
|
||||
drb = b;
|
||||
if (t > tb && dlt <= tb &&
|
||||
dlt > tb - resist)
|
||||
*h = b - tb, snapy = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* snapped both ways */
|
||||
return snapx && snapy;
|
||||
}
|
||||
|
||||
void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h,
|
||||
ObDirection dir)
|
||||
{
|
||||
GList *it;
|
||||
ObClient *target; /* target */
|
||||
gint l, t, r, b; /* my left, top, right and bottom sides */
|
||||
gint dlt, drb; /* my destination left/top and right/bottom sides */
|
||||
gint tl, tt, tr, tb; /* target's left, top, right and bottom bottom sides*/
|
||||
gint incw, inch;
|
||||
ObClient *snapx = NULL, *snapy = NULL;
|
||||
Rect dock_area;
|
||||
|
||||
if (!resist) return;
|
||||
|
||||
incw = c->size_inc.width;
|
||||
inch = c->size_inc.height;
|
||||
|
||||
l = RECT_LEFT(c->frame->area);
|
||||
r = RECT_RIGHT(c->frame->area);
|
||||
t = RECT_TOP(c->frame->area);
|
||||
b = RECT_BOTTOM(c->frame->area);
|
||||
|
||||
for (it = stacking_list; it; it = g_list_next(it)) {
|
||||
if (!WINDOW_IS_CLIENT(it->data))
|
||||
continue;
|
||||
target = it->data;
|
||||
|
||||
/* don't snap to invisibles or ourself */
|
||||
if (!target->frame->visible || target == c) continue;
|
||||
if (!target->frame->visible || target == c)
|
||||
continue;
|
||||
/* don't snap to windows set to below and skip_taskbar (desklets) */
|
||||
if (target->below && !c->below && target->skip_taskbar) continue;
|
||||
if (target->below && !c->below && target->skip_taskbar)
|
||||
continue;
|
||||
|
||||
tl = RECT_LEFT(target->frame->area);
|
||||
tr = RECT_RIGHT(target->frame->area);
|
||||
tt = RECT_TOP(target->frame->area);
|
||||
tb = RECT_BOTTOM(target->frame->area);
|
||||
|
||||
if (snapx == NULL) {
|
||||
/* horizontal snapping */
|
||||
if (t < tb && b > tt) {
|
||||
switch (dir) {
|
||||
case OB_DIRECTION_EAST:
|
||||
case OB_DIRECTION_NORTHEAST:
|
||||
case OB_DIRECTION_SOUTHEAST:
|
||||
case OB_DIRECTION_NORTH:
|
||||
case OB_DIRECTION_SOUTH:
|
||||
dlt = l;
|
||||
drb = r + *w - c->frame->area.width;
|
||||
if (r < tl && drb >= tl &&
|
||||
drb < tl + resist)
|
||||
*w = tl - l, snapx = target;
|
||||
break;
|
||||
case OB_DIRECTION_WEST:
|
||||
case OB_DIRECTION_NORTHWEST:
|
||||
case OB_DIRECTION_SOUTHWEST:
|
||||
dlt = l - *w + c->frame->area.width;
|
||||
drb = r;
|
||||
if (l > tr && dlt <= tr &&
|
||||
dlt > tr - resist)
|
||||
*w = r - tr, snapx = target;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (snapy == NULL) {
|
||||
/* vertical snapping */
|
||||
if (l < tr && r > tl) {
|
||||
switch (dir) {
|
||||
case OB_DIRECTION_SOUTH:
|
||||
case OB_DIRECTION_SOUTHWEST:
|
||||
case OB_DIRECTION_SOUTHEAST:
|
||||
case OB_DIRECTION_EAST:
|
||||
case OB_DIRECTION_WEST:
|
||||
dlt = t;
|
||||
drb = b + *h - c->frame->area.height;
|
||||
if (b < tt && drb >= tt &&
|
||||
drb < tt + resist)
|
||||
*h = tt - t, snapy = target;
|
||||
break;
|
||||
case OB_DIRECTION_NORTH:
|
||||
case OB_DIRECTION_NORTHWEST:
|
||||
case OB_DIRECTION_NORTHEAST:
|
||||
dlt = t - *h + c->frame->area.height;
|
||||
drb = b;
|
||||
if (t > tb && dlt <= tb &&
|
||||
dlt > tb - resist)
|
||||
*h = b - tb, snapy = target;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* snapped both ways */
|
||||
if (snapx && snapy) break;
|
||||
if (resist_size_window(c->frame->area, target->frame->area,
|
||||
resist, w, h, dir))
|
||||
break;
|
||||
}
|
||||
dock_get_area(&dock_area);
|
||||
resist_size_window(c->frame->area, dock_area,
|
||||
resist, w, h, dir);
|
||||
}
|
||||
|
||||
void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
|
||||
|
|
207
openbox/screen.c
207
openbox/screen.c
|
@ -26,6 +26,7 @@
|
|||
#include "startupnotify.h"
|
||||
#include "moveresize.h"
|
||||
#include "config.h"
|
||||
#include "mainloop.h"
|
||||
#include "screen.h"
|
||||
#include "client.h"
|
||||
#include "session.h"
|
||||
|
@ -53,6 +54,7 @@
|
|||
static gboolean screen_validate_layout(ObDesktopLayout *l);
|
||||
static gboolean replace_wm();
|
||||
static void screen_tell_ksplash();
|
||||
static void screen_fallback_focus();
|
||||
|
||||
guint screen_num_desktops;
|
||||
guint screen_num_monitors;
|
||||
|
@ -73,7 +75,7 @@ static GSList *struts_left = NULL;
|
|||
static GSList *struts_right = NULL;
|
||||
static GSList *struts_bottom = NULL;
|
||||
|
||||
static ObPagerPopup *desktop_cycle_popup;
|
||||
static ObPagerPopup *desktop_popup;
|
||||
|
||||
static gboolean replace_wm()
|
||||
{
|
||||
|
@ -107,22 +109,7 @@ static gboolean replace_wm()
|
|||
current_wm_sn_owner = None;
|
||||
}
|
||||
|
||||
{
|
||||
/* Generate a timestamp */
|
||||
XEvent event;
|
||||
|
||||
XSelectInput(ob_display, screen_support_win, PropertyChangeMask);
|
||||
|
||||
XChangeProperty(ob_display, screen_support_win,
|
||||
prop_atoms.wm_class, prop_atoms.string,
|
||||
8, PropModeAppend, NULL, 0);
|
||||
XWindowEvent(ob_display, screen_support_win,
|
||||
PropertyChangeMask, &event);
|
||||
|
||||
XSelectInput(ob_display, screen_support_win, NoEventMask);
|
||||
|
||||
timestamp = event.xproperty.time;
|
||||
}
|
||||
timestamp = event_get_server_time();
|
||||
|
||||
XSetSelectionOwner(ob_display, wm_sn_atom, screen_support_win,
|
||||
timestamp);
|
||||
|
@ -172,12 +159,14 @@ gboolean screen_annex()
|
|||
|
||||
/* create the netwm support window */
|
||||
attrib.override_redirect = TRUE;
|
||||
attrib.event_mask = PropertyChangeMask;
|
||||
screen_support_win = XCreateWindow(ob_display,
|
||||
RootWindow(ob_display, ob_screen),
|
||||
-100, -100, 1, 1, 0,
|
||||
CopyFromParent, InputOutput,
|
||||
CopyFromParent,
|
||||
CWOverrideRedirect, &attrib);
|
||||
CWEventMask | CWOverrideRedirect,
|
||||
&attrib);
|
||||
XMapWindow(ob_display, screen_support_win);
|
||||
XLowerWindow(ob_display, screen_support_win);
|
||||
|
||||
|
@ -283,7 +272,9 @@ gboolean screen_annex()
|
|||
supported[i++] = prop_atoms.net_moveresize_window;
|
||||
supported[i++] = prop_atoms.net_wm_moveresize;
|
||||
supported[i++] = prop_atoms.net_wm_user_time;
|
||||
/*
|
||||
supported[i++] = prop_atoms.net_wm_user_time_window;
|
||||
*/
|
||||
supported[i++] = prop_atoms.net_frame_extents;
|
||||
supported[i++] = prop_atoms.net_request_frame_extents;
|
||||
supported[i++] = prop_atoms.net_restack_window;
|
||||
|
@ -353,12 +344,12 @@ void screen_startup(gboolean reconfig)
|
|||
guint32 d;
|
||||
gboolean namesexist = FALSE;
|
||||
|
||||
desktop_cycle_popup = pager_popup_new(FALSE);
|
||||
pager_popup_height(desktop_cycle_popup, POPUP_HEIGHT);
|
||||
desktop_popup = pager_popup_new(FALSE);
|
||||
pager_popup_height(desktop_popup, POPUP_HEIGHT);
|
||||
|
||||
if (reconfig) {
|
||||
/* update the pager popup's width */
|
||||
pager_popup_text_width_to_strings(desktop_cycle_popup,
|
||||
pager_popup_text_width_to_strings(desktop_popup,
|
||||
screen_desktop_names,
|
||||
screen_num_desktops);
|
||||
return;
|
||||
|
@ -441,7 +432,7 @@ void screen_startup(gboolean reconfig)
|
|||
|
||||
void screen_shutdown(gboolean reconfig)
|
||||
{
|
||||
pager_popup_free(desktop_cycle_popup);
|
||||
pager_popup_free(desktop_popup);
|
||||
|
||||
if (reconfig)
|
||||
return;
|
||||
|
@ -545,13 +536,52 @@ void screen_set_num_desktops(guint num)
|
|||
screen_set_desktop(num - 1, TRUE);
|
||||
}
|
||||
|
||||
void screen_set_desktop(guint num, gboolean dofocus)
|
||||
static void screen_fallback_focus()
|
||||
{
|
||||
ObClient *c;
|
||||
gboolean allow_omni;
|
||||
|
||||
/* only allow omnipresent windows to get focus on desktop change if
|
||||
an omnipresent window is already focused (it'll keep focus probably, but
|
||||
maybe not depending on mouse-focus options) */
|
||||
allow_omni = focus_client && (client_normal(focus_client) &&
|
||||
focus_client->desktop == DESKTOP_ALL);
|
||||
|
||||
/* the client moved there already so don't move focus. prevent flicker
|
||||
on sendtodesktop + follow */
|
||||
if (focus_client && focus_client->desktop == screen_desktop)
|
||||
return;
|
||||
|
||||
/* have to try focus here because when you leave an empty desktop
|
||||
there is no focus out to watch for. also, we have different rules
|
||||
here. we always allow it to look under the mouse pointer if
|
||||
config_focus_last is FALSE
|
||||
|
||||
do this before hiding the windows so if helper windows are coming
|
||||
with us, they don't get hidden
|
||||
*/
|
||||
if ((c = focus_fallback(TRUE, !config_focus_last, allow_omni,
|
||||
!allow_omni)))
|
||||
{
|
||||
/* only do the flicker reducing stuff ahead of time if we are going
|
||||
to call xsetinputfocus on the window ourselves. otherwise there is
|
||||
no guarantee the window will actually take focus.. */
|
||||
if (c->can_focus) {
|
||||
/* reduce flicker by hiliting now rather than waiting for the
|
||||
server FocusIn event */
|
||||
frame_adjust_focus(c->frame, TRUE);
|
||||
/* do this here so that if you switch desktops to a window with
|
||||
helper windows then the helper windows won't flash */
|
||||
client_bring_helper_windows(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void screen_set_desktop(guint num, gboolean dofocus)
|
||||
{
|
||||
GList *it;
|
||||
guint old;
|
||||
gulong ignore_start;
|
||||
gboolean allow_omni;
|
||||
|
||||
g_assert(num < screen_num_desktops);
|
||||
|
||||
|
@ -583,39 +613,7 @@ void screen_set_desktop(guint num, gboolean dofocus)
|
|||
}
|
||||
}
|
||||
|
||||
/* only allow omnipresent windows to get focus on desktop change if
|
||||
an omnipresent window is already focused (it'll keep focus probably, but
|
||||
maybe not depending on mouse-focus options) */
|
||||
allow_omni = focus_client && (client_normal(focus_client) &&
|
||||
focus_client->desktop == DESKTOP_ALL);
|
||||
|
||||
/* the client moved there already so don't move focus. prevent flicker
|
||||
on sendtodesktop + follow */
|
||||
if (focus_client && focus_client->desktop == screen_desktop)
|
||||
dofocus = FALSE;
|
||||
|
||||
/* have to try focus here because when you leave an empty desktop
|
||||
there is no focus out to watch for. also, we have different rules
|
||||
here. we always allow it to look under the mouse pointer if
|
||||
config_focus_last is FALSE
|
||||
|
||||
do this before hiding the windows so if helper windows are coming
|
||||
with us, they don't get hidden
|
||||
*/
|
||||
if (dofocus && (c = focus_fallback(TRUE, !config_focus_last, allow_omni)))
|
||||
{
|
||||
/* only do the flicker reducing stuff ahead of time if we are going
|
||||
to call xsetinputfocus on the window ourselves. otherwise there is
|
||||
no guarantee the window will actually take focus.. */
|
||||
if (c->can_focus) {
|
||||
/* reduce flicker by hiliting now rather than waiting for the
|
||||
server FocusIn event */
|
||||
frame_adjust_focus(c->frame, TRUE);
|
||||
/* do this here so that if you switch desktops to a window with
|
||||
helper windows then the helper windows won't flash */
|
||||
client_bring_helper_windows(c);
|
||||
}
|
||||
}
|
||||
if (dofocus) screen_fallback_focus();
|
||||
|
||||
/* hide windows from bottom to top */
|
||||
for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {
|
||||
|
@ -629,10 +627,18 @@ void screen_set_desktop(guint num, gboolean dofocus)
|
|||
|
||||
if (event_curtime != CurrentTime)
|
||||
screen_desktop_user_time = event_curtime;
|
||||
|
||||
if (ob_state() == OB_STATE_RUNNING)
|
||||
screen_show_desktop_popup(screen_desktop);
|
||||
}
|
||||
|
||||
void screen_add_desktop(gboolean current)
|
||||
{
|
||||
gulong ignore_start;
|
||||
|
||||
/* ignore enter events caused by this */
|
||||
ignore_start = event_start_ignore_all_enters();
|
||||
|
||||
screen_set_num_desktops(screen_num_desktops+1);
|
||||
|
||||
/* move all the clients over */
|
||||
|
@ -651,15 +657,21 @@ void screen_add_desktop(gboolean current)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
event_end_ignore_all_enters(ignore_start);
|
||||
}
|
||||
|
||||
void screen_remove_desktop(gboolean current)
|
||||
{
|
||||
guint rmdesktop, movedesktop;
|
||||
GList *it, *stacking_copy;
|
||||
gulong ignore_start;
|
||||
|
||||
if (screen_num_desktops <= 1) return;
|
||||
|
||||
/* ignore enter events caused by this */
|
||||
ignore_start = event_start_ignore_all_enters();
|
||||
|
||||
/* what desktop are we removing and moving to? */
|
||||
if (current)
|
||||
rmdesktop = screen_desktop;
|
||||
|
@ -696,15 +708,15 @@ void screen_remove_desktop(gboolean current)
|
|||
}
|
||||
}
|
||||
|
||||
/* act like we're changing desktops */
|
||||
/* fallback focus like we're changing desktops */
|
||||
if (screen_desktop < screen_num_desktops - 1) {
|
||||
gint d = screen_desktop;
|
||||
screen_desktop = screen_last_desktop;
|
||||
screen_set_desktop(d, TRUE);
|
||||
screen_fallback_focus();
|
||||
ob_debug("fake desktop change\n");
|
||||
}
|
||||
|
||||
screen_set_num_desktops(screen_num_desktops-1);
|
||||
|
||||
event_end_ignore_all_enters(ignore_start);
|
||||
}
|
||||
|
||||
static void get_row_col(guint d, guint *r, guint *c)
|
||||
|
@ -815,25 +827,34 @@ static guint translate_row_col(guint r, guint c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void screen_desktop_popup(guint d, gboolean show)
|
||||
static gboolean hide_desktop_popup_func(gpointer data)
|
||||
{
|
||||
pager_popup_hide(desktop_popup);
|
||||
return FALSE; /* don't repeat */
|
||||
}
|
||||
|
||||
void screen_show_desktop_popup(guint d)
|
||||
{
|
||||
Rect *a;
|
||||
|
||||
if (!show) {
|
||||
pager_popup_hide(desktop_cycle_popup);
|
||||
} else {
|
||||
a = screen_physical_area_active();
|
||||
pager_popup_position(desktop_cycle_popup, CenterGravity,
|
||||
a->x + a->width / 2, a->y + a->height / 2);
|
||||
pager_popup_icon_size_multiplier(desktop_cycle_popup,
|
||||
(screen_desktop_layout.columns /
|
||||
screen_desktop_layout.rows) / 2,
|
||||
(screen_desktop_layout.rows/
|
||||
screen_desktop_layout.columns) / 2);
|
||||
pager_popup_max_width(desktop_cycle_popup,
|
||||
MAX(a->width/3, POPUP_WIDTH));
|
||||
pager_popup_show(desktop_cycle_popup, screen_desktop_names[d], d);
|
||||
}
|
||||
/* 0 means don't show the popup */
|
||||
if (!config_desktop_popup_time) return;
|
||||
|
||||
a = screen_physical_area_active();
|
||||
pager_popup_position(desktop_popup, CenterGravity,
|
||||
a->x + a->width / 2, a->y + a->height / 2);
|
||||
pager_popup_icon_size_multiplier(desktop_popup,
|
||||
(screen_desktop_layout.columns /
|
||||
screen_desktop_layout.rows) / 2,
|
||||
(screen_desktop_layout.rows/
|
||||
screen_desktop_layout.columns) / 2);
|
||||
pager_popup_max_width(desktop_popup,
|
||||
MAX(a->width/3, POPUP_WIDTH));
|
||||
pager_popup_show(desktop_popup, screen_desktop_names[d], d);
|
||||
|
||||
ob_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
|
||||
ob_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000,
|
||||
hide_desktop_popup_func, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
guint screen_find_desktop(guint from, ObDirection dir,
|
||||
|
@ -942,30 +963,6 @@ guint screen_find_desktop(guint from, ObDirection dir,
|
|||
return d;
|
||||
}
|
||||
|
||||
guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
|
||||
gboolean dialog, gboolean done, gboolean cancel)
|
||||
{
|
||||
static guint d = (guint)-1;
|
||||
guint ret;
|
||||
|
||||
if (d == (guint)-1)
|
||||
d = screen_desktop;
|
||||
|
||||
if ((!cancel && !done) || !dialog)
|
||||
d = screen_find_desktop(d, dir, wrap, linear);
|
||||
|
||||
if (dialog && !cancel && !done)
|
||||
screen_desktop_popup(d, TRUE);
|
||||
else
|
||||
screen_desktop_popup(0, FALSE);
|
||||
ret = d;
|
||||
|
||||
if (!dialog || cancel || done)
|
||||
d = (guint)-1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean screen_validate_layout(ObDesktopLayout *l)
|
||||
{
|
||||
if (l->columns == 0 && l->rows == 0) /* both 0's is bad data.. */
|
||||
|
@ -1092,7 +1089,7 @@ void screen_update_desktop_names()
|
|||
}
|
||||
|
||||
/* resize the pager for these names */
|
||||
pager_popup_text_width_to_strings(desktop_cycle_popup,
|
||||
pager_popup_text_width_to_strings(desktop_popup,
|
||||
screen_desktop_names,
|
||||
screen_num_desktops);
|
||||
}
|
||||
|
@ -1142,7 +1139,7 @@ void screen_show_desktop(gboolean show, ObClient *show_only)
|
|||
else if (!show_only) {
|
||||
ObClient *c;
|
||||
|
||||
if ((c = focus_fallback(TRUE, FALSE, TRUE))) {
|
||||
if ((c = focus_fallback(TRUE, FALSE, TRUE, FALSE))) {
|
||||
/* only do the flicker reducing stuff ahead of time if we are going
|
||||
to call xsetinputfocus on the window ourselves. otherwise there
|
||||
is no guarantee the window will actually take focus.. */
|
||||
|
@ -1555,7 +1552,9 @@ Rect* screen_physical_area_active()
|
|||
Rect *a;
|
||||
gint x, y;
|
||||
|
||||
if (focus_client)
|
||||
if (moveresize_client)
|
||||
a = screen_physical_area_monitor(client_monitor(focus_client));
|
||||
else if (focus_client)
|
||||
a = screen_physical_area_monitor(client_monitor(focus_client));
|
||||
else {
|
||||
Rect mon;
|
||||
|
|
|
@ -72,15 +72,11 @@ void screen_add_desktop(gboolean current);
|
|||
/*! Remove a desktop, either at the end or the current desktop */
|
||||
void screen_remove_desktop(gboolean current);
|
||||
|
||||
/*! Interactively change desktops */
|
||||
guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
|
||||
gboolean dialog, gboolean done, gboolean cancel);
|
||||
|
||||
guint screen_find_desktop(guint from, ObDirection dir,
|
||||
gboolean wrap, gboolean linear);
|
||||
|
||||
/*! Show/hide the desktop popup (pager) for the given desktop */
|
||||
void screen_desktop_popup(guint d, gboolean show);
|
||||
/*! Show the desktop popup/notification */
|
||||
void screen_show_desktop_popup(guint d);
|
||||
|
||||
/*! Shows and focuses the desktop and hides all the client windows, or
|
||||
returns to the normal state, showing client windows.
|
||||
|
|
8
po/no.po
8
po/no.po
|
@ -5,7 +5,7 @@
|
|||
# Michael Kjelbergvik Thung <postlogic@switch-case.org>, 2007.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openbox 3.4.2\n"
|
||||
"Project-Id-Version: openbox 3.4.3\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
|
||||
"POT-Creation-Date: 2007-07-22 08:25-0400\n"
|
||||
"PO-Revision-Date: 2007-05-20 18:41+0200\n"
|
||||
|
@ -31,15 +31,15 @@ msgstr "Gå dit..."
|
|||
|
||||
#: openbox/client_list_combined_menu.c:98
|
||||
msgid "Manage desktops"
|
||||
msgstr ""
|
||||
msgstr "Behandle skrivebord"
|
||||
|
||||
#: openbox/client_list_combined_menu.c:99 openbox/client_list_menu.c:152
|
||||
msgid "_Add new desktop"
|
||||
msgstr ""
|
||||
msgstr "_Nytt skrivebord"
|
||||
|
||||
#: openbox/client_list_combined_menu.c:100 openbox/client_list_menu.c:153
|
||||
msgid "_Remove last desktop"
|
||||
msgstr ""
|
||||
msgstr "_Fjern siste skrivebord"
|
||||
|
||||
#: openbox/client_list_combined_menu.c:146
|
||||
msgid "Windows"
|
||||
|
|
12
po/zh_TW.po
12
po/zh_TW.po
|
@ -5,10 +5,10 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openbox 3.4.2\n"
|
||||
"Project-Id-Version: openbox 3.4.3\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n"
|
||||
"POT-Creation-Date: 2007-07-22 08:25-0400\n"
|
||||
"PO-Revision-Date: 2007-05-23 16:22+0200\n"
|
||||
"PO-Revision-Date: 2007-07-23 23:22+0200\n"
|
||||
"Last-Translator: Wei-Lun Chao <chaoweilun@gmail.com>\n"
|
||||
"Language-Team: Chinese (traditional) <zh-l10n@linux.org.tw>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -19,7 +19,7 @@ msgstr ""
|
|||
#: openbox/actions/execute.c:88
|
||||
#, c-format
|
||||
msgid "Failed to convert the path '%s' from utf8"
|
||||
msgstr "從 utf8 轉換路徑「%s」時失敗"
|
||||
msgstr "轉換路徑「%s」自 utf8 時失敗"
|
||||
|
||||
#: openbox/actions/execute.c:97 openbox/actions/execute.c:115
|
||||
#, c-format
|
||||
|
@ -32,15 +32,15 @@ msgstr "到那裏去…"
|
|||
|
||||
#: openbox/client_list_combined_menu.c:98
|
||||
msgid "Manage desktops"
|
||||
msgstr ""
|
||||
msgstr "管理桌面"
|
||||
|
||||
#: openbox/client_list_combined_menu.c:99 openbox/client_list_menu.c:152
|
||||
msgid "_Add new desktop"
|
||||
msgstr ""
|
||||
msgstr "加入新桌面(_A)"
|
||||
|
||||
#: openbox/client_list_combined_menu.c:100 openbox/client_list_menu.c:153
|
||||
msgid "_Remove last desktop"
|
||||
msgstr ""
|
||||
msgstr "移除尾端桌面(_R)"
|
||||
|
||||
#: openbox/client_list_combined_menu.c:146
|
||||
msgid "Windows"
|
||||
|
|
|
@ -186,7 +186,9 @@ RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
|
|||
if (!read_int(db, "padding.width", &theme->paddingx) ||
|
||||
theme->paddingx < 0 || theme->paddingx > 100)
|
||||
theme->paddingx = 3;
|
||||
theme->paddingy = theme->paddingx;
|
||||
if (!read_int(db, "padding.height", &theme->paddingy) ||
|
||||
theme->paddingy < 0 || theme->paddingy > 100)
|
||||
theme->paddingy = theme->paddingx;
|
||||
if (!read_int(db, "border.width", &theme->fbwidth) ||
|
||||
theme->fbwidth < 0 || theme->fbwidth > 100)
|
||||
theme->fbwidth = 1;
|
||||
|
|
Loading…
Reference in a new issue