mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
297 lines
7.4 KiB
C++
297 lines
7.4 KiB
C++
#include "config.h"
|
|
|
|
#include "debug.h"
|
|
#include "Winhints.h"
|
|
#include "Frame.h"
|
|
#include "Windowmanager.h"
|
|
#include "Desktop.h"
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
Desktop_List desktops;
|
|
|
|
int Desktop::desktop_count_ = 0;
|
|
Desktop* Desktop::current_ = 0;
|
|
|
|
Desktop *Desktop::desktop(int num)
|
|
{
|
|
if(num>=(int)desktops.size()) return desktops.item(desktops.size()-1);
|
|
if(num<1) return desktops.item(0);
|
|
|
|
for(uint n=0; n<desktops.size(); n++) {
|
|
Desktop *d=desktops[n];
|
|
if(d->number()==num) return d;
|
|
}
|
|
return desktops.item(0);
|
|
}
|
|
|
|
Desktop *Desktop::next()
|
|
{
|
|
uint num = current()->number();
|
|
num++;
|
|
if(num > desktops.count())
|
|
current(0);
|
|
else
|
|
current(num);
|
|
return current();
|
|
}
|
|
|
|
Desktop *Desktop::prev()
|
|
{
|
|
int num = current()->number();
|
|
num--;
|
|
if(num < 1)
|
|
current(desktops.count());
|
|
else
|
|
current(num);
|
|
return current();
|
|
}
|
|
|
|
Desktop::Desktop(const char *name)
|
|
{
|
|
desktops.append(this);
|
|
number_ = desktops.count();
|
|
|
|
DBG("::Desktop %d", number_);
|
|
|
|
if(name)
|
|
name_ = strdup(name);
|
|
else
|
|
name_ = 0;
|
|
}
|
|
|
|
Desktop::~Desktop()
|
|
{
|
|
desktops.remove(this);
|
|
if(current_==this) {
|
|
current(desktop(number()+1));
|
|
}
|
|
|
|
// put any clients onto another desktop:
|
|
for(uint n=0; n<map_order.size(); n++)
|
|
if(map_order[n]->desktop()==this)
|
|
map_order[n]->desktop(current_);
|
|
|
|
if(name_) delete []name_;
|
|
}
|
|
|
|
void Desktop::name(const char *name)
|
|
{
|
|
if(name_) delete []name_;
|
|
if(name) name_ = strdup(name);
|
|
}
|
|
|
|
extern Frame *menu_frame; //Frame where titlebar menu is popped up. Set only when changing window desktop.
|
|
void Desktop::current(Desktop *cur)
|
|
{
|
|
if(cur == current_) return;
|
|
|
|
current_ = cur;
|
|
|
|
Frame *f = 0, *top = 0;
|
|
for(uint n=0; n<stack_order.size(); n++) {
|
|
f = stack_order[n];
|
|
if(!f->desktop() && f->state()!=UNMAPPED) {
|
|
if(f->state()==OTHER_DESKTOP) f->state(NORMAL);
|
|
if(!f->frame_flag(SKIP_FOCUS) && !f->frame_flag(SKIP_LIST)) top=f;
|
|
continue;
|
|
}
|
|
|
|
// Keep this window in 'NORMAL' state.
|
|
if(f==menu_frame && f->state()==NORMAL) {
|
|
top=f;
|
|
continue;
|
|
}
|
|
|
|
if(f->state()!=UNMAPPED) {
|
|
if(f->desktop()==cur) {
|
|
if(f->state()==OTHER_DESKTOP) {
|
|
f->state(NORMAL);
|
|
}
|
|
top=f;
|
|
|
|
} else {
|
|
|
|
if(f->state()==NORMAL) {
|
|
f->state(OTHER_DESKTOP);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(cur!=0) {
|
|
setProperty(fl_xid(root), _XA_NET_CURRENT_DESKTOP, XA_CARDINAL, cur->number()-1);
|
|
if(top) {
|
|
top->activate();
|
|
top->raise();
|
|
}
|
|
DBG("Went to desktop: %d", cur->number());
|
|
}
|
|
}
|
|
|
|
Desktop* Desktop::add(const char *name)
|
|
{
|
|
Desktop *d = new Desktop(name);
|
|
if(!name) {
|
|
char buf[32]; sprintf(buf, _("Workspace %d"), d->number());
|
|
d->name(buf);
|
|
}
|
|
return d;
|
|
}
|
|
|
|
// Updates viewport info, since we dont support LARGE desktops
|
|
// According to NET-WM speac these MUST be set to (0,0)
|
|
void Desktop::update_desktop_viewport()
|
|
{
|
|
CARD32 val[2] = { 0, 0 };
|
|
XChangeProperty(fl_display, root_win, _XA_NET_DESKTOP_VIEWPORT, XA_CARDINAL,
|
|
32, PropModeReplace, (unsigned char *)&val, 2);
|
|
}
|
|
|
|
void Desktop::update_desktop_geometry()
|
|
{
|
|
CARD32 val[2] = { Fl::w(), Fl::h() };
|
|
XChangeProperty(fl_display, root_win, _XA_NET_DESKTOP_GEOMETRY, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *)&val, 2);
|
|
|
|
}
|
|
|
|
void Desktop::update_desktop_workarea()
|
|
{
|
|
CARD32 val[4];
|
|
val[0] = root->x();
|
|
val[1] = root->y();
|
|
val[2] = root->w();
|
|
val[3] = root->h();
|
|
|
|
XChangeProperty(fl_display, root_win, _XA_NET_WORKAREA, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *)&val, 4);
|
|
}
|
|
|
|
void Desktop::update_desktop_names(bool send)
|
|
{
|
|
char *workspaces[16] = { 0 };
|
|
int cnt=0;
|
|
for(uint n=0; n<desktops.size(); n++) {
|
|
Desktop *d=desktops[n];
|
|
if(!d->name()) {
|
|
char tmp[64]; snprintf(tmp, sizeof(tmp)-1, _("Workspace %d"), cnt+1);
|
|
workspaces[cnt] = strdup(tmp);
|
|
} else {
|
|
workspaces[cnt] = strdup(d->name());
|
|
}
|
|
cnt++;
|
|
}
|
|
|
|
if(send) {
|
|
XTextProperty names;
|
|
if(XStringListToTextProperty((char **)workspaces, cnt, &names)) {
|
|
XSetTextProperty(fl_display, fl_xid(root), &names, _XA_NET_DESKTOP_NAMES);
|
|
XFree(names.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Updates both NET desktop count atoms
|
|
void Desktop::update_desktop_count(uint cnt, bool send)
|
|
{
|
|
if(cnt<0) cnt=0;
|
|
if(cnt>8) cnt=8;
|
|
|
|
Desktop::desktop_count_ = cnt;
|
|
if(send) {
|
|
setProperty(fl_xid(root), _XA_NET_NUM_DESKTOPS, XA_CARDINAL, Desktop::desktop_count_);
|
|
|
|
update_desktop_viewport();
|
|
update_desktop_workarea();
|
|
update_desktop_geometry();
|
|
}
|
|
|
|
if(desktops.count()<cnt) {
|
|
int add = cnt-desktops.count();
|
|
for(int a=0; a<add; a++)
|
|
Desktop::add();
|
|
DBG("Increased desktops to %d", desktops.count());
|
|
} else if(desktops.count()>cnt) {
|
|
int del = desktops.count()-cnt;
|
|
for(int a=0; a<del; a++) {
|
|
Desktop *d = desktops.item(desktops.size()-1);
|
|
delete d;
|
|
}
|
|
DBG("Decreased desktops to %d", desktops.count());
|
|
}
|
|
}
|
|
|
|
void Desktop::set_names()
|
|
{
|
|
int length=0;
|
|
char *buffer=0;
|
|
|
|
XTextProperty names;
|
|
// First try to get NET desktop names
|
|
XGetTextProperty(fl_display, RootWindow(fl_display, fl_screen), &names, _XA_NET_DESKTOP_NAMES);
|
|
buffer = (char *)names.value;
|
|
length = names.nitems;
|
|
|
|
if(buffer) {
|
|
char* c = buffer;
|
|
for (int i = 1; c < buffer+length; i++) {
|
|
char* d = c;
|
|
while(*d) d++;
|
|
Desktop::desktop(i)->name(c);
|
|
c = d+1;
|
|
}
|
|
XFree(names.value);
|
|
|
|
} else {
|
|
// No desktop names in XServer already, read from ede config file
|
|
Fl_Config cfg(fl_find_config_file("ede.conf", 0));
|
|
cfg.set_section("Workspaces");
|
|
char tmp[128], name[128];
|
|
for(uint n=1; n<=8; n++) {
|
|
snprintf(tmp, sizeof(tmp)-1, "Workspace%d", n);
|
|
if(!cfg.read(tmp, name, 0, sizeof(name))) {
|
|
if(n<=desktops.count()) {
|
|
Desktop::desktop(n)->name(name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// called at startup, read the list of desktops from the root
|
|
// window properties, or on failure make some default desktops.
|
|
void init_desktops()
|
|
{
|
|
int current_num=0, p=0;
|
|
|
|
p = getIntProperty(fl_xid(root), _XA_NET_NUM_DESKTOPS, XA_CARDINAL, -1);
|
|
if(p<0) {
|
|
// No desktop count in XServer already, read from ede config file
|
|
Fl_Config cfg(fl_find_config_file("ede.conf", 0));
|
|
cfg.get("Workspaces", "Count", p, 4);
|
|
}
|
|
|
|
DBG("Total Desks: %d", p);
|
|
|
|
Desktop::update_desktop_count(p);
|
|
Desktop::set_names();
|
|
Desktop::update_desktop_names(true);
|
|
|
|
// Try to get current NET desktop
|
|
p = getIntProperty(fl_xid(root), _XA_NET_CURRENT_DESKTOP, XA_CARDINAL, -1);
|
|
// If not valid number, try GNOME
|
|
if(p >= 0 && p < Desktop::desktop_count()+1)
|
|
current_num = p+1; // Got valid
|
|
else
|
|
current_num = 1; // Not valid, use 1
|
|
|
|
DBG("Current desktop: %d", current_num);
|
|
Desktop::current(Desktop::desktop(current_num));
|
|
|
|
DBG("Desktops inited!");
|
|
}
|
|
|