From e08de6796850f4cfc907b17a74bbfaa6e6a58649 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 20 May 2007 07:11:35 +0000 Subject: [PATCH] merge r6648-6665 from trunk --- openbox/focus_cycle_indicator.c | 244 +++++++++++++++ openbox/focus_cycle_indicator.h | 32 ++ openbox/focus_cycle_popup.c | 520 +++++++++++++++++++++++++++++++ openbox/focus_cycle_popup.h | 42 +++ openbox/frame.c | 531 ++++++++++++++++++++++++-------- openbox/frame.h | 30 +- openbox/framerender.c | 48 ++- openbox/menu.c | 37 ++- openbox/menuframe.h | 3 - openbox/openbox.c | 4 +- 10 files changed, 1333 insertions(+), 158 deletions(-) create mode 100644 openbox/focus_cycle_indicator.c create mode 100644 openbox/focus_cycle_indicator.h create mode 100644 openbox/focus_cycle_popup.c create mode 100644 openbox/focus_cycle_popup.h diff --git a/openbox/focus_cycle_indicator.c b/openbox/focus_cycle_indicator.c new file mode 100644 index 00000000..a8e0c2d6 --- /dev/null +++ b/openbox/focus_cycle_indicator.c @@ -0,0 +1,244 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + focus_cycle_indicator.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 "focus_cycle.h" +#include "client.h" +#include "openbox.h" +#include "frame.h" +#include "event.h" +#include "render/render.h" + +#include +#include + +#define FOCUS_INDICATOR_WIDTH 6 + +struct +{ + InternalWindow top; + InternalWindow left; + InternalWindow right; + InternalWindow bottom; +} focus_indicator; + +static RrAppearance *a_focus_indicator; +static RrColor *color_white; + +static Window create_window(Window parent, gulong mask, + XSetWindowAttributes *attrib) +{ + return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0, + RrDepth(ob_rr_inst), InputOutput, + RrVisual(ob_rr_inst), mask, attrib); + +} + +void focus_cycle_indicator_startup(gboolean reconfig) +{ + XSetWindowAttributes attr; + + if (reconfig) return; + + focus_indicator.top.obwin.type = Window_Internal; + focus_indicator.left.obwin.type = Window_Internal; + focus_indicator.right.obwin.type = Window_Internal; + focus_indicator.bottom.obwin.type = Window_Internal; + + attr.override_redirect = True; + attr.background_pixel = BlackPixel(ob_display, ob_screen); + focus_indicator.top.win = + create_window(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel, &attr); + focus_indicator.left.win = + create_window(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel, &attr); + focus_indicator.right.win = + create_window(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel, &attr); + focus_indicator.bottom.win = + create_window(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel, &attr); + + stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.top)); + stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.left)); + stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.right)); + stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.bottom)); + + color_white = RrColorNew(ob_rr_inst, 0xff, 0xff, 0xff); + + a_focus_indicator = RrAppearanceNew(ob_rr_inst, 4); + a_focus_indicator->surface.grad = RR_SURFACE_SOLID; + a_focus_indicator->surface.relief = RR_RELIEF_FLAT; + a_focus_indicator->surface.primary = RrColorNew(ob_rr_inst, + 0, 0, 0); + a_focus_indicator->texture[0].type = RR_TEXTURE_LINE_ART; + a_focus_indicator->texture[0].data.lineart.color = color_white; + a_focus_indicator->texture[1].type = RR_TEXTURE_LINE_ART; + a_focus_indicator->texture[1].data.lineart.color = color_white; + a_focus_indicator->texture[2].type = RR_TEXTURE_LINE_ART; + a_focus_indicator->texture[2].data.lineart.color = color_white; + a_focus_indicator->texture[3].type = RR_TEXTURE_LINE_ART; + a_focus_indicator->texture[3].data.lineart.color = color_white; +} + +void focus_cycle_indicator_shutdown(gboolean reconfig) +{ + if (reconfig) return; + + RrColorFree(color_white); + + RrAppearanceFree(a_focus_indicator); + + XDestroyWindow(ob_display, focus_indicator.top.win); + XDestroyWindow(ob_display, focus_indicator.left.win); + XDestroyWindow(ob_display, focus_indicator.right.win); + XDestroyWindow(ob_display, focus_indicator.bottom.win); +} + +void focus_cycle_draw_indicator(ObClient *c) +{ + if (!c) { + XUnmapWindow(ob_display, focus_indicator.top.win); + XUnmapWindow(ob_display, focus_indicator.left.win); + XUnmapWindow(ob_display, focus_indicator.right.win); + XUnmapWindow(ob_display, focus_indicator.bottom.win); + + /* kill enter events cause by this unmapping */ + event_ignore_all_queued_enters(); + } else { + /* + if (c) + frame_adjust_focus(c->frame, FALSE); + frame_adjust_focus(c->frame, TRUE); + */ + gint x, y, w, h; + gint wt, wl, wr, wb; + + wt = wl = wr = wb = FOCUS_INDICATOR_WIDTH; + + x = c->frame->area.x; + y = c->frame->area.y; + w = c->frame->area.width; + h = wt; + + XMoveResizeWindow(ob_display, focus_indicator.top.win, + x, y, w, h); + a_focus_indicator->texture[0].data.lineart.x1 = 0; + a_focus_indicator->texture[0].data.lineart.y1 = h-1; + a_focus_indicator->texture[0].data.lineart.x2 = 0; + a_focus_indicator->texture[0].data.lineart.y2 = 0; + a_focus_indicator->texture[1].data.lineart.x1 = 0; + a_focus_indicator->texture[1].data.lineart.y1 = 0; + a_focus_indicator->texture[1].data.lineart.x2 = w-1; + a_focus_indicator->texture[1].data.lineart.y2 = 0; + a_focus_indicator->texture[2].data.lineart.x1 = w-1; + a_focus_indicator->texture[2].data.lineart.y1 = 0; + a_focus_indicator->texture[2].data.lineart.x2 = w-1; + a_focus_indicator->texture[2].data.lineart.y2 = h-1; + a_focus_indicator->texture[3].data.lineart.x1 = (wl-1); + a_focus_indicator->texture[3].data.lineart.y1 = h-1; + a_focus_indicator->texture[3].data.lineart.x2 = w - wr; + a_focus_indicator->texture[3].data.lineart.y2 = h-1; + RrPaint(a_focus_indicator, focus_indicator.top.win, + w, h); + + x = c->area.x; + y = c->frame->area.y; + w = wl; + h = c->frame->area.height; + + XMoveResizeWindow(ob_display, focus_indicator.left.win, + x, y, w, h); + a_focus_indicator->texture[0].data.lineart.x1 = w-1; + a_focus_indicator->texture[0].data.lineart.y1 = 0; + a_focus_indicator->texture[0].data.lineart.x2 = 0; + a_focus_indicator->texture[0].data.lineart.y2 = 0; + a_focus_indicator->texture[1].data.lineart.x1 = 0; + a_focus_indicator->texture[1].data.lineart.y1 = 0; + a_focus_indicator->texture[1].data.lineart.x2 = 0; + a_focus_indicator->texture[1].data.lineart.y2 = h-1; + a_focus_indicator->texture[2].data.lineart.x1 = 0; + a_focus_indicator->texture[2].data.lineart.y1 = h-1; + a_focus_indicator->texture[2].data.lineart.x2 = w-1; + a_focus_indicator->texture[2].data.lineart.y2 = h-1; + a_focus_indicator->texture[3].data.lineart.x1 = w-1; + a_focus_indicator->texture[3].data.lineart.y1 = wt-1; + a_focus_indicator->texture[3].data.lineart.x2 = w-1; + a_focus_indicator->texture[3].data.lineart.y2 = h - wb; + RrPaint(a_focus_indicator, focus_indicator.left.win, + w, h); + + x = c->frame->area.x + c->frame->area.width - wr; + y = c->frame->area.y; + w = wr; + h = c->frame->area.height ; + + XMoveResizeWindow(ob_display, focus_indicator.right.win, + x, y, w, h); + a_focus_indicator->texture[0].data.lineart.x1 = 0; + a_focus_indicator->texture[0].data.lineart.y1 = 0; + a_focus_indicator->texture[0].data.lineart.x2 = w-1; + a_focus_indicator->texture[0].data.lineart.y2 = 0; + a_focus_indicator->texture[1].data.lineart.x1 = w-1; + a_focus_indicator->texture[1].data.lineart.y1 = 0; + a_focus_indicator->texture[1].data.lineart.x2 = w-1; + a_focus_indicator->texture[1].data.lineart.y2 = h-1; + a_focus_indicator->texture[2].data.lineart.x1 = w-1; + a_focus_indicator->texture[2].data.lineart.y1 = h-1; + a_focus_indicator->texture[2].data.lineart.x2 = 0; + a_focus_indicator->texture[2].data.lineart.y2 = h-1; + a_focus_indicator->texture[3].data.lineart.x1 = 0; + a_focus_indicator->texture[3].data.lineart.y1 = wt-1; + a_focus_indicator->texture[3].data.lineart.x2 = 0; + a_focus_indicator->texture[3].data.lineart.y2 = h - wb; + RrPaint(a_focus_indicator, focus_indicator.right.win, + w, h); + + x = c->frame->area.x; + y = c->frame->area.y + c->frame->area.height - wb; + w = c->frame->area.width; + h = wb; + + XMoveResizeWindow(ob_display, focus_indicator.bottom.win, + x, y, w, h); + a_focus_indicator->texture[0].data.lineart.x1 = 0; + a_focus_indicator->texture[0].data.lineart.y1 = 0; + a_focus_indicator->texture[0].data.lineart.x2 = 0; + a_focus_indicator->texture[0].data.lineart.y2 = h-1; + a_focus_indicator->texture[1].data.lineart.x1 = 0; + a_focus_indicator->texture[1].data.lineart.y1 = h-1; + a_focus_indicator->texture[1].data.lineart.x2 = w-1; + a_focus_indicator->texture[1].data.lineart.y2 = h-1; + a_focus_indicator->texture[2].data.lineart.x1 = w-1; + a_focus_indicator->texture[2].data.lineart.y1 = h-1; + a_focus_indicator->texture[2].data.lineart.x2 = w-1; + a_focus_indicator->texture[2].data.lineart.y2 = 0; + a_focus_indicator->texture[3].data.lineart.x1 = wl-1; + a_focus_indicator->texture[3].data.lineart.y1 = 0; + a_focus_indicator->texture[3].data.lineart.x2 = w - wr; + a_focus_indicator->texture[3].data.lineart.y2 = 0; + RrPaint(a_focus_indicator, focus_indicator.bottom.win, + w, h); + + XMapWindow(ob_display, focus_indicator.top.win); + XMapWindow(ob_display, focus_indicator.left.win); + XMapWindow(ob_display, focus_indicator.right.win); + XMapWindow(ob_display, focus_indicator.bottom.win); + } +} diff --git a/openbox/focus_cycle_indicator.h b/openbox/focus_cycle_indicator.h new file mode 100644 index 00000000..8c84f71a --- /dev/null +++ b/openbox/focus_cycle_indicator.h @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + focus_cycle_indicator.h 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. +*/ + +#ifndef __focus_cycle_indicator_h +#define __focus_cycle_indicator_h + +struct _ObClient; + +void focus_cycle_indicator_startup(gboolean reconfig); +void focus_cycle_indicator_shutdown(gboolean reconfig); + +void focus_cycle_draw_indicator(struct _ObClient *c); + +void focus_cycle_stop(); + +#endif diff --git a/openbox/focus_cycle_popup.c b/openbox/focus_cycle_popup.c new file mode 100644 index 00000000..ef01ddf4 --- /dev/null +++ b/openbox/focus_cycle_popup.c @@ -0,0 +1,520 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + focus_cycle_popup.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 "focus_cycle_popup.h" +#include "popup.h" +#include "client.h" +#include "screen.h" +#include "focus.h" +#include "focus_cycle.h" +#include "openbox.h" +#include "window.h" +#include "render/render.h" + +#include +#include + +#define ICON_SIZE 40 +#define ICON_HILITE_WIDTH 2 +#define ICON_HILITE_MARGIN 1 +#define OUTSIDE_BORDER 3 + +typedef struct _ObFocusCyclePopup ObFocusCyclePopup; +typedef struct _ObFocusCyclePopupTarget ObFocusCyclePopupTarget; + +struct _ObFocusCyclePopupTarget +{ + ObClient *client; + gchar *text; + Window win; +}; + +struct _ObFocusCyclePopup +{ + ObWindow obwin; + Window bg; + + Window text; + + GList *targets; + gint n_targets; + + const ObFocusCyclePopupTarget *last_target; + + gint maxtextw; + + RrAppearance *a_bg; + RrAppearance *a_text; + RrAppearance *a_icon; + + RrPixel32 *hilite_rgba; + + gboolean mapped; +}; + +/*! This popup shows all possible windows */ +static ObFocusCyclePopup popup; +/*! This popup shows a single window */ +static ObIconPopup *single_popup; + +static gchar *popup_get_name (ObClient *c); +static void popup_setup (ObFocusCyclePopup *p, + gboolean create_targets, + gboolean iconic_windows, + gboolean all_desktops, + gboolean dock_windows, + gboolean desktop_windows); +static void popup_render (ObFocusCyclePopup *p, + const ObClient *c); + +static Window create_window(Window parent, guint bwidth, gulong mask, + XSetWindowAttributes *attr) +{ + return XCreateWindow(ob_display, parent, 0, 0, 1, 1, bwidth, + RrDepth(ob_rr_inst), InputOutput, + RrVisual(ob_rr_inst), mask, attr); +} + +void focus_cycle_popup_startup(gboolean reconfig) +{ + XSetWindowAttributes attrib; + + single_popup = icon_popup_new(TRUE); + + popup.obwin.type = Window_Internal; + popup.a_bg = RrAppearanceCopy(ob_rr_theme->osd_hilite_bg); + popup.a_text = RrAppearanceCopy(ob_rr_theme->osd_hilite_label); + popup.a_icon = RrAppearanceCopy(ob_rr_theme->a_clear_tex); + + popup.a_text->surface.parent = popup.a_bg; + popup.a_icon->surface.parent = popup.a_bg; + + popup.a_icon->texture[0].type = RR_TEXTURE_RGBA; + + RrAppearanceAddTextures(popup.a_bg, 1); + popup.a_bg->texture[0].type = RR_TEXTURE_RGBA; + + attrib.override_redirect = True; + attrib.border_pixel=RrColorPixel(ob_rr_theme->frame_focused_border_color); + popup.bg = create_window(RootWindow(ob_display, ob_screen), + ob_rr_theme->fbwidth, + CWOverrideRedirect | CWBorderPixel, &attrib); + + popup.text = create_window(popup.bg, 0, 0, NULL); + + popup.targets = NULL; + popup.n_targets = 0; + popup.last_target = NULL; + + popup.hilite_rgba = NULL; + + XMapWindow(ob_display, popup.text); + + stacking_add(INTERNAL_AS_WINDOW(&popup)); +} + +void focus_cycle_popup_shutdown(gboolean reconfig) +{ + icon_popup_free(single_popup); + + stacking_remove(INTERNAL_AS_WINDOW(&popup)); + + while(popup.targets) { + ObFocusCyclePopupTarget *t = popup.targets->data; + + g_free(t->text); + XDestroyWindow(ob_display, t->win); + + popup.targets = g_list_delete_link(popup.targets, popup.targets); + } + + g_free(popup.hilite_rgba); + + XDestroyWindow(ob_display, popup.text); + XDestroyWindow(ob_display, popup.bg); + + RrAppearanceFree(popup.a_icon); + RrAppearanceFree(popup.a_text); + RrAppearanceFree(popup.a_bg); +} + +static void popup_setup(ObFocusCyclePopup *p, gboolean create_targets, + gboolean iconic_windows, gboolean all_desktops, + gboolean dock_windows, gboolean desktop_windows) +{ + gint maxwidth, n; + GList *it; + + g_assert(p->targets == NULL); + g_assert(p->n_targets == 0); + + /* make its width to be the width of all the possible titles */ + + /* build a list of all the valid focus targets and measure their strings, + and count them */ + maxwidth = 0; + n = 0; + for (it = g_list_last(focus_order); it; it = g_list_previous(it)) { + ObClient *ft = it->data; + + if (focus_cycle_target_valid(ft, + iconic_windows, + all_desktops, + dock_windows, + desktop_windows)) + { + gchar *text = popup_get_name(ft); + + /* measure */ + p->a_text->texture[0].data.text.string = text; + maxwidth = MAX(maxwidth, RrMinWidth(p->a_text)); + + if (!create_targets) + g_free(text); + else { + ObFocusCyclePopupTarget *t = g_new(ObFocusCyclePopupTarget, 1); + + t->client = ft; + t->text = text; + t->win = create_window(p->bg, 0, 0, NULL); + + XMapWindow(ob_display, t->win); + + p->targets = g_list_prepend(p->targets, t); + ++n; + } + } + } + + p->n_targets = n; + p->maxtextw = maxwidth; +} + +static gchar *popup_get_name(ObClient *c) +{ + ObClient *p; + gchar *title = NULL; + const gchar *desk = NULL; + gchar *ret; + + /* find our highest direct parent, including non-normal windows */ + for (p = c; p->transient_for && p->transient_for != OB_TRAN_GROUP; + p = p->transient_for); + + if (c->desktop != DESKTOP_ALL && c->desktop != screen_desktop) + desk = screen_desktop_names[c->desktop]; + + /* use the transient's parent's title/icon if we don't have one */ + if (p != c && !strcmp("", (c->iconic ? c->icon_title : c->title))) + title = g_strdup(p->iconic ? p->icon_title : p->title); + + if (title == NULL) + title = g_strdup(c->iconic ? c->icon_title : c->title); + + if (desk) + ret = g_strdup_printf("%s [%s]", title, desk); + else { + ret = title; + title = NULL; + } + g_free(title); + + return ret; +} + +static void popup_render(ObFocusCyclePopup *p, const ObClient *c) +{ + gint ml, mt, mr, mb; + gint l, t, r, b; + gint x, y, w, h; + Rect *screen_area; + gint icons_per_row; + gint icon_rows; + gint textx, texty, textw, texth; + gint rgbax, rgbay, rgbaw, rgbah; + gint icons_center_x; + gint innerw, innerh; + gint i; + GList *it; + const ObFocusCyclePopupTarget *newtarget; + gint newtargetx, newtargety; + + /* XXX find the middle monitor? */ + screen_area = screen_physical_area_monitor(0); + + /* get the outside margins */ + RrMargins(p->a_bg, &ml, &mt, &mr, &mb); + + /* get our outside borders */ + l = ml + OUTSIDE_BORDER; + r = mr + OUTSIDE_BORDER; + t = mt + OUTSIDE_BORDER; + b = mb + OUTSIDE_BORDER; + + /* get the icon pictures' sizes */ + innerw = ICON_SIZE - (ICON_HILITE_WIDTH + ICON_HILITE_MARGIN) * 2; + innerh = ICON_SIZE - (ICON_HILITE_WIDTH + ICON_HILITE_MARGIN) * 2; + + /* get the width from the text and keep it within limits */ + w = l + r + p->maxtextw; + w = MIN(w, MAX(screen_area->width/3, POPUP_WIDTH)); /* max width */ + w = MAX(w, POPUP_WIDTH); /* min width */ + + /* how many icons will fit in that row? make the width fit that */ + w -= l + r; + icons_per_row = (w + ICON_SIZE - 1) / ICON_SIZE; + w = icons_per_row * ICON_SIZE + l + r; + + /* how many rows do we need? */ + icon_rows = (p->n_targets-1) / icons_per_row + 1; + + /* get the text dimensions */ + textw = w - l - r; + texth = RrMinHeight(p->a_text); + + /* find the height of the dialog */ + h = t + b + (icon_rows * ICON_SIZE) + (OUTSIDE_BORDER*2 + texth); + + /* get the position of the text */ + textx = l; + texty = h - texth - b; + + /* find the position for the popup (include the outer borders) */ + x = screen_area->x + (screen_area->width - + (w + ob_rr_theme->fbwidth * 2)) / 2; + y = screen_area->y + (screen_area->height - + (h + ob_rr_theme->fbwidth * 2)) / 2; + + /* get the dimensions of the target hilite texture */ + rgbax = ml; + rgbay = mt; + rgbaw = w - ml - mr; + rgbah = h - mt - mb; + + /* center the icons if there is less than one row */ + if (icon_rows == 1) + icons_center_x = (w - p->n_targets * ICON_SIZE) / 2; + else + icons_center_x = 0; + + if (!p->mapped) { + /* position the background but don't draw it*/ + XMoveResizeWindow(ob_display, p->bg, x, y, w, h); + + /* set up the hilite texture for the background */ + p->a_bg->texture[0].data.rgba.width = rgbaw; + p->a_bg->texture[0].data.rgba.height = rgbah; + p->hilite_rgba = g_new(RrPixel32, rgbaw * rgbah); + p->a_bg->texture[0].data.rgba.data = p->hilite_rgba; + + /* position the text, but don't draw it */ + XMoveResizeWindow(ob_display, p->text, textx, texty, textw, texth); + p->a_text->surface.parentx = textx; + p->a_text->surface.parenty = texty; + } + + /* find the focused target */ + for (i = 0, it = p->targets; it; ++i, it = g_list_next(it)) { + const ObFocusCyclePopupTarget *target = it->data; + const gint row = i / icons_per_row; /* starting from 0 */ + const gint col = i % icons_per_row; /* starting from 0 */ + + if (target->client == c) { + /* save the target */ + newtarget = target; + newtargetx = icons_center_x + l + (col * ICON_SIZE); + newtargety = t + (row * ICON_SIZE); + + if (!p->mapped) + break; /* if we're not dimensioning, then we're done */ + } + } + + g_assert(newtarget != NULL); + + /* create the hilite under the target icon */ + { + RrPixel32 color; + gint i, j, o; + + color = ((ob_rr_theme->osd_color->r & 0xff) << RrDefaultRedOffset) + + ((ob_rr_theme->osd_color->g & 0xff) << RrDefaultGreenOffset) + + ((ob_rr_theme->osd_color->b & 0xff) << RrDefaultBlueOffset); + + o = 0; + for (i = 0; i < rgbah; ++i) + for (j = 0; j < rgbaw; ++j) { + guchar a; + const gint x = j + rgbax - newtargetx; + const gint y = i + rgbay - newtargety; + + if (x < 0 || x >= ICON_SIZE || + y < 0 || y >= ICON_SIZE) + { + /* outside the target */ + a = 0x00; + } + else if (x < ICON_HILITE_WIDTH || + x >= ICON_SIZE - ICON_HILITE_WIDTH || + y < ICON_HILITE_WIDTH || + y >= ICON_SIZE - ICON_HILITE_WIDTH) + { + /* the border of the target */ + a = 0x88; + } + else { + /* the background of the target */ + a = 0x22; + } + + p->hilite_rgba[o++] = + color + (a << RrDefaultAlphaOffset); + } + } + + /* * * draw everything * * */ + + /* draw the background */ + RrPaint(p->a_bg, p->bg, w, h); + + /* draw the icons */ + for (i = 0, it = p->targets; it; ++i, it = g_list_next(it)) { + const ObFocusCyclePopupTarget *target = it->data; + + /* have to redraw the targetted icon and last targetted icon, + they can pick up the hilite changes in the backgroud */ + if (!p->mapped || newtarget == target || p->last_target == target) { + const ObClientIcon *icon; + const gint row = i / icons_per_row; /* starting from 0 */ + const gint col = i % icons_per_row; /* starting from 0 */ + gint innerx, innery; + + /* find the dimensions of the icon inside it */ + innerx = icons_center_x + l + (col * ICON_SIZE); + innerx += ICON_HILITE_WIDTH + ICON_HILITE_MARGIN; + innery = t + (row * ICON_SIZE); + innery += ICON_HILITE_WIDTH + ICON_HILITE_MARGIN; + + /* move the icon */ + XMoveResizeWindow(ob_display, target->win, + innerx, innery, innerw, innerh); + + /* get the icon from the client */ + icon = client_icon(target->client, innerw, innerh); + p->a_icon->texture[0].data.rgba.width = icon->width; + p->a_icon->texture[0].data.rgba.height = icon->height; + p->a_icon->texture[0].data.rgba.data = icon->data; + + /* draw the icon */ + p->a_icon->surface.parentx = innerx; + p->a_icon->surface.parenty = innery; + RrPaint(p->a_icon, target->win, innerw, innerh); + } + } + + /* draw the text */ + p->a_text->texture[0].data.text.string = newtarget->text; + p->a_text->surface.parentx = textx; + p->a_text->surface.parenty = texty; + RrPaint(p->a_text, p->text, textw, texth); + + p->last_target = newtarget; +} + +void focus_cycle_popup_show(ObClient *c, gboolean iconic_windows, + gboolean all_desktops, gboolean dock_windows, + gboolean desktop_windows) +{ + g_assert(c != NULL); + + /* do this stuff only when the dialog is first showing */ + if (!popup.mapped) + popup_setup(&popup, TRUE, iconic_windows, all_desktops, + dock_windows, desktop_windows); + g_assert(popup.targets != NULL); + + popup_render(&popup, c); + + if (!popup.mapped) { + /* show the dialog */ + XMapWindow(ob_display, popup.bg); + XFlush(ob_display); + popup.mapped = TRUE; + } +} + +void focus_cycle_popup_hide() +{ + XUnmapWindow(ob_display, popup.bg); + XFlush(ob_display); + + popup.mapped = FALSE; + + while(popup.targets) { + ObFocusCyclePopupTarget *t = popup.targets->data; + + g_free(t->text); + XDestroyWindow(ob_display, t->win); + + popup.targets = g_list_delete_link(popup.targets, popup.targets); + } + popup.n_targets = 0; + popup.last_target = NULL; + + g_free(popup.hilite_rgba); + popup.hilite_rgba = NULL; +} + +void focus_cycle_popup_single_show(struct _ObClient *c, + gboolean iconic_windows, + gboolean all_desktops, + gboolean dock_windows, + gboolean desktop_windows) +{ + gchar *text; + + g_assert(c != NULL); + + /* do this stuff only when the dialog is first showing */ + if (!popup.mapped) { + Rect *a; + + popup_setup(&popup, FALSE, iconic_windows, all_desktops, + dock_windows, desktop_windows); + g_assert(popup.targets == NULL); + + /* position the popup */ + a = screen_physical_area_monitor(0); + icon_popup_position(single_popup, CenterGravity, + a->x + a->width / 2, a->y + a->height / 2); + icon_popup_height(single_popup, POPUP_HEIGHT); + icon_popup_min_width(single_popup, POPUP_WIDTH); + icon_popup_max_width(single_popup, MAX(a->width/3, POPUP_WIDTH)); + icon_popup_text_width(single_popup, popup.maxtextw); + } + + text = popup_get_name(c); + icon_popup_show(single_popup, text, client_icon(c, ICON_SIZE, ICON_SIZE)); + g_free(text); +} + +void focus_cycle_popup_single_hide() +{ + icon_popup_hide(single_popup); +} diff --git a/openbox/focus_cycle_popup.h b/openbox/focus_cycle_popup.h new file mode 100644 index 00000000..ded39e20 --- /dev/null +++ b/openbox/focus_cycle_popup.h @@ -0,0 +1,42 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + focus_cycle.h 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. +*/ + +#ifndef __focus_cycle_popup_h +#define __focus_cycle_popup_h + +struct _ObClient; + +#include + +void focus_cycle_popup_startup(gboolean reconfig); +void focus_cycle_popup_shutdown(gboolean reconfig); + +void focus_cycle_popup_show(struct _ObClient *c, gboolean iconic_windows, + gboolean all_desktops, gboolean dock_windows, + gboolean desktop_windows); +void focus_cycle_popup_hide(); + +void focus_cycle_popup_single_show(struct _ObClient *c, + gboolean iconic_windows, + gboolean all_desktops, + gboolean dock_windows, + gboolean desktop_windows); +void focus_cycle_popup_single_hide(); + +#endif diff --git a/openbox/frame.c b/openbox/frame.c index e042c4fc..ca66821a 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -46,8 +46,7 @@ #define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */ #define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */ -#define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \ - f->cbwidth_y) +#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_y) static void flash_done(gpointer data); static gboolean flash_timeout(gpointer data); @@ -72,6 +71,11 @@ static Visual *check_32bit_client(ObClient *c) XWindowAttributes wattrib; Status ret; + /* we're already running at 32 bit depth, yay. we don't need to use their + visual */ + if (RrDepth(ob_rr_inst) == 32) + return NULL; + ret = XGetWindowAttributes(ob_display, c->window, &wattrib); g_assert(ret != BadDrawable); g_assert(ret != BadWindow); @@ -104,8 +108,8 @@ ObFrame *frame_new(ObClient *client) XCreateColormap(ob_display, RootWindow(ob_display, ob_screen), visual, AllocNone); - attrib.background_pixel = BlackPixel(ob_display, 0); - attrib.border_pixel = BlackPixel(ob_display, 0); + attrib.background_pixel = BlackPixel(ob_display, ob_screen); + attrib.border_pixel = BlackPixel(ob_display, ob_screen); } attrib.event_mask = FRAME_EVENTMASK; self->window = createWindow(RootWindow(ob_display, ob_screen), visual, @@ -127,23 +131,22 @@ ObFrame *frame_new(ObClient *client) } attrib.event_mask = ELEMENT_EVENTMASK; self->title = createWindow(self->window, NULL, mask, &attrib); + self->titleleft = createWindow(self->window, NULL, mask, &attrib); + self->titletop = createWindow(self->window, NULL, mask, &attrib); + self->titletopleft = createWindow(self->window, NULL, mask, &attrib); + self->titletopright = createWindow(self->window, NULL, mask, &attrib); + self->titleright = createWindow(self->window, NULL, mask, &attrib); + self->titlebottom = createWindow(self->window, NULL, mask, &attrib); - mask |= CWCursor; - attrib.cursor = ob_cursor(OB_CURSOR_NORTH); self->topresize = createWindow(self->title, NULL, mask, &attrib); - attrib.cursor = ob_cursor(OB_CURSOR_NORTHWEST); self->tltresize = createWindow(self->title, NULL, mask, &attrib); self->tllresize = createWindow(self->title, NULL, mask, &attrib); - attrib.cursor = ob_cursor(OB_CURSOR_NORTHEAST); self->trtresize = createWindow(self->title, NULL, mask, &attrib); self->trrresize = createWindow(self->title, NULL, mask, &attrib); - attrib.cursor = ob_cursor(OB_CURSOR_WEST); - self->leftresize = createWindow(self->inner, NULL, mask, &attrib); - attrib.cursor = ob_cursor(OB_CURSOR_EAST); - self->rightresize = createWindow(self->inner, NULL, mask, &attrib); + self->left = createWindow(self->window, NULL, mask, &attrib); + self->right = createWindow(self->window, NULL, mask, &attrib); - mask &= ~CWCursor; self->label = createWindow(self->title, NULL, mask, &attrib); self->max = createWindow(self->title, NULL, mask, &attrib); self->close = createWindow(self->title, NULL, mask, &attrib); @@ -152,21 +155,27 @@ ObFrame *frame_new(ObClient *client) self->icon = createWindow(self->title, NULL, mask, &attrib); self->iconify = createWindow(self->title, NULL, mask, &attrib); - mask |= CWCursor; - attrib.cursor = ob_cursor(OB_CURSOR_SOUTH); self->handle = createWindow(self->window, NULL, mask, &attrib); - attrib.cursor = ob_cursor(OB_CURSOR_SOUTHWEST); self->lgrip = createWindow(self->handle, NULL, mask, &attrib); - attrib.cursor = ob_cursor(OB_CURSOR_SOUTHEAST); self->rgrip = createWindow(self->handle, NULL, mask, &attrib); + self->handleleft = createWindow(self->handle, NULL, mask, &attrib); + self->handleright = createWindow(self->handle, NULL, mask, &attrib); + + self->handletop = createWindow(self->window, NULL, mask, &attrib); + self->handlebottom = createWindow(self->window, NULL, mask, &attrib); + self->lgripleft = createWindow(self->window, NULL, mask, &attrib); + self->lgriptop = createWindow(self->window, NULL, mask, &attrib); + self->lgripbottom = createWindow(self->window, NULL, mask, &attrib); + self->rgripright = createWindow(self->window, NULL, mask, &attrib); + self->rgriptop = createWindow(self->window, NULL, mask, &attrib); + self->rgripbottom = createWindow(self->window, NULL, mask, &attrib); + self->focused = FALSE; /* the other stuff is shown based on decor settings */ XMapWindow(ob_display, self->plate); XMapWindow(ob_display, self->inner); - XMapWindow(ob_display, self->lgrip); - XMapWindow(ob_display, self->rgrip); XMapWindow(ob_display, self->label); self->max_press = self->close_press = self->desk_press = @@ -181,14 +190,6 @@ ObFrame *frame_new(ObClient *client) static void set_theme_statics(ObFrame *self) { - gint handle_height; - - if (ob_rr_theme->handle_height > 0) - handle_height = ob_rr_theme->handle_height; - else - handle_height = 1; - - /* set colors/appearance/sizes for stuff that doesn't change */ XResizeWindow(ob_display, self->max, ob_rr_theme->button_size, ob_rr_theme->button_size); @@ -202,10 +203,6 @@ static void set_theme_statics(ObFrame *self) ob_rr_theme->button_size, ob_rr_theme->button_size); XResizeWindow(ob_display, self->shade, ob_rr_theme->button_size, ob_rr_theme->button_size); - XResizeWindow(ob_display, self->lgrip, - ob_rr_theme->grip_width, handle_height); - XResizeWindow(ob_display, self->rgrip, - ob_rr_theme->grip_width, handle_height); XResizeWindow(ob_display, self->tltresize, ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1); XResizeWindow(ob_display, self->trtresize, @@ -285,14 +282,14 @@ void frame_adjust_shape(ObFrame *self) if (!self->client->shaped) { /* clear the shape on the frame window */ XShapeCombineMask(ob_display, self->window, ShapeBounding, - self->innersize.left, - self->innersize.top, + self->size.left, + self->size.top, None, ShapeSet); } else { /* make the frame's shape match the clients */ XShapeCombineShape(ob_display, self->window, ShapeBounding, - self->innersize.left, - self->innersize.top, + self->size.left, + self->size.top, self->client->window, ShapeBounding, ShapeSet); @@ -300,7 +297,7 @@ void frame_adjust_shape(ObFrame *self) if (self->decorations & OB_FRAME_DECOR_TITLEBAR) { xrect[0].x = -ob_rr_theme->fbwidth; xrect[0].y = -ob_rr_theme->fbwidth; - xrect[0].width = self->width + self->rbwidth * 2; + xrect[0].width = self->width + self->bwidth * 2; xrect[0].height = ob_rr_theme->title_height + self->bwidth * 2; ++num; @@ -309,7 +306,7 @@ void frame_adjust_shape(ObFrame *self) if (self->decorations & OB_FRAME_DECOR_HANDLE) { xrect[1].x = -ob_rr_theme->fbwidth; xrect[1].y = FRAME_HANDLE_Y(self); - xrect[1].width = self->width + self->rbwidth * 2; + xrect[1].width = self->width + self->bwidth * 2; xrect[1].height = ob_rr_theme->handle_height + self->bwidth * 2; ++num; @@ -341,46 +338,99 @@ void frame_adjust_area(ObFrame *self, gboolean moved, self->bwidth = self->cbwidth_x = self->cbwidth_y = 0; } self->rbwidth = self->bwidth; + self->leftb = self->rightb = TRUE; - if (self->max_horz) - self->bwidth = self->cbwidth_x = 0; + if (self->max_horz) { + self->leftb = self->rightb = FALSE; + self->cbwidth_x = 0; + } - STRUT_SET(self->innersize, - self->cbwidth_x, - self->cbwidth_y, - self->cbwidth_x, - self->cbwidth_y); - self->width = self->client->area.width + self->cbwidth_x * 2 - - (self->max_horz ? self->rbwidth * 2 : 0); + self->width = self->client->area.width + self->cbwidth_x * 2; self->width = MAX(self->width, 1); /* no lower than 1 */ - /* set border widths */ - if (!fake) { - XSetWindowBorderWidth(ob_display, self->window, self->bwidth); - XSetWindowBorderWidth(ob_display, self->inner, self->bwidth); - XSetWindowBorderWidth(ob_display, self->title, self->rbwidth); - XSetWindowBorderWidth(ob_display, self->handle, self->rbwidth); - XSetWindowBorderWidth(ob_display, self->lgrip, self->rbwidth); - XSetWindowBorderWidth(ob_display, self->rgrip, self->rbwidth); - XSetWindowBorderWidth(ob_display, self->leftresize, self->bwidth); - XSetWindowBorderWidth(ob_display, self->rightresize, self->bwidth); - } + STRUT_SET(self->size, + self->cbwidth_x + (self->leftb ? self->bwidth : 0), + self->cbwidth_y + self->bwidth, + self->cbwidth_x + (self->rightb ? self->bwidth : 0), + self->cbwidth_y + self->bwidth); if (self->decorations & OB_FRAME_DECOR_TITLEBAR) - self->innersize.top += ob_rr_theme->title_height + self->rbwidth + - (self->rbwidth - self->bwidth); + self->size.top += ob_rr_theme->title_height + self->rbwidth; if (self->decorations & OB_FRAME_DECOR_HANDLE && ob_rr_theme->handle_height > 0) - self->innersize.bottom += ob_rr_theme->handle_height + - self->rbwidth + (self->rbwidth - self->bwidth); + { + self->size.bottom += ob_rr_theme->handle_height + self->bwidth; + } /* position/size and map/unmap all the windows */ if (!fake) { + if (self->bwidth) { + XMoveResizeWindow(ob_display, self->titletop, + ob_rr_theme->grip_width + self->bwidth, 0, + self->client->area.width + + self->cbwidth_x * 2 + self->bwidth * 2 - + (ob_rr_theme->grip_width + self->bwidth) * 2, + self->bwidth); + XMoveResizeWindow(ob_display, self->titletopleft, + 0, 0, + ob_rr_theme->grip_width + self->bwidth, + self->bwidth); + XMoveResizeWindow(ob_display, self->titletopright, + self->client->area.width + + self->cbwidth_x * 2 + self->bwidth * 2 - + ob_rr_theme->grip_width - self->bwidth, + 0, + ob_rr_theme->grip_width + self->bwidth, + self->bwidth); + + XMoveResizeWindow(ob_display, self->titleleft, + 0, self->bwidth, + self->bwidth, + (self->leftb ? + ob_rr_theme->grip_width : + self->size.top - self->bwidth)); + XMoveResizeWindow(ob_display, self->titleright, + self->client->area.width + + self->cbwidth_x * 2 + self->bwidth, + self->bwidth, + self->bwidth, + (self->rightb ? + ob_rr_theme->grip_width : + self->size.top - self->bwidth)); + + XMapWindow(ob_display, self->titletop); + XMapWindow(ob_display, self->titletopleft); + XMapWindow(ob_display, self->titletopright); + XMapWindow(ob_display, self->titleleft); + XMapWindow(ob_display, self->titleright); + + if (self->decorations & OB_FRAME_DECOR_TITLEBAR && + self->rbwidth) + { + XMoveResizeWindow(ob_display, self->titlebottom, + self->bwidth, + ob_rr_theme->title_height + self->bwidth, + self->client->area.width + + self->cbwidth_x * 2, + self->rbwidth); + + XMapWindow(ob_display, self->titlebottom); + } else + XUnmapWindow(ob_display, self->titlebottom); + } else { + XUnmapWindow(ob_display, self->titletop); + XUnmapWindow(ob_display, self->titletopleft); + XUnmapWindow(ob_display, self->titletopright); + XUnmapWindow(ob_display, self->titleleft); + XUnmapWindow(ob_display, self->titleright); + } + if (self->decorations & OB_FRAME_DECOR_TITLEBAR) { XMoveResizeWindow(ob_display, self->title, - -self->bwidth, -self->bwidth, + self->bwidth, self->bwidth, self->width, ob_rr_theme->title_height); + XMapWindow(ob_display, self->title); if (self->decorations & OB_FRAME_DECOR_GRIPS) { @@ -398,35 +448,17 @@ void frame_adjust_area(ObFrame *self, gboolean moved, XMoveWindow(ob_display, self->trrresize, self->width - ob_rr_theme->paddingx - 1, 0); - XMoveResizeWindow(ob_display, self->leftresize, - -(ob_rr_theme->fbwidth * 2) - 1, - 0, - 1, - self->client->area.height + - self->cbwidth_y * 2); - XMoveResizeWindow(ob_display, self->rightresize, - self->client->area.width + - self->cbwidth_x * 2, - 0, - 1, - self->client->area.height + - self->cbwidth_y * 2); - XMapWindow(ob_display, self->topresize); XMapWindow(ob_display, self->tltresize); XMapWindow(ob_display, self->tllresize); XMapWindow(ob_display, self->trtresize); XMapWindow(ob_display, self->trrresize); - XMapWindow(ob_display, self->leftresize); - XMapWindow(ob_display, self->rightresize); } else { XUnmapWindow(ob_display, self->topresize); XUnmapWindow(ob_display, self->tltresize); XUnmapWindow(ob_display, self->tllresize); XUnmapWindow(ob_display, self->trtresize); XUnmapWindow(ob_display, self->trrresize); - XUnmapWindow(ob_display, self->leftresize); - XUnmapWindow(ob_display, self->rightresize); } } else XUnmapWindow(ob_display, self->title); @@ -437,26 +469,143 @@ void frame_adjust_area(ObFrame *self, gboolean moved, layout_title(self); if (!fake) { - if (self->decorations & OB_FRAME_DECOR_HANDLE) - { - gint handle_height; - - if (ob_rr_theme->handle_height > 0) - handle_height = ob_rr_theme->handle_height; - else - handle_height = 1; + if (self->bwidth) { + XMoveResizeWindow(ob_display, self->handlebottom, + ob_rr_theme->grip_width + + self->bwidth * 2, + self->size.top + self->client->area.height + + self->size.bottom - self->bwidth, + self->width - (ob_rr_theme->grip_width + + self->bwidth) * 2, + self->bwidth); + + XMoveResizeWindow(ob_display, self->lgripleft, + 0, + self->size.top + self->client->area.height + + self->size.bottom - + (self->leftb ? + ob_rr_theme->grip_width : + self->size.bottom), + self->bwidth, + (self->leftb ? + ob_rr_theme->grip_width : + self->size.bottom)); + XMoveResizeWindow(ob_display, self->rgripright, + self->size.left + self->client->area.width + + self->size.right - self->bwidth, + self->size.top + self->client->area.height + + self->size.bottom - + (self->leftb ? + ob_rr_theme->grip_width : + self->size.bottom), + self->bwidth, + (self->rightb ? + ob_rr_theme->grip_width : + self->size.bottom)); + + XMoveResizeWindow(ob_display, self->lgripbottom, + self->bwidth, + self->size.top + self->client->area.height + + self->size.bottom - self->bwidth, + ob_rr_theme->grip_width + self->bwidth, + self->bwidth); + XMoveResizeWindow(ob_display, self->rgripbottom, + self->size.left + self->client->area.width + + self->size.right - self->bwidth * 2 - + ob_rr_theme->grip_width, + self->size.top + self->client->area.height + + self->size.bottom - self->bwidth, + ob_rr_theme->grip_width + self->bwidth, + self->bwidth); + + XMapWindow(ob_display, self->handlebottom); + XMapWindow(ob_display, self->lgripleft); + XMapWindow(ob_display, self->rgripright); + XMapWindow(ob_display, self->lgripbottom); + XMapWindow(ob_display, self->rgripbottom); + + if (self->decorations & OB_FRAME_DECOR_HANDLE && + ob_rr_theme->handle_height > 0) + { + XMoveResizeWindow(ob_display, self->handletop, + ob_rr_theme->grip_width + + self->bwidth * 2, + FRAME_HANDLE_Y(self), + self->width - (ob_rr_theme->grip_width + + self->bwidth) * 2, + self->bwidth); + XMapWindow(ob_display, self->handletop); + + if (self->decorations & OB_FRAME_DECOR_GRIPS) { + XMoveResizeWindow(ob_display, self->handleleft, + ob_rr_theme->grip_width, + 0, + self->bwidth, + ob_rr_theme->handle_height); + XMoveResizeWindow(ob_display, self->handleright, + self->width - + ob_rr_theme->grip_width - + self->bwidth, + 0, + self->bwidth, + ob_rr_theme->handle_height); + + XMoveResizeWindow(ob_display, self->lgriptop, + self->bwidth, + FRAME_HANDLE_Y(self), + ob_rr_theme->grip_width + + self->bwidth, + self->bwidth); + XMoveResizeWindow(ob_display, self->rgriptop, + self->size.left + + self->client->area.width + + self->size.right - self->bwidth * 2 - + ob_rr_theme->grip_width, + FRAME_HANDLE_Y(self), + ob_rr_theme->grip_width + + self->bwidth, + self->bwidth); + + XMapWindow(ob_display, self->handleleft); + XMapWindow(ob_display, self->handleright); + XMapWindow(ob_display, self->lgriptop); + XMapWindow(ob_display, self->rgriptop); + } else { + XUnmapWindow(ob_display, self->handleleft); + XUnmapWindow(ob_display, self->handleright); + XUnmapWindow(ob_display, self->lgriptop); + XUnmapWindow(ob_display, self->rgriptop); + } + } else + XUnmapWindow(ob_display, self->handletop); + } else { + XUnmapWindow(ob_display, self->handlebottom); + XUnmapWindow(ob_display, self->lgripleft); + XUnmapWindow(ob_display, self->rgripright); + XUnmapWindow(ob_display, self->lgripbottom); + XUnmapWindow(ob_display, self->rgripbottom); + } + if (self->decorations & OB_FRAME_DECOR_HANDLE && + ob_rr_theme->handle_height > 0) + { XMoveResizeWindow(ob_display, self->handle, - -self->bwidth, FRAME_HANDLE_Y(self), - self->width, handle_height); + self->bwidth, + FRAME_HANDLE_Y(self) + self->bwidth, + self->width, ob_rr_theme->handle_height); XMapWindow(ob_display, self->handle); if (self->decorations & OB_FRAME_DECOR_GRIPS) { - XMoveWindow(ob_display, self->lgrip, - -self->rbwidth, -self->rbwidth); - XMoveWindow(ob_display, self->rgrip, - -self->rbwidth + self->width - - ob_rr_theme->grip_width, -self->rbwidth); + XMoveResizeWindow(ob_display, self->lgrip, + 0, 0, + ob_rr_theme->grip_width, + ob_rr_theme->handle_height); + XMoveResizeWindow(ob_display, self->rgrip, + self->width - ob_rr_theme->grip_width, + 0, + ob_rr_theme->grip_width, + ob_rr_theme->handle_height); + XMapWindow(ob_display, self->lgrip); XMapWindow(ob_display, self->rgrip); } else { @@ -466,31 +615,50 @@ void frame_adjust_area(ObFrame *self, gboolean moved, } else XUnmapWindow(ob_display, self->handle); + if (self->bwidth && !self->max_horz) { + XMoveResizeWindow(ob_display, self->left, + 0, + self->bwidth + ob_rr_theme->grip_width, + self->bwidth, + self->client->area.height + + self->size.top + self->size.bottom - + ob_rr_theme->grip_width * 2); + XMoveResizeWindow(ob_display, self->right, + self->client->area.width + + self->cbwidth_x * 2 + self->bwidth, + self->bwidth + ob_rr_theme->grip_width, + self->bwidth, + self->client->area.height + + self->size.top + self->size.bottom - + ob_rr_theme->grip_width * 2); + + XMapWindow(ob_display, self->left); + XMapWindow(ob_display, self->right); + } else { + XUnmapWindow(ob_display, self->left); + XUnmapWindow(ob_display, self->right); + } + /* move and resize the inner border window which contains the plate */ XMoveResizeWindow(ob_display, self->inner, - self->innersize.left - self->cbwidth_x - - self->bwidth, - self->innersize.top - self->cbwidth_y - - self->bwidth, + 0, + self->size.top - self->cbwidth_y, self->client->area.width + - self->cbwidth_x * 2, + self->cbwidth_x * 2 + + (self->leftb ? self->bwidth : 0) + + (self->rightb ? self->bwidth : 0), self->client->area.height + self->cbwidth_y * 2); /* move the plate */ XMoveWindow(ob_display, self->plate, - self->cbwidth_x, self->cbwidth_y); + (self->leftb ? self->bwidth : 0) + self->cbwidth_x, + self->cbwidth_y); /* when the client has StaticGravity, it likes to move around. */ XMoveWindow(ob_display, self->client->window, 0, 0); } - - STRUT_SET(self->size, - self->innersize.left + self->bwidth, - self->innersize.top + self->bwidth, - self->innersize.right + self->bwidth, - self->innersize.bottom + self->bwidth); } /* shading can change without being moved or resized */ @@ -498,7 +666,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved, self->client->area.width + self->size.left + self->size.right, (self->client->shaded ? - ob_rr_theme->title_height + self->rbwidth * 2: + ob_rr_theme->title_height + self->bwidth * 2: self->client->area.height + self->size.top + self->size.bottom)); @@ -521,9 +689,10 @@ void frame_adjust_area(ObFrame *self, gboolean moved, reflected afterwards. */ XMoveResizeWindow(ob_display, self->window, - self->area.x, self->area.y, - self->area.width - self->bwidth * 2, - self->area.height - self->bwidth * 2); + self->area.x, + self->area.y, + self->area.width, + self->area.height); if (resized) { framerender_frame(self); @@ -550,6 +719,51 @@ void frame_adjust_area(ObFrame *self, gboolean moved, if (resized && (self->decorations & OB_FRAME_DECOR_TITLEBAR)) XResizeWindow(ob_display, self->label, self->label_width, ob_rr_theme->label_height); + + /* set up cursors */ + if (!fake && + (self->functions & OB_CLIENT_FUNC_RESIZE) != + (self->client->functions & OB_CLIENT_FUNC_RESIZE)) + { + gboolean r = self->client->functions & OB_CLIENT_FUNC_RESIZE; + XSetWindowAttributes a; + + a.cursor = ob_cursor(r ? OB_CURSOR_NORTH : OB_CURSOR_NONE); + XChangeWindowAttributes(ob_display, self->topresize, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->titletop, CWCursor, &a); + a.cursor = ob_cursor(r ? OB_CURSOR_NORTHWEST : OB_CURSOR_NONE); + XChangeWindowAttributes(ob_display, self->tltresize, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->tllresize, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->titletopleft, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->titleleft, CWCursor, &a); + a.cursor = ob_cursor(r ? OB_CURSOR_NORTHEAST : OB_CURSOR_NONE); + XChangeWindowAttributes(ob_display, self->trtresize, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->trrresize, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->titletopright, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->titleright, CWCursor, &a); + a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE); + XChangeWindowAttributes(ob_display, self->left, CWCursor, &a); + a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE); + XChangeWindowAttributes(ob_display, self->right, CWCursor, &a); + a.cursor = ob_cursor(r ? OB_CURSOR_SOUTH : OB_CURSOR_NONE); + XChangeWindowAttributes(ob_display, self->handle, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->handletop, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->handlebottom, CWCursor, &a); + a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHWEST : OB_CURSOR_NONE); + XChangeWindowAttributes(ob_display, self->lgrip, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->handleleft, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->lgripleft, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->lgriptop, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->lgripbottom, 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); + + self->functions = self->client->functions; + } } void frame_adjust_client_area(ObFrame *self) @@ -624,8 +838,24 @@ void frame_grab_client(ObFrame *self) g_hash_table_insert(window_map, &self->tllresize, self->client); g_hash_table_insert(window_map, &self->trtresize, self->client); g_hash_table_insert(window_map, &self->trrresize, self->client); - g_hash_table_insert(window_map, &self->leftresize, self->client); - g_hash_table_insert(window_map, &self->rightresize, self->client); + g_hash_table_insert(window_map, &self->left, self->client); + g_hash_table_insert(window_map, &self->right, self->client); + g_hash_table_insert(window_map, &self->titleleft, self->client); + g_hash_table_insert(window_map, &self->titletop, self->client); + g_hash_table_insert(window_map, &self->titletopleft, self->client); + g_hash_table_insert(window_map, &self->titletopright, self->client); + g_hash_table_insert(window_map, &self->titleright, self->client); + g_hash_table_insert(window_map, &self->titlebottom, self->client); + g_hash_table_insert(window_map, &self->handleleft, self->client); + g_hash_table_insert(window_map, &self->handletop, self->client); + g_hash_table_insert(window_map, &self->handleright, self->client); + g_hash_table_insert(window_map, &self->handlebottom, self->client); + g_hash_table_insert(window_map, &self->lgripleft, self->client); + g_hash_table_insert(window_map, &self->lgriptop, self->client); + g_hash_table_insert(window_map, &self->lgripbottom, self->client); + g_hash_table_insert(window_map, &self->rgripright, self->client); + g_hash_table_insert(window_map, &self->rgriptop, self->client); + g_hash_table_insert(window_map, &self->rgripbottom, self->client); } void frame_release_client(ObFrame *self) @@ -684,8 +914,24 @@ void frame_release_client(ObFrame *self) g_hash_table_remove(window_map, &self->tllresize); g_hash_table_remove(window_map, &self->trtresize); g_hash_table_remove(window_map, &self->trrresize); - g_hash_table_remove(window_map, &self->leftresize); - g_hash_table_remove(window_map, &self->rightresize); + g_hash_table_remove(window_map, &self->left); + g_hash_table_remove(window_map, &self->right); + g_hash_table_remove(window_map, &self->titleleft); + g_hash_table_remove(window_map, &self->titletop); + g_hash_table_remove(window_map, &self->titletopleft); + g_hash_table_remove(window_map, &self->titletopright); + g_hash_table_remove(window_map, &self->titleright); + g_hash_table_remove(window_map, &self->titlebottom); + g_hash_table_remove(window_map, &self->handleleft); + g_hash_table_remove(window_map, &self->handletop); + g_hash_table_remove(window_map, &self->handleright); + g_hash_table_remove(window_map, &self->handlebottom); + g_hash_table_remove(window_map, &self->lgripleft); + g_hash_table_remove(window_map, &self->lgriptop); + g_hash_table_remove(window_map, &self->lgripbottom); + g_hash_table_remove(window_map, &self->rgripright); + g_hash_table_remove(window_map, &self->rgriptop); + g_hash_table_remove(window_map, &self->rgripbottom); ob_main_loop_timeout_remove_data(ob_main_loop, flash_timeout, self, TRUE); } @@ -954,24 +1200,39 @@ ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y) return OB_FRAME_CONTEXT_TITLEBAR; } - if (win == self->window) return OB_FRAME_CONTEXT_FRAME; - if (win == self->label) return OB_FRAME_CONTEXT_TITLEBAR; - if (win == self->handle) return OB_FRAME_CONTEXT_BOTTOM; - if (win == self->lgrip) return OB_FRAME_CONTEXT_BLCORNER; - if (win == self->rgrip) return OB_FRAME_CONTEXT_BRCORNER; - if (win == self->topresize) return OB_FRAME_CONTEXT_TOP; - if (win == self->tltresize) return OB_FRAME_CONTEXT_TLCORNER; - if (win == self->tllresize) return OB_FRAME_CONTEXT_TLCORNER; - if (win == self->trtresize) return OB_FRAME_CONTEXT_TRCORNER; - if (win == self->trrresize) return OB_FRAME_CONTEXT_TRCORNER; - if (win == self->leftresize) return OB_FRAME_CONTEXT_LEFT; - if (win == self->rightresize) return OB_FRAME_CONTEXT_RIGHT; - if (win == self->max) return OB_FRAME_CONTEXT_MAXIMIZE; - if (win == self->iconify) return OB_FRAME_CONTEXT_ICONIFY; - if (win == self->close) return OB_FRAME_CONTEXT_CLOSE; - if (win == self->icon) return OB_FRAME_CONTEXT_ICON; - if (win == self->desk) return OB_FRAME_CONTEXT_ALLDESKTOPS; - if (win == self->shade) return OB_FRAME_CONTEXT_SHADE; + if (win == self->window) return OB_FRAME_CONTEXT_FRAME; + if (win == self->label) return OB_FRAME_CONTEXT_TITLEBAR; + if (win == self->handle) return OB_FRAME_CONTEXT_BOTTOM; + if (win == self->handletop) return OB_FRAME_CONTEXT_BOTTOM; + if (win == self->handlebottom) return OB_FRAME_CONTEXT_BOTTOM; + if (win == self->handleleft) return OB_FRAME_CONTEXT_BLCORNER; + if (win == self->lgrip) return OB_FRAME_CONTEXT_BLCORNER; + if (win == self->lgripleft) return OB_FRAME_CONTEXT_BLCORNER; + if (win == self->lgriptop) return OB_FRAME_CONTEXT_BLCORNER; + if (win == self->lgripbottom) return OB_FRAME_CONTEXT_BLCORNER; + if (win == self->handleright) return OB_FRAME_CONTEXT_BRCORNER; + if (win == self->rgrip) return OB_FRAME_CONTEXT_BRCORNER; + if (win == self->rgripright) return OB_FRAME_CONTEXT_BLCORNER; + if (win == self->rgriptop) return OB_FRAME_CONTEXT_BLCORNER; + if (win == self->rgripbottom) return OB_FRAME_CONTEXT_BLCORNER; + if (win == self->titletop) return OB_FRAME_CONTEXT_TOP; + if (win == self->topresize) return OB_FRAME_CONTEXT_TOP; + if (win == self->tltresize) return OB_FRAME_CONTEXT_TLCORNER; + if (win == self->tllresize) return OB_FRAME_CONTEXT_TLCORNER; + if (win == self->titleleft) return OB_FRAME_CONTEXT_TLCORNER; + if (win == self->titletopleft) return OB_FRAME_CONTEXT_TLCORNER; + if (win == self->trtresize) return OB_FRAME_CONTEXT_TRCORNER; + if (win == self->trrresize) return OB_FRAME_CONTEXT_TRCORNER; + if (win == self->titleright) return OB_FRAME_CONTEXT_TRCORNER; + if (win == self->titletopright) return OB_FRAME_CONTEXT_TRCORNER; + if (win == self->left) return OB_FRAME_CONTEXT_LEFT; + if (win == self->right) return OB_FRAME_CONTEXT_RIGHT; + if (win == self->max) return OB_FRAME_CONTEXT_MAXIMIZE; + if (win == self->iconify) return OB_FRAME_CONTEXT_ICONIFY; + if (win == self->close) return OB_FRAME_CONTEXT_CLOSE; + if (win == self->icon) return OB_FRAME_CONTEXT_ICON; + if (win == self->desk) return OB_FRAME_CONTEXT_ALLDESKTOPS; + if (win == self->shade) return OB_FRAME_CONTEXT_SHADE; return OB_FRAME_CONTEXT_NONE; } @@ -1185,7 +1446,7 @@ static gboolean frame_animate_iconify(gpointer p) x = iconx; y = icony; w = iconw; - h = self->innersize.top; /* just the titlebar */ + h = self->size.top; /* just the titlebar */ } if (time > 0) { @@ -1202,7 +1463,7 @@ static gboolean frame_animate_iconify(gpointer p) x = x - (dx * elapsed) / FRAME_ANIMATE_ICONIFY_TIME; y = y - (dy * elapsed) / FRAME_ANIMATE_ICONIFY_TIME; w = w - (dw * elapsed) / FRAME_ANIMATE_ICONIFY_TIME; - h = self->innersize.top; /* just the titlebar */ + h = self->size.top; /* just the titlebar */ } if (time == 0) diff --git a/openbox/frame.h b/openbox/frame.h index 13e49564..b1ed8183 100644 --- a/openbox/frame.h +++ b/openbox/frame.h @@ -83,6 +83,7 @@ struct _ObFrame Rect area; gboolean visible; + guint functions; guint decorations; gboolean max_horz; @@ -99,13 +100,32 @@ struct _ObFrame Window lgrip; Window rgrip; + /* These are borders of the frame and its elements */ + Window titleleft; + Window titletop; + Window titletopleft; + Window titletopright; + Window titleright; + Window titlebottom; + Window left; + Window right; + Window handleleft; + Window handletop; + Window handleright; + Window handlebottom; + Window lgriptop; + Window lgripleft; + Window lgripbottom; + Window rgriptop; + Window rgripright; + Window rgripbottom; + + /* These are resize handles inside the titlebar */ Window topresize; Window tltresize; Window tllresize; Window trtresize; Window trrresize; - Window leftresize; - Window rightresize; Colormap colormap; @@ -117,8 +137,6 @@ struct _ObFrame RrAppearance *a_unfocused_handle; RrAppearance *a_focused_handle; - Strut innersize; - GSList *clients; gint icon_on; /* if the window icon button is on */ @@ -139,9 +157,11 @@ struct _ObFrame gint max_x; /* x-position of the window maximize button */ gint close_x; /* x-position of the window close button */ gint bwidth; /* border width */ - gint rbwidth; /* title border width */ + gint rbwidth; /* border width between the title and client */ gint cbwidth_x; /* client border width */ gint cbwidth_y; /* client border width */ + gboolean leftb; /* is there a border to the left of the client? */ + gboolean rightb; /* is there a border to the right of the client?*/ /* the leftmost and rightmost elements in the titlebar */ ObFrameContext leftmost; diff --git a/openbox/framerender.c b/openbox/framerender.c index 78c1d02f..5fdc8a95 100644 --- a/openbox/framerender.c +++ b/openbox/framerender.c @@ -46,13 +46,47 @@ void framerender_frame(ObFrame *self) px = (self->focused ? RrColorPixel(ob_rr_theme->frame_focused_border_color) : RrColorPixel(ob_rr_theme->frame_unfocused_border_color)); - XSetWindowBorder(ob_display, self->window, px); - XSetWindowBorder(ob_display, self->title, px); - XSetWindowBorder(ob_display, self->handle, px); - XSetWindowBorder(ob_display, self->rgrip, px); - XSetWindowBorder(ob_display, self->lgrip, px); - XSetWindowBorder(ob_display, self->leftresize, px); - XSetWindowBorder(ob_display, self->rightresize, px); + + XSetWindowBackground(ob_display, self->left, px); + XClearWindow(ob_display, self->left); + XSetWindowBackground(ob_display, self->right, px); + XClearWindow(ob_display, self->right); + + XSetWindowBackground(ob_display, self->titleleft, px); + XClearWindow(ob_display, self->titleleft); + XSetWindowBackground(ob_display, self->titletop, px); + XClearWindow(ob_display, self->titletop); + XSetWindowBackground(ob_display, self->titletopleft, px); + XClearWindow(ob_display, self->titletopleft); + XSetWindowBackground(ob_display, self->titletopright, px); + XClearWindow(ob_display, self->titletopright); + XSetWindowBackground(ob_display, self->titleright, px); + XClearWindow(ob_display, self->titleright); + XSetWindowBackground(ob_display, self->titlebottom, px); + XClearWindow(ob_display, self->titlebottom); + + XSetWindowBackground(ob_display, self->handleleft, px); + XClearWindow(ob_display, self->handleleft); + XSetWindowBackground(ob_display, self->handletop, px); + XClearWindow(ob_display, self->handletop); + XSetWindowBackground(ob_display, self->handleright, px); + XClearWindow(ob_display, self->handleright); + XSetWindowBackground(ob_display, self->handlebottom, px); + XClearWindow(ob_display, self->handlebottom); + + XSetWindowBackground(ob_display, self->lgripleft, px); + XClearWindow(ob_display, self->lgripleft); + XSetWindowBackground(ob_display, self->lgriptop, px); + XClearWindow(ob_display, self->lgriptop); + XSetWindowBackground(ob_display, self->lgripbottom, px); + XClearWindow(ob_display, self->lgripbottom); + + XSetWindowBackground(ob_display, self->rgripright, px); + XClearWindow(ob_display, self->rgripright); + XSetWindowBackground(ob_display, self->rgriptop, px); + XClearWindow(ob_display, self->rgriptop); + XSetWindowBackground(ob_display, self->rgripbottom, px); + XClearWindow(ob_display, self->rgripbottom); } if (self->decorations & OB_FRAME_DECOR_TITLEBAR) { diff --git a/openbox/menu.c b/openbox/menu.c index dbb0c701..66d2ac7c 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -333,6 +333,13 @@ ObMenu* menu_new(const gchar *name, const gchar *title, self->more_menu->data = data; self->more_menu->shortcut = g_unichar_tolower(g_utf8_get_char("M")); + self->more_menu->show_func = self->show_func; + self->more_menu->hide_func = self->hide_func; + self->more_menu->update_func = self->update_func; + self->more_menu->execute_func = self->execute_func; + self->more_menu->destroy_func = self->destroy_func; + self->more_menu->place_func = self->place_func; + return self; } @@ -531,32 +538,50 @@ ObMenuEntry* menu_add_separator(ObMenu *self, gint id, const gchar *label) void menu_set_show_func(ObMenu *self, ObMenuShowFunc func) { - self->show_func = func; + do { + self->show_func = func; + self = self->more_menu; + } while (self); } void menu_set_hide_func(ObMenu *self, ObMenuHideFunc func) { - self->hide_func = func; + do { + self->hide_func = func; + self = self->more_menu; + } while (self); } void menu_set_update_func(ObMenu *self, ObMenuUpdateFunc func) { - self->update_func = func; + do { + self->update_func = func; + self = self->more_menu; + } while (self); } void menu_set_execute_func(ObMenu *self, ObMenuExecuteFunc func) { - self->execute_func = func; + do { + self->execute_func = func; + self = self->more_menu; + } while (self); } void menu_set_destroy_func(ObMenu *self, ObMenuDestroyFunc func) { - self->destroy_func = func; + do { + self->destroy_func = func; + self = self->more_menu; + } while (self); } void menu_set_place_func(ObMenu *self, ObMenuPlaceFunc func) { - self->place_func = func; + do { + self->place_func = func; + self = self->more_menu; + } while (self); } ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id) diff --git a/openbox/menuframe.h b/openbox/menuframe.h index e1f4b15b..75e03da4 100644 --- a/openbox/menuframe.h +++ b/openbox/menuframe.h @@ -77,9 +77,6 @@ struct _ObMenuFrame struct _ObMenuEntryFrame { - /* if this is true then it doesn't have an entry to point to */ - gboolean more; - struct _ObMenuEntry *entry; ObMenuFrame *frame; diff --git a/openbox/openbox.c b/openbox/openbox.c index 7270379e..ec5c7db2 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -301,8 +301,8 @@ gint main(gint argc, gchar **argv) moveresize_startup(reconfigure); keyboard_startup(reconfigure); mouse_startup(reconfigure); - menu_startup(reconfigure); menu_frame_startup(reconfigure); + menu_startup(reconfigure); if (!reconfigure) { guint32 xid; @@ -344,8 +344,8 @@ gint main(gint argc, gchar **argv) client_unmanage_all(); } - menu_frame_shutdown(reconfigure); menu_shutdown(reconfigure); + menu_frame_shutdown(reconfigure); mouse_shutdown(reconfigure); keyboard_shutdown(reconfigure); moveresize_shutdown(reconfigure); -- 2.34.1