+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame.c for the Openbox window manager
+ Copyright (c) 2003 Ben 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 "frame.h"
#include "client.h"
#include "openbox.h"
#include "extensions.h"
+#include "prop.h"
#include "config.h"
#include "framerender.h"
#include "mainloop.h"
+#include "focus.h"
+#include "moveresize.h"
#include "render/theme.h"
#define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
static void set_theme_statics(ObFrame *self);
static void free_theme_statics(ObFrame *self);
-static Window createWindow(Window parent, unsigned long mask,
+static Window createWindow(Window parent, gulong mask,
XSetWindowAttributes *attrib)
{
return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
ObFrame *frame_new()
{
XSetWindowAttributes attrib;
- unsigned long mask;
+ gulong mask;
ObFrame *self;
- self = g_new(ObFrame, 1);
+ self = g_new0(ObFrame, 1);
- self->visible = FALSE;
self->obscured = TRUE;
- self->decorations = 0;
- self->flashing = FALSE;
/* create all of the decor windows */
- mask = CWOverrideRedirect | CWEventMask;
+ mask = CWEventMask;
attrib.event_mask = FRAME_EVENTMASK;
- attrib.override_redirect = TRUE;
self->window = createWindow(RootWindow(ob_display, ob_screen),
mask, &attrib);
static void set_theme_statics(ObFrame *self)
{
/* set colors/appearance/sizes for stuff that doesn't change */
- XSetWindowBorder(ob_display, self->window, ob_rr_theme->b_color->pixel);
- XSetWindowBorder(ob_display, self->title, ob_rr_theme->b_color->pixel);
- XSetWindowBorder(ob_display, self->handle, ob_rr_theme->b_color->pixel);
- XSetWindowBorder(ob_display, self->rgrip, ob_rr_theme->b_color->pixel);
- XSetWindowBorder(ob_display, self->lgrip, ob_rr_theme->b_color->pixel);
+ XSetWindowBorder(ob_display, self->window,
+ RrColorPixel(ob_rr_theme->b_color));
+ XSetWindowBorder(ob_display, self->title,
+ RrColorPixel(ob_rr_theme->b_color));
+ XSetWindowBorder(ob_display, self->handle,
+ RrColorPixel(ob_rr_theme->b_color));
+ XSetWindowBorder(ob_display, self->rgrip,
+ RrColorPixel(ob_rr_theme->b_color));
+ XSetWindowBorder(ob_display, self->lgrip,
+ RrColorPixel(ob_rr_theme->b_color));
XResizeWindow(ob_display, self->max,
ob_rr_theme->button_size, ob_rr_theme->button_size);
void frame_show(ObFrame *self)
{
if (!self->visible) {
- self->visible = TRUE;
- XMapWindow(ob_display, self->window);
+ self->visible = TRUE;
+ XMapWindow(ob_display, self->client->window);
+ XMapWindow(ob_display, self->window);
}
}
void frame_hide(ObFrame *self)
{
if (self->visible) {
- self->visible = FALSE;
- self->client->ignore_unmaps++;
- XUnmapWindow(ob_display, self->window);
+ self->visible = FALSE;
+ self->client->ignore_unmaps += 2;
+ /* we unmap the client itself so that we can get MapRequest
+ events, and because the ICCCM tells us to! */
+ XUnmapWindow(ob_display, self->window);
+ XUnmapWindow(ob_display, self->client->window);
}
}
{
free_theme_statics(self);
set_theme_statics(self);
- frame_adjust_area(self, TRUE, TRUE, FALSE);
}
void frame_adjust_shape(ObFrame *self)
{
#ifdef SHAPE
- int num;
+ gint num;
XRectangle xrect[2];
if (!self->client->shaped) {
void frame_adjust_area(ObFrame *self, gboolean moved,
gboolean resized, gboolean fake)
{
+ Strut oldsize;
+
+ oldsize = self->size;
+
if (resized) {
self->decorations = self->client->decorations;
self->max_horz = self->client->max_horz;
frame_adjust_shape(self);
}
+
+ if (!STRUT_EQUAL(self->size, oldsize)) {
+ guint32 vals[4];
+ vals[0] = self->size.left;
+ vals[1] = self->size.right;
+ vals[2] = self->size.top;
+ vals[3] = self->size.bottom;
+ PROP_SETA32(self->client->window, kde_net_wm_frame_strut,
+ cardinal, vals, 4);
+ }
+
+ /* if this occurs while we are focus cycling, the indicator needs to
+ match the changes */
+ if (focus_cycle_target == self->client)
+ focus_cycle_draw_indicator();
}
}
void frame_release_client(ObFrame *self, ObClient *client)
{
XEvent ev;
+ gboolean reparent = TRUE;
g_assert(self->client == client);
/* check if the app has already reparented its window away */
- if (XCheckTypedWindowEvent(ob_display, client->window,
- ReparentNotify, &ev)) {
- XPutBackEvent(ob_display, &ev);
-
- /* re-map the window since the unmanaging process unmaps it */
+ while (XCheckTypedWindowEvent(ob_display, client->window,
+ ReparentNotify, &ev))
+ {
+ /* This check makes sure we don't catch our own reparent action to
+ our frame window. This doesn't count as the app reparenting itself
+ away of course.
+
+ Reparent events that are generated by us are just discarded here.
+ They are of no consequence to us anyhow.
+ */
+ if (ev.xreparent.parent != self->plate) {
+ reparent = FALSE;
+ XPutBackEvent(ob_display, &ev);
+ break;
+ }
+ }
- /* XXX ... um no it doesnt it unmaps its parent, the window itself
- retains its mapped state, no?! XXX
- XMapWindow(ob_display, client->window); */
- } else {
- /* according to the ICCCM - if the client doesn't reparent itself,
- then we will reparent the window to root for them */
- XReparentWindow(ob_display, client->window,
+ if (reparent) {
+ /* according to the ICCCM - if the client doesn't reparent itself,
+ then we will reparent the window to root for them */
+ XReparentWindow(ob_display, client->window,
RootWindow(ob_display, ob_screen),
- client->area.x,
- client->area.y);
+ client->area.x,
+ client->area.y);
}
/* remove all the windows for the frame from the window_map */
static void layout_title(ObFrame *self)
{
- char *lc;
- int x;
+ gchar *lc;
+ gint x;
gboolean n, d, i, l, m, c, s;
n = d = i = l = m = c = s = FALSE;
}
}
-ObFrameContext frame_context_from_string(char *name)
+ObFrameContext frame_context_from_string(const gchar *name)
{
- if (!g_ascii_strcasecmp("desktop", name))
+ if (!g_ascii_strcasecmp("Desktop", name))
return OB_FRAME_CONTEXT_DESKTOP;
- else if (!g_ascii_strcasecmp("client", name))
+ else if (!g_ascii_strcasecmp("Client", name))
return OB_FRAME_CONTEXT_CLIENT;
- else if (!g_ascii_strcasecmp("titlebar", name))
+ else if (!g_ascii_strcasecmp("Titlebar", name))
return OB_FRAME_CONTEXT_TITLEBAR;
- else if (!g_ascii_strcasecmp("handle", name))
+ else if (!g_ascii_strcasecmp("Handle", name))
return OB_FRAME_CONTEXT_HANDLE;
- else if (!g_ascii_strcasecmp("frame", name))
+ else if (!g_ascii_strcasecmp("Frame", name))
return OB_FRAME_CONTEXT_FRAME;
- else if (!g_ascii_strcasecmp("tlcorner", name))
+ else if (!g_ascii_strcasecmp("TLCorner", name))
return OB_FRAME_CONTEXT_TLCORNER;
- else if (!g_ascii_strcasecmp("trcorner", name))
+ else if (!g_ascii_strcasecmp("TRCorner", name))
return OB_FRAME_CONTEXT_TRCORNER;
- else if (!g_ascii_strcasecmp("blcorner", name))
+ else if (!g_ascii_strcasecmp("BLCorner", name))
return OB_FRAME_CONTEXT_BLCORNER;
- else if (!g_ascii_strcasecmp("brcorner", name))
+ else if (!g_ascii_strcasecmp("BRCorner", name))
return OB_FRAME_CONTEXT_BRCORNER;
- else if (!g_ascii_strcasecmp("maximize", name))
+ else if (!g_ascii_strcasecmp("Maximize", name))
return OB_FRAME_CONTEXT_MAXIMIZE;
- else if (!g_ascii_strcasecmp("alldesktops", name))
+ else if (!g_ascii_strcasecmp("AllDesktops", name))
return OB_FRAME_CONTEXT_ALLDESKTOPS;
- else if (!g_ascii_strcasecmp("shade", name))
+ else if (!g_ascii_strcasecmp("Shade", name))
return OB_FRAME_CONTEXT_SHADE;
- else if (!g_ascii_strcasecmp("iconify", name))
+ else if (!g_ascii_strcasecmp("Iconify", name))
return OB_FRAME_CONTEXT_ICONIFY;
- else if (!g_ascii_strcasecmp("icon", name))
+ else if (!g_ascii_strcasecmp("Icon", name))
return OB_FRAME_CONTEXT_ICON;
- else if (!g_ascii_strcasecmp("close", name))
+ else if (!g_ascii_strcasecmp("Close", name))
return OB_FRAME_CONTEXT_CLOSE;
+ else if (!g_ascii_strcasecmp("MoveResize", name))
+ return OB_FRAME_CONTEXT_MOVE_RESIZE;
return OB_FRAME_CONTEXT_NONE;
}
{
ObFrame *self;
+ if (moveresize_in_progress)
+ return OB_FRAME_CONTEXT_MOVE_RESIZE;
+
if (win == RootWindow(ob_display, ob_screen))
return OB_FRAME_CONTEXT_DESKTOP;
if (client == NULL) return OB_FRAME_CONTEXT_NONE;
return OB_FRAME_CONTEXT_NONE;
}
-void frame_client_gravity(ObFrame *self, int *x, int *y)
+void frame_client_gravity(ObFrame *self, gint *x, gint *y)
{
/* horizontal */
switch (self->client->gravity) {
}
}
-void frame_frame_gravity(ObFrame *self, int *x, int *y)
+void frame_frame_gravity(ObFrame *self, gint *x, gint *y)
{
/* horizontal */
switch (self->client->gravity) {
return FALSE; /* we are done */
self->flash_on = !self->flash_on;
- {
- gboolean focused;
-
- focused = self->focused; /* save the focused flag */
+ if (!self->focused) {
frame_adjust_focus(self, self->flash_on);
- self->focused = focused;
+ self->focused = FALSE;
}
return TRUE; /* go again */
if (!self->flashing)
ob_main_loop_timeout_add(ob_main_loop,
- G_USEC_PER_SEC * 0.75,
+ G_USEC_PER_SEC * 0.6,
flash_timeout,
self,
flash_done);