1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-21 21:38:00 +01:00
Files
wmaker/src/switchmenu.c
Rodolfo García Peñas (kix) f846b7cdd3 Window comments cleanup
This patch only add some tabs the window.h (only window struct area).

The main change is that moves this block to switchpanel.c, because
is only used there:

       ((w)->wm_gnustep_attr->flags & GSWindowLevelAttr) && \
       ((w)->wm_gnustep_attr->window_level == WMMainMenuWindowLevel || \
        (w)->wm_gnustep_attr->window_level == WMSubmenuWindowLevel))

The patch also include two comments in the window's image:

- WIcon icon is only used when the window is minimized, else is NULL
- RImage has the window image, used in switchpanel,...
2012-11-11 12:00:59 +00:00

427 lines
11 KiB
C

/*
* Window Maker window manager
*
* Copyright (c) 1997 Shige Abe
* Copyright (c) 1997-2003 Alfredo K. Kojima
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "WindowMaker.h"
#include "window.h"
#include "actions.h"
#include "client.h"
#include "funcs.h"
#include "stacking.h"
#include "workspace.h"
#include "framewin.h"
#define IS_GNUSTEP_MENU(w) ((w)->wm_gnustep_attr && \
((w)->wm_gnustep_attr->flags & GSWindowLevelAttr) && \
((w)->wm_gnustep_attr->window_level == WMMainMenuWindowLevel || \
(w)->wm_gnustep_attr->window_level == WMSubmenuWindowLevel))
/********* Global Variables *******/
extern WPreferences wPreferences;
static int initialized = 0;
static void observer(void *self, WMNotification * notif);
static void wsobserver(void *self, WMNotification * notif);
/*
* FocusWindow
*
* - Needs to check if already in the right workspace before
* calling wChangeWorkspace?
*
* Order:
* Switch to correct workspace
* Unshade if shaded
* If iconified then deiconify else focus/raise.
*/
static void focusWindow(WMenu * menu, WMenuEntry * entry)
{
WWindow *wwin;
WScreen *scr;
int x, y, move = 0;
wwin = (WWindow *) entry->clientdata;
scr = wwin->screen_ptr;
wMakeWindowVisible(wwin);
x = wwin->frame_x;
y = wwin->frame_y;
/* bring window back to visible area */
move = wScreenBringInside(scr, &x, &y, wwin->frame->core->width, wwin->frame->core->height);
if (move) {
wWindowConfigure(wwin, x, y, wwin->client.width, wwin->client.height);
}
}
void InitializeSwitchMenu(void)
{
if (!initialized) {
initialized = 1;
WMAddNotificationObserver(observer, NULL, WMNManaged, NULL);
WMAddNotificationObserver(observer, NULL, WMNUnmanaged, NULL);
WMAddNotificationObserver(observer, NULL, WMNChangedWorkspace, NULL);
WMAddNotificationObserver(observer, NULL, WMNChangedState, NULL);
WMAddNotificationObserver(observer, NULL, WMNChangedFocus, NULL);
WMAddNotificationObserver(observer, NULL, WMNChangedStacking, NULL);
WMAddNotificationObserver(observer, NULL, WMNChangedName, NULL);
WMAddNotificationObserver(wsobserver, NULL, WMNWorkspaceChanged, NULL);
WMAddNotificationObserver(wsobserver, NULL, WMNWorkspaceNameChanged, NULL);
}
}
/*
*
* Open switch menu
*
*/
void OpenSwitchMenu(WScreen * scr, int x, int y, int keyboard)
{
WMenu *switchmenu = scr->switch_menu;
WWindow *wwin;
if (switchmenu) {
if (switchmenu->flags.mapped) {
if (!switchmenu->flags.buttoned) {
wMenuUnmap(switchmenu);
} else {
wRaiseFrame(switchmenu->frame->core);
if (keyboard)
wMenuMapAt(switchmenu, 0, 0, True);
else
wMenuMapCopyAt(switchmenu, x - switchmenu->frame->core->width / 2, y);
}
} else {
if (keyboard && x == scr->scr_width / 2 && y == scr->scr_height / 2) {
y = y - switchmenu->frame->core->height / 2;
}
wMenuMapAt(switchmenu, x - switchmenu->frame->core->width / 2, y, keyboard);
}
return;
}
switchmenu = wMenuCreate(scr, _("Windows"), True);
scr->switch_menu = switchmenu;
wwin = scr->focused_window;
while (wwin) {
UpdateSwitchMenu(scr, wwin, ACTION_ADD);
wwin = wwin->prev;
}
if (switchmenu) {
int newx, newy;
if (!switchmenu->flags.realized)
wMenuRealize(switchmenu);
if (keyboard && x == 0 && y == 0) {
newx = newy = 0;
} else if (keyboard && x == scr->scr_width / 2 && y == scr->scr_height / 2) {
newx = x - switchmenu->frame->core->width / 2;
newy = y - switchmenu->frame->core->height / 2;
} else {
newx = x - switchmenu->frame->core->width / 2;
newy = y;
}
wMenuMapAt(switchmenu, newx, newy, keyboard);
}
}
static int menuIndexForWindow(WMenu * menu, WWindow * wwin, int old_pos)
{
int idx;
if (menu->entry_no <= old_pos)
return -1;
#define WS(i) ((WWindow*)menu->entries[i]->clientdata)->frame->workspace
if (old_pos >= 0) {
if (WS(old_pos) >= wwin->frame->workspace
&& (old_pos == 0 || WS(old_pos - 1) <= wwin->frame->workspace)) {
return old_pos;
}
}
#undef WS
for (idx = 0; idx < menu->entry_no; idx++) {
WWindow *tw = (WWindow *) menu->entries[idx]->clientdata;
if (!IS_OMNIPRESENT(tw)
&& tw->frame->workspace > wwin->frame->workspace) {
break;
}
}
return idx;
}
/*
* Update switch menu
*/
void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
{
WMenu *switchmenu = scr->switch_menu;
WMenuEntry *entry;
char title[MAX_MENU_TEXT_LENGTH + 6];
int len = sizeof(title);
int i;
int checkVisibility = 0;
if (!wwin->screen_ptr->switch_menu)
return;
/*
* This menu is updated under the following conditions:
*
* 1. When a window is created.
* 2. When a window is destroyed.
*
* 3. When a window changes it's title.
* 4. When a window changes its workspace.
*/
if (action == ACTION_ADD) {
char *t;
int idx;
if (wwin->flags.internal_window || WFLAGP(wwin, skip_window_list) || IS_GNUSTEP_MENU(wwin)) {
return;
}
if (wwin->frame->title)
snprintf(title, len, "%s", wwin->frame->title);
else
snprintf(title, len, "%s", DEF_WINDOW_TITLE);
t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
if (IS_OMNIPRESENT(wwin))
idx = -1;
else {
idx = menuIndexForWindow(switchmenu, wwin, -1);
}
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
wfree(t);
entry->flags.indicator = 1;
entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH + 8);
if (IS_OMNIPRESENT(wwin))
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH, "[*]");
else
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH, "[%s]",
scr->workspaces[wwin->frame->workspace]->name);
if (wwin->flags.hidden) {
entry->flags.indicator_type = MI_HIDDEN;
entry->flags.indicator_on = 1;
} else if (wwin->flags.miniaturized) {
entry->flags.indicator_type = MI_MINIWINDOW;
entry->flags.indicator_on = 1;
} else if (wwin->flags.focused) {
entry->flags.indicator_type = MI_DIAMOND;
entry->flags.indicator_on = 1;
} else if (wwin->flags.shaded) {
entry->flags.indicator_type = MI_SHADED;
entry->flags.indicator_on = 1;
}
wMenuRealize(switchmenu);
checkVisibility = 1;
} else {
char *t;
for (i = 0; i < switchmenu->entry_no; i++) {
entry = switchmenu->entries[i];
/* this is the entry that was changed */
if (entry->clientdata == wwin) {
switch (action) {
case ACTION_REMOVE:
wMenuRemoveItem(switchmenu, i);
wMenuRealize(switchmenu);
checkVisibility = 1;
break;
case ACTION_CHANGE:
if (entry->text)
wfree(entry->text);
if (wwin->frame->title)
snprintf(title, MAX_MENU_TEXT_LENGTH, "%s", wwin->frame->title);
else
snprintf(title, MAX_MENU_TEXT_LENGTH, "%s", DEF_WINDOW_TITLE);
t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
entry->text = t;
wMenuRealize(switchmenu);
checkVisibility = 1;
break;
case ACTION_CHANGE_WORKSPACE:
if (entry->rtext) {
int idx = -1;
char *t, *rt;
int it, ion;
if (IS_OMNIPRESENT(wwin)) {
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH, "[*]");
} else {
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH,
"[%s]",
scr->workspaces[wwin->frame->workspace]->name);
}
rt = entry->rtext;
entry->rtext = NULL;
t = entry->text;
entry->text = NULL;
it = entry->flags.indicator_type;
ion = entry->flags.indicator_on;
if (!IS_OMNIPRESENT(wwin) && idx < 0) {
idx = menuIndexForWindow(switchmenu, wwin, i);
}
wMenuRemoveItem(switchmenu, i);
entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin);
wfree(t);
entry->rtext = rt;
entry->flags.indicator = 1;
entry->flags.indicator_type = it;
entry->flags.indicator_on = ion;
}
wMenuRealize(switchmenu);
checkVisibility = 1;
break;
case ACTION_CHANGE_STATE:
if (wwin->flags.hidden) {
entry->flags.indicator_type = MI_HIDDEN;
entry->flags.indicator_on = 1;
} else if (wwin->flags.miniaturized) {
entry->flags.indicator_type = MI_MINIWINDOW;
entry->flags.indicator_on = 1;
} else if (wwin->flags.shaded && !wwin->flags.focused) {
entry->flags.indicator_type = MI_SHADED;
entry->flags.indicator_on = 1;
} else {
entry->flags.indicator_on = wwin->flags.focused;
entry->flags.indicator_type = MI_DIAMOND;
}
break;
}
break;
}
}
}
if (checkVisibility) {
int tmp;
tmp = switchmenu->frame->top_width + 5;
/* if menu got unreachable, bring it to a visible place */
if (switchmenu->frame_x < tmp - (int)switchmenu->frame->core->width) {
wMenuMove(switchmenu, tmp - (int)switchmenu->frame->core->width,
switchmenu->frame_y, False);
}
}
wMenuPaint(switchmenu);
}
static void UpdateSwitchMenuWorkspace(WScreen *scr, int workspace)
{
WMenu *menu = scr->switch_menu;
int i;
WWindow *wwin;
if (!menu)
return;
for (i = 0; i < menu->entry_no; i++) {
wwin = (WWindow *) menu->entries[i]->clientdata;
if (wwin->frame->workspace == workspace && !IS_OMNIPRESENT(wwin)) {
if (IS_OMNIPRESENT(wwin))
snprintf(menu->entries[i]->rtext, MAX_WORKSPACENAME_WIDTH, "[*]");
else
snprintf(menu->entries[i]->rtext, MAX_WORKSPACENAME_WIDTH, "[%s]",
scr->workspaces[wwin->frame->workspace]->name);
menu->flags.realized = 0;
}
}
if (!menu->flags.realized)
wMenuRealize(menu);
}
static void observer(void *self, WMNotification * notif)
{
WWindow *wwin = (WWindow *) WMGetNotificationObject(notif);
const char *name = WMGetNotificationName(notif);
void *data = WMGetNotificationClientData(notif);
if (!wwin)
return;
if (strcmp(name, WMNManaged) == 0)
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_ADD);
else if (strcmp(name, WMNUnmanaged) == 0)
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_REMOVE);
else if (strcmp(name, WMNChangedWorkspace) == 0)
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_WORKSPACE);
else if (strcmp(name, WMNChangedFocus) == 0)
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
else if (strcmp(name, WMNChangedName) == 0)
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE);
else if (strcmp(name, WMNChangedState) == 0) {
if (strcmp((char *)data, "omnipresent") == 0) {
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_WORKSPACE);
} else {
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
}
}
}
static void wsobserver(void *self, WMNotification * notif)
{
WScreen *scr = (WScreen *) WMGetNotificationObject(notif);
const char *name = WMGetNotificationName(notif);
void *data = WMGetNotificationClientData(notif);
if (strcmp(name, WMNWorkspaceNameChanged) == 0) {
UpdateSwitchMenuWorkspace(scr, (uintptr_t)data);
} else if (strcmp(name, WMNWorkspaceChanged) == 0) {
}
}