The code for my (very useful if you ask me) AutoRaise deskbar addon that brings the focussed window to front after a timeout.

MIT of course.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25442 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol 2008-05-11 00:40:56 +00:00
parent a4a6c26a2a
commit fe8567ec1c
10 changed files with 1281 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,41 @@
AutoRaise : beyond FocusFollowsMouse, for BeOS
(c) 2002, mmu_man, revol@free.fr
Released under MIT licence,
usual disclaimer applies, blah blah blah...
This tiny Deskbar replicant is a window autoraiser. It will bring to front whatever window is under the mouse after a selectable delay.
Installation:
- put the AutoRaise folder where you want (I suggest /boot/apps),
- you can delete the src/ folder if you aren't interested in the sources,
- double-click on either the 'Put me in Deskbar', or 'Put me in Deskbar (persistant)', the later will keep it in between boots.
Alternately, you can run it in a Terminal:
AutoRaise --deskbar
or, if you want it to be reloaded on each boot:
AutoRaise --deskbar --persist
Customisation:
* Left-click will toggles activation.
* right-click brings a menu:
* Active: check it to activate auto raising
* Mode: The default mode (option 1) is to raise every window. You can also set it so it only raises the Deskbar, whenever you have the mouse on top of it, even if you have a window over it (option 2), or rather only when your mouse is over a visible part of it (option 3).
* Inactive behaviour: This sets up the mouse behaviour when AutoRaise is NOT active. This takes effects only when it's not active (either immediately or when you disables it). It's the same control as the "Focus follows mouse" in the Mouse preferences panel, however I recommend you don't run the preference panel while AutoRaise is active, as it will conflict, and you will get funky behaviour :))
* Delay: allows you to change the delay before the focused window is brought to front.
Informations:
There is a special version for Dano, since it provides some helpful API...
To get it just recompile it, it will detect itself it is compiled under R5.1.
I'm not sure the Dano version still compiles however, as I begun this proggy under Dano, but finished it in R5, and didn't check back, since I don't use it much.
The R5 version has a problem on tabs, because there isn't any mean to know the window tab position and size. So it acts as if the tab was as wide as the window, (it uses the outer region).
The code was based on parts of Deskscope, 2000 Shamyl Zakariya
Sorry it's really ugly, but it does the job :)

View File

@ -0,0 +1,98 @@
#include "AutoRaiseApp.h"
#include "AutoRaiseIcon.h"
AutoRaiseApp::AutoRaiseApp()
: BApplication( APP_SIG )
{
removeFromDeskbar(NULL);
_directToDeskbar = false;
//since the tray item shows an icon, and the class TrayView needs to be able to know the location
//of the executing binary, we write into the settings file this critical information when the app is fired up
app_info info;
be_app->GetAppInfo(&info);
//now, put the path into the settings file
AutoRaiseSettings settings;
settings.SetAppPath(info.ref);
}
AutoRaiseApp::~AutoRaiseApp()
{
return;
}
void AutoRaiseApp::ArgvReceived(int32 argc, char ** argv)
{
BString option;
bool inDeskbar = false, persist = false;
for (int32 i = 1; i < argc; i++)
{
option = argv[i];
if (option.IFindFirst("deskbar") != B_ERROR)
inDeskbar = true;
if (option.IFindFirst("persist") != B_ERROR)
persist = true;
}
if (inDeskbar && !persist)
{
printf(APP_NAME" being put into Tray (one shot)...\n");
PutInTray(false);
_directToDeskbar = true;
}
else if (inDeskbar && persist)
{
printf(APP_NAME" being put into Tray (persistant)...\n");
PutInTray(true);
_directToDeskbar = true;
}
else
{
printf("\nUsage: "APP_NAME" [options]\n\t--deskbar\twill not open window, will just put "APP_NAME" into tray\n\t--persist will put "APP_NAME" into tray such that it remains between bootings\n");
}
be_app_messenger.SendMessage(B_QUIT_REQUESTED);
}
void AutoRaiseApp::ReadyToRun()
{
if (!_directToDeskbar)
{
printf("\nUsage: " APP_NAME " [options]\n\t--deskbar\twill not open window, will just put " APP_NAME " into tray\n\t--persist will put " APP_NAME " into tray such that it remains between bootings\n");
BAlert *alert = new BAlert("usage box", APP_NAME ", (c) 2002, mmu_man\nUsage: " APP_NAME " [options]\n\t--deskbar\twill not open window, will just put " APP_NAME " into tray\n\t--persist will put "APP_NAME" into tray such that it remains between bootings\n", "Ok", NULL, NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_INFO_ALERT);
alert->SetShortcut(0, B_ENTER);
alert->Go();
be_app_messenger.SendMessage(B_QUIT_REQUESTED);
}
}
void AutoRaiseApp::PutInTray(bool persist)
{
BDeskbar db;
if (!persist)
db.AddItem(new TrayView);
else {
BRoster roster;
entry_ref ref;
roster.FindApp(APP_SIG, &ref);
int32 id;
db.AddItem(&ref, &id);
}
}
int main()
{
AutoRaiseApp *app = new AutoRaiseApp();
app->Run();
}

View File

@ -0,0 +1,26 @@
#ifndef ICON_H
#define ICON_H
#include <Application.h>
#include <Archivable.h>
#include <ClassInfo.h>
#include "common.h"
#include "settings.h"
class AutoRaiseApp: public BApplication{
protected:
bool _directToDeskbar;
public:
AutoRaiseApp();
virtual ~AutoRaiseApp();
virtual bool QuitRequested() { return true; }
virtual void ArgvReceived(int32 argc, char ** args);
virtual void ReadyToRun();
void PutInTray(bool);
};
#endif

View File

@ -0,0 +1,642 @@
/* this is for the DANO hack (new, simpler version than the BStringIO hack) */
#include <BeBuild.h>
#ifdef B_BEOS_VERSION_DANO
#define private public
#include <Messenger.h>
#undef private
#endif
#include "AutoRaiseIcon.h"
#include <stdlib.h>
#include <DataIO.h>
#include <Screen.h>
#include <View.h>
#include <Debug.h>
extern "C" _EXPORT BView *instantiate_deskbar_item(void)
{
puts("Instanciating AutoRaise TrayView...");
return (new TrayView);
}
long removeFromDeskbar(void *)
{
BDeskbar db;
if (db.RemoveItem(APP_NAME) != B_OK)
printf("Unable to remove AutoRaise from BDeskbar\n");
return 0;
}
//**************************************************
ConfigMenu::ConfigMenu(TrayView *tv, bool useMag)
:BPopUpMenu("config_popup", false, false){
BMenu *tmpm;
BMenuItem *tmpi;
BMessage *msg;
bigtime_t delay;
AutoRaiseSettings *s = tv->Settings();
SetFont(be_plain_font);
BMenuItem *active = new BMenuItem("Active", new BMessage(MSG_TOOGLE_ACTIVE));
active->SetMarked(s->Active());
AddItem(active);
tmpm = new BMenu("Mode");
tmpm->SetFont(be_plain_font);
msg = new BMessage(MSG_SET_MODE);
msg->AddInt32(AR_MODE, Mode_All);
tmpi = new BMenuItem("Default (all windows)", msg);
tmpi->SetMarked(s->Mode() == Mode_All);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_MODE);
msg->AddInt32(AR_MODE, Mode_DeskbarOver);
tmpi = new BMenuItem("Deskbar only (over its area)", msg);
tmpi->SetMarked(s->Mode() == Mode_DeskbarOver);
#ifdef USE_DANO_HACK
tmpi->SetEnabled(false);
#endif
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_MODE);
msg->AddInt32(AR_MODE, Mode_DeskbarTouch);
tmpi = new BMenuItem("Deskbar only (touch)", msg);
tmpi->SetMarked(s->Mode() == Mode_DeskbarTouch);
tmpm->AddItem(tmpi);
tmpm->SetTargetForItems(tv);
BMenuItem *modem = new BMenuItem(tmpm);
modem->SetEnabled(s->Active());
AddItem(modem);
tmpm = new BMenu("Inactive behaviour");
tmpm->SetFont(be_plain_font);
msg = new BMessage(MSG_SET_BEHAVIOUR);
msg->AddInt32(AR_BEHAVIOUR, B_NORMAL_MOUSE);
tmpi = new BMenuItem("Normal", msg);
tmpi->SetMarked(tv->fNormalMM == B_NORMAL_MOUSE);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_BEHAVIOUR);
msg->AddInt32(AR_BEHAVIOUR, B_FOCUS_FOLLOWS_MOUSE);
tmpi = new BMenuItem("Focus follows mouse", msg);
tmpi->SetMarked(tv->fNormalMM == B_FOCUS_FOLLOWS_MOUSE);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_BEHAVIOUR);
msg->AddInt32(AR_BEHAVIOUR, B_WARP_MOUSE);
tmpi = new BMenuItem("Warping (ffm)", msg);
tmpi->SetMarked(tv->fNormalMM == B_WARP_MOUSE);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_BEHAVIOUR);
msg->AddInt32(AR_BEHAVIOUR, B_INSTANT_WARP_MOUSE);
tmpi = new BMenuItem("Instant warping (ffm)", msg);
tmpi->SetMarked(tv->fNormalMM == B_INSTANT_WARP_MOUSE);
tmpm->AddItem(tmpi);
tmpm->SetTargetForItems(tv);
BMenuItem *behavm = new BMenuItem(tmpm);
AddItem(behavm);
tmpm = new BMenu("Delay");
tmpm->SetFont(be_plain_font);
msg = new BMessage(MSG_SET_DELAY);
msg->AddInt64(AR_DELAY, 100000LL);
tmpi = new BMenuItem("0.1 s", msg);
tmpi->SetMarked(tv->raise_delay == 100000LL);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_DELAY);
msg->AddInt64(AR_DELAY, 200000LL);
tmpi = new BMenuItem("0.2 s", msg);
tmpi->SetMarked(tv->raise_delay == 200000LL);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_DELAY);
msg->AddInt64(AR_DELAY, 500000LL);
tmpi = new BMenuItem("0.5 s", msg);
tmpi->SetMarked(tv->raise_delay == 500000LL);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_DELAY);
msg->AddInt64(AR_DELAY, 1000000LL);
tmpi = new BMenuItem("1 s", msg);
tmpi->SetMarked(tv->raise_delay == 1000000LL);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_DELAY);
msg->AddInt64(AR_DELAY, 2000000LL);
tmpi = new BMenuItem("2 s", msg);
tmpi->SetMarked(tv->raise_delay == 2000000LL);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_DELAY);
msg->AddInt64(AR_DELAY, 3000000LL);
tmpi = new BMenuItem("3 s", msg);
tmpi->SetMarked(tv->raise_delay == 3000000LL);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_DELAY);
msg->AddInt64(AR_DELAY, 4000000LL);
tmpi = new BMenuItem("4 s", msg);
tmpi->SetMarked(tv->raise_delay == 4000000LL);
tmpm->AddItem(tmpi);
msg = new BMessage(MSG_SET_DELAY);
msg->AddInt64(AR_DELAY, 5000000LL);
tmpi = new BMenuItem("5 s", msg);
tmpi->SetMarked(tv->raise_delay == 5000000LL);
tmpm->AddItem(tmpi);
tmpm->SetTargetForItems(tv);
BMenuItem *delaym = new BMenuItem(tmpm);
delaym->SetEnabled(s->Active());
AddItem(delaym);
AddSeparatorItem();
// AddItem(new BMenuItem("Settings...", new BMessage(OPEN_SETTINGS)));
AddItem(new BMenuItem("About "APP_NAME, new BMessage(B_ABOUT_REQUESTED)));
AddItem(new BMenuItem("Remove from tray", new BMessage(REMOVE_FROM_TRAY)));
SetTargetForItems(tv);
SetAsyncAutoDestruct(true);
}
ConfigMenu::~ConfigMenu() {}
//************************************************
TrayView::TrayView()
:BView(BRect(0, 0, B_MINI_ICON, B_MINI_ICON -1), "AutoRaise", B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW){
_init(); //Initialization common to both constructors
}
//Rehydratable constructor
TrayView::TrayView(BMessage *mdArchive):BView(mdArchive){
_init(); //As above
}
void TrayView::GetPreferredSize(float *w, float *h)
{
*w = B_MINI_ICON;
*h = B_MINI_ICON - 1;
}
void TrayView::_init()
{
thread_info ti;
status_t err;
watching = false;
_settings = new AutoRaiseSettings;
_appPath = _settings->AppPath();
raise_delay = _settings->Delay();
current_window = 0;
polling_delay = 100000;
fPollerSem = create_sem(0, "AutoRaise poller sync");
last_raiser_thread = 0;
fNormalMM = mouse_mode();
_activeIcon = NULL;
_inactiveIcon = NULL;
get_thread_info(find_thread(NULL), &ti);
fDeskbarTeam = ti.team;
#ifndef USE_DANO_HACK
resume_thread(poller_thread = spawn_thread(poller, "AutoRaise desktop poller", B_NORMAL_PRIORITY, (void *)this));
#endif
//determine paths to icon files based on app path in settings file
BResources res;
BFile theapp(&_appPath, B_READ_ONLY);
if ((err = res.SetTo(&theapp)) != B_OK) {
printf("Unable to find the app to get the resources !!!\n");
// removeFromDeskbar(NULL);
// delete _settings;
// return;
}
size_t bmsz;
char *p;
p = (char *)res.LoadResource('MICN', ACTIVE_ICON, &bmsz);
_activeIcon = new BBitmap(BRect(0, 0, B_MINI_ICON-1, B_MINI_ICON -1), B_CMAP8);
if (!p)
puts("ERROR loading active icon");
else
_activeIcon->SetBits(p, B_MINI_ICON*B_MINI_ICON, 0, B_CMAP8);
p = (char *)res.LoadResource('MICN', INACTIVE_ICON, &bmsz);
_inactiveIcon = new BBitmap(BRect(0, 0, B_MINI_ICON-1, B_MINI_ICON -1), B_CMAP8);
if (!p)
puts("ERROR loading inactive icon");
else
_inactiveIcon->SetBits(p, B_MINI_ICON*B_MINI_ICON, 0, B_CMAP8);
SetDrawingMode(B_OP_ALPHA);
SetFlags(Flags() | B_WILL_DRAW);
// begin watching if we want
// (doesn't work here, better do it in AttachedToWindow())
}
TrayView::~TrayView(){
status_t ret;
if (watching) {
#ifdef USE_DANO_HACK
be_roster->StopWatching(this);
#else
// acquire_sem(fPollerSem);
#endif
set_mouse_mode(fNormalMM);
watching = false;
}
delete_sem(fPollerSem);
#ifndef USE_DANO_HACK
wait_for_thread(poller_thread, &ret);
#endif
if (_activeIcon) delete _activeIcon;
if (_inactiveIcon) delete _inactiveIcon;
if (_settings) delete _settings;
return;
}
//Dehydrate into a message (called by the DeskBar)
status_t TrayView::Archive(BMessage *data, bool deep = true) const {
// BEntry appentry(&_appPath, true);
// BPath appPath(&appentry);
status_t error=BView::Archive(data, deep);
data->AddString("add_on", APP_SIG);
// data->AddFlat("_appPath", (BFlattenable *) &_appPath);
data->AddRef("_appPath", &_appPath);
return B_NO_ERROR;
}
//Rehydrate the View from a given message (called by the DeskBar)
TrayView *TrayView::Instantiate(BMessage *data) {
if (!validate_instantiation(data, "TrayView"))
{
return NULL;
}
return (new TrayView(data));
}
void TrayView::AttachedToWindow() {
if(Parent())
SetViewColor(Parent()->ViewColor());
if (_settings->Active()) {
fNormalMM = mouse_mode();
set_mouse_mode(B_FOCUS_FOLLOWS_MOUSE);
#ifdef USE_DANO_HACK
be_roster->StartWatching(this, B_REQUEST_WINDOW_ACTIVATED);
#else
release_sem(fPollerSem);
#endif
watching = true;
}
}
void TrayView::Draw(BRect updaterect) {
BRect bnds(Bounds());
if (Parent()) SetHighColor(Parent()->ViewColor());
else SetHighColor(189, 186, 189, 255);
FillRect(bnds);
if (_settings->Active())
{
if (_activeIcon) DrawBitmap(_activeIcon);
}
else
{
if (_inactiveIcon) DrawBitmap(_inactiveIcon);
}
}
void TrayView::MouseDown(BPoint where) {
BWindow *window = Window(); /*To handle the MouseDown message*/
if (!window) /*Check for proper instantiation*/
return;
BMessage *mouseMsg = window->CurrentMessage();
if (!mouseMsg) /*Check for existence*/
return;
if (mouseMsg->what == B_MOUSE_DOWN) {
/*Variables for storing the button pressed / modifying key*/
uint32 buttons = 0;
uint32 modifiers = 0;
/*Get the button pressed*/
mouseMsg->FindInt32("buttons", (int32 *) &buttons);
/*Get modifier key (if any)*/
mouseMsg->FindInt32("modifiers", (int32 *) &modifiers);
/*Now perform action*/
switch(buttons) {
case B_PRIMARY_MOUSE_BUTTON:
{
SetActive(!_settings->Active());
break;
}
case B_SECONDARY_MOUSE_BUTTON:
{
ConvertToScreen(&where);
//menu will delete itself (see constructor of ConfigMenu),
//so all we're concerned about is calling Go() asynchronously
ConfigMenu *menu = new ConfigMenu(this, false);
menu->Go(where, true, true, ConvertToScreen(Bounds()), true);
break;
}
}
}
}
int32 fronter(void *arg)
{
TrayView *tv = (TrayView *)arg;
int32 tok = tv->current_window;
int32 ws = current_workspace();
sem_id sem = tv->fPollerSem;
int32 *tl, tlc;
window_info *wi;
snooze(tv->raise_delay);
#ifndef USE_DANO_HACK
if (acquire_sem(sem) != B_OK)
return B_OK; // this really needs a better locking model...
#endif
if (ws != current_workspace())
goto end; // don't touch windows if we changed workspace
if (tv->last_raiser_thread != find_thread(NULL))
goto end; // seems a newer one has been spawn, exit
PRINT(("tok = %ld cw = %ld\n", tok, tv->current_window));
if (tok == tv->current_window) {
bool doZoom = false;
BRect zoomRect(0.0f, 0.0f, 10.0f, 10.0f);
do_window_action(tok, B_BRING_TO_FRONT, zoomRect, doZoom);
}
end:
release_sem(sem);
return B_OK;
}
#ifndef USE_DANO_HACK
int32 poller(void *arg)
{
TrayView *tv = (TrayView *)arg;
volatile int32 tok = tv->current_window;
int32 *tl = NULL;
int32 i, tlc;
window_info *wi = NULL;
int pass=0;
BPoint mouse;
uint32 buttons;
while (acquire_sem(tv->fPollerSem) == B_OK) {
release_sem(tv->fPollerSem);
pass++;
BLooper *l = tv->Looper();
if (!l || l->LockWithTimeout(500000) != B_OK)
continue;
tv->GetMouse(&mouse, &buttons);
tv->ConvertToScreen(&mouse);
tv->Looper()->Unlock();
if (buttons) // we don't want to interfere when the user is moving a window or something...
goto zzz;
tl = get_token_list(-1, &tlc);
for (i=0; i<tlc; i++) {
wi = get_window_info(tl[i]);
if (wi) {
if (wi->layer < 3) // we hit the desktop or a window not on this WS
goto zzz;
if ((wi->window_left > wi->window_right) || (wi->window_top > wi->window_bottom))
goto zzz; // invalid window ?
/*
printf("if (!%s && (%li, %li)isin(%li)(%li, %li, %li, %li) && (%li != %li) ", wi->is_mini?"true":"false",
(long)mouse.x, (long)mouse.y, i, wi->window_left, wi->window_right, wi->window_top, wi->window_bottom, wi->id, tok);
*/
if ((!wi->is_mini)
&& (((long)mouse.x) > wi->window_left) && (((long)mouse.x) < wi->window_right)
&& (((long)mouse.y) > wi->window_top) && (((long)mouse.y) < wi->window_bottom)) {
//((tv->_settings->Mode() != Mode_DeskbarOver) || (wi->team == tv->fDeskbarTeam))
if ((tv->_settings->Mode() == Mode_All) && (wi->id == tv->current_window))
goto zzz; // already raised
if ((tv->_settings->Mode() == Mode_All) || (wi->team == tv->fDeskbarTeam)) {
tv->current_window = wi->id;
tok = wi->id;
resume_thread(tv->last_raiser_thread = spawn_thread(fronter, "fronter", B_NORMAL_PRIORITY, (void *)tv));
goto zzz;
} else if (tv->_settings->Mode() == Mode_DeskbarTouch) // give up, before we find Deskbar under it
goto zzz;
}
free(wi);
wi=NULL;
} else
goto zzz;
}
zzz:
// puts("");
if (wi) free(wi);
wi = NULL;
if (tl) free(tl);
tl = NULL;
snooze(tv->polling_delay);
}
return B_OK;
}
#endif
void TrayView::MessageReceived(BMessage* message)
{
BMessenger msgr;
int32 *tl, tlc;
port_id pi;
int32 tok;
window_info *wi;
BAlert *alert;
bigtime_t delay;
int32 mode;
bool wasactive;
BPoint mouse;
uint32 buttons;
switch(message->what)
{
case MSG_TOOGLE_ACTIVE:
SetActive(!_settings->Active());
break;
case MSG_SET_ACTIVE:
SetActive(true);
break;
case MSG_SET_INACTIVE:
SetActive(false);
break;
case MSG_SET_DELAY:
delay = DEFAULT_DELAY;
message->FindInt64(AR_DELAY, &delay);
raise_delay = delay;
_settings->SetDelay(delay);
break;
case MSG_SET_MODE:
mode = Mode_All;
message->FindInt32(AR_MODE, &mode);
_settings->SetMode(mode);
break;
case MSG_SET_BEHAVIOUR:
message->FindInt32(AR_BEHAVIOUR, &mode);
wasactive = _settings->Active();
if (wasactive)
SetActive(false);
fNormalMM = (mode_mouse)mode;
set_mouse_mode(fNormalMM);
if (wasactive)
SetActive(true);
break;
case REMOVE_FROM_TRAY:
{
thread_id tid = spawn_thread(removeFromDeskbar, "RemoveFromDeskbar", B_NORMAL_PRIORITY, NULL);
if (tid) resume_thread(tid);
break;
}
case B_ABOUT_REQUESTED:
alert = new BAlert("about box", "AutoRaise, (c) 2002, mmu_man\nEnjoy :-)", "Ok", NULL, NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_INFO_ALERT);
alert->SetShortcut(0, B_ENTER);
alert->Go(NULL); // use asynchronous version
break;
case OPEN_SETTINGS:
break;
#ifdef USE_DANO_HACK
case B_SOME_WINDOW_ACTIVATED:
// printf("Window Activated\n");
// message->PrintToStream();
GetMouse(&mouse, &buttons);
if (buttons)
break;
if (message->FindMessenger("be:window", &msgr) < B_OK)
puts("BMsgr ERROR");
else {
bool doZoom = false;
BRect zoomRect(0.0f, 0.0f, 0.0f, 0.0f);
pi = msgr.fPort;
// printf("port:%li (%lx)\n", pi, pi);
tl = get_token_list(msgr.Team(), &tlc);
// printf("tokens (team %li): (%li) ", msgr.Team(), tlc);
for (tlc; tlc; tlc--) {
// printf("%li ", tl[tlc-1]);
wi = get_window_info(tl[tlc-1]);
if (wi) {
if (wi->client_port == pi) {
if ((wi->layer < 3) // we hit the desktop or a window not on this WS
|| (wi->window_left > wi->window_right) || (wi->window_top > wi->window_bottom)
|| (wi->is_mini)
|| (/*(_settings->Mode() == Mode_All) && */(wi->id == current_window))) {
// already raised
free(wi);
break;
}
if ((_settings->Mode() == Mode_All) || (wi->team == fDeskbarTeam)) {
PRINT(("raising wi=%li, cp=%ld, pi=%ld team=%ld DBteam=%ld\n", wi->id, wi->client_port, pi, wi->team, fDeskbarTeam));
current_window = wi->id;
tok = wi->id;
resume_thread(last_raiser_thread = spawn_thread(fronter, "fronter", B_NORMAL_PRIORITY, (void *)this));
} else {
current_window = wi->id;
}
}
free(wi);
}
}
// puts("");
free(tl);
}
break;
#endif
default:
BView::MessageReceived(message);
}
}
AutoRaiseSettings *TrayView::Settings() const
{
return _settings;
}
void TrayView::SetActive(bool st)
{
_settings->SetActive(st);
if (_settings->Active())
{
if (!watching) {
fNormalMM = mouse_mode();
set_mouse_mode(B_FOCUS_FOLLOWS_MOUSE);
#ifdef USE_DANO_HACK
be_roster->StartWatching(this, B_REQUEST_WINDOW_ACTIVATED);
#else
release_sem(fPollerSem);
#endif
watching = true;
}
}
else
{
if (watching) {
#ifdef USE_DANO_HACK
be_roster->StopWatching(this);
#else
acquire_sem(fPollerSem);
#endif
set_mouse_mode(fNormalMM);
watching = false;
}
}
Invalidate();
}

View File

@ -0,0 +1,94 @@
#ifndef TRAY_VIEW
#define TRAY_VIEW
#include <InterfaceDefs.h>
#include <TranslationKit.h>
#include <Deskbar.h>
#include <OS.h>
#include "common.h"
#include "settings.h"
#include <Roster.h>
//exported instantiator function
extern "C" _EXPORT BView* instantiate_deskbar_item();
//since we can't remove the view from the deskbar from within the same thread
//as tray view, a thread will be spawned and this function called. It removed TrayView
//from the Deskbar
long removeFromDeskbar(void *);
class _EXPORT TrayView;
/*********************************************
class TrayView derived from BView
The icon in the Deskbar tray, provides the fundamental
user interface. Archivable, so it can be flattened and fired
at the deskbar.
*********************************************/
class TrayView:public BView{
private:
BBitmap *_activeIcon, *_inactiveIcon;
entry_ref _appPath;
bool watching;
void _init(void); //initialization common to all constructors
public:
AutoRaiseSettings *_settings;
mode_mouse fNormalMM;
volatile int32 current_window; // id
bigtime_t raise_delay;
volatile thread_id last_raiser_thread;
team_id fDeskbarTeam;
bigtime_t polling_delay; // for !DANO
sem_id fPollerSem;
thread_id poller_thread;
TrayView();
TrayView(BMessage *mdArchive);
virtual ~TrayView();
virtual status_t Archive(BMessage *data, bool deep = true) const;
static TrayView *Instantiate(BMessage *data);
virtual void Draw(BRect updateRect );
virtual void AttachedToWindow();
virtual void MouseDown(BPoint where);
virtual void MessageReceived(BMessage* message);
virtual void GetPreferredSize(float *w, float *h);
AutoRaiseSettings *Settings() const;
void SetActive(bool);
};
int32 fronter(void *);
int32 poller(void *);
/*********************************************
ConfigMenu derived from BPopUpMenu
Provides the contextual left-click menu for the
TrayView. Fires it's messages at the TrayView specified
in it's constructor;
Also, it's by default set to asynchronously destruct,
so it's basically a fire & forget kinda fella.
*********************************************/
class ConfigMenu: public BPopUpMenu{
private:
public:
ConfigMenu(TrayView *tv, bool useMag);
virtual ~ConfigMenu();
};
#endif

106
src/apps/autoraise/common.h Normal file
View File

@ -0,0 +1,106 @@
#ifndef COMMON_H
#define COMMON_H
#include <stdio.h>
#include <AppKit.h>
#include <InterfaceKit.h>
#include <String.h>
#include <StorageKit.h>
// R5.1 has a very helpful API...
#if (B_BEOS_VERSION == 0x0510)
#define USE_DANO_HACK
#endif
/***************************************************
common.h
Constants used by app
***************************************************/
// used to check the image to use to get the resources
#define APP_NAME "AutoRaise"
#define APP_SIG "application/x-vnd.mmu.AutoRaise"
#define SETTINGS_FILE "x-vnd.mmu.AutoRaise_settings"
//names of data segments in settings file
//also used in messages
#define DEFAULT_DELAY 500000LL
// float: delay before raise
#define AR_DELAY "ar:delay"
// bool: last state
#define AR_ACTIVE "ar:active"
#define AR_MODE "ar:mode"
enum {
Mode_All,
Mode_DeskbarOver,
Mode_DeskbarTouch
};
#define AR_BEHAVIOUR "ar:behaviour"
// resources
#define ACTIVE_ICON "AR:ON"
#define INACTIVE_ICON "AR:OFF"
// messages
#define ADD_TO_TRAY 'zATT'
#define REMOVE_FROM_TRAY 'zRFT'
#define OPEN_SETTINGS 'zOPS'
#define MSG_DELAY_POPUP 'arDP'
#define MSG_TOOGLE_ACTIVE 'arTA'
#define MSG_SET_ACTIVE 'arSA'
#define MSG_SET_INACTIVE 'arSI'
#define MSG_SET_DELAY 'arSD'
#define MSG_SET_MODE 'arSM'
#define MSG_SET_BEHAVIOUR 'arSB'
/* from OpenTracker deskbar/WindowMenuItem.h */
// from interface_defs.h
struct window_info {
team_id team;
int32 id; /* window's token */
int32 thread;
int32 client_token;
int32 client_port;
uint32 workspaces;
int32 layer;
uint32 w_type; /* B_TITLED_WINDOW, etc. */
uint32 flags; /* B_WILL_FLOAT, etc. */
int32 window_left;
int32 window_top;
int32 window_right;
int32 window_bottom;
int32 show_hide_level;
bool is_mini;
char name[1];
};
// from interface_misc.h
enum window_action {
B_MINIMIZE_WINDOW,
B_BRING_TO_FRONT
};
// from interface_misc.h
void do_window_action(int32 window_id, int32 action,
BRect zoomRect, bool zoom);
window_info *get_window_info(int32 a_token);
int32 *get_token_list(team_id app, int32 *count);
void do_minimize_team(BRect zoomRect, team_id team, bool zoom);
void do_bring_to_front_team(BRect zoomRect, team_id app, bool zoom);
#endif

121
src/apps/autoraise/makefile Normal file
View File

@ -0,0 +1,121 @@
## BeOS Generic Makefile v2.2 ##
## Fill in this file to specify the project being created, and the referenced
## makefile-engine will do all of the hard work for you. This handles both
## Intel and PowerPC builds of the BeOS.
## Application Specific Settings ---------------------------------------------
# specify the name of the binary
NAME= AutoRaise
# specify the type of binary
# APP: Application
# SHARED: Shared library or add-on
# STATIC: Static library archive
# DRIVER: Kernel Driver
TYPE= APP
# add support for new Pe and Eddie features
# to fill in generic makefile
#%{
# @src->@
# specify the source files to use
# full paths or paths relative to the makefile can be included
# all files, regardless of directory, will have their object
# files created in the common object directory.
# Note that this means this makefile will not work correctly
# if two source files with the same name (source.c or source.cpp)
# are included from different directories. Also note that spaces
# in folder names do not work well with this makefile.
#SRCS= AutoRaiseApp.cpp AutoRaiseWindow.cpp AutoRaiseIcon.cpp
SRCS= AutoRaiseApp.cpp AutoRaiseIcon.cpp settings.cpp
# specify the resource files to use
# full path or a relative path to the resource file can be used.
RSRCS= AutoRaise.rsrc
# @<-src@
#%}
# end support for Pe and Eddie
# specify additional libraries to link against
# there are two acceptable forms of library specifications
# - if your library follows the naming pattern of:
# libXXX.so or libXXX.a you can simply specify XXX
# library: libbe.so entry: be
#
# - if your library does not follow the standard library
# naming scheme you need to specify the path to the library
# and it's name
# library: my_lib.a entry: my_lib.a or path/my_lib.a
LIBS= be stdc++.r4 zeta
# specify additional paths to directories following the standard
# libXXX.so or libXXX.a naming scheme. You can specify full paths
# or paths relative to the makefile. The paths included may not
# be recursive, so include all of the paths where libraries can
# be found. Directories where source files are found are
# automatically included.
LIBPATHS=
# additional paths to look for system headers
# thes use the form: #include <header>
# source file directories are NOT auto-included here
SYSTEM_INCLUDE_PATHS =
# additional paths to look for local headers
# thes use the form: #include "header"
# source file directories are automatically included
LOCAL_INCLUDE_PATHS =
# specify the level of optimization that you desire
# NONE, SOME, FULL
OPTIMIZE=
# specify any preprocessor symbols to be defined. The symbols will not
# have their values set automatically; you must supply the value (if any)
# to use. For example, setting DEFINES to "DEBUG=1" will cause the
# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG"
# would pass "-DDEBUG" on the compiler's command line.
DEFINES=
# specify special warning levels
# if unspecified default warnings will be used
# NONE = supress all warnings
# ALL = enable all warnings
WARNINGS =
# specify whether image symbols will be created
# so that stack crawls in the debugger are meaningful
# if TRUE symbols will be created
SYMBOLS =
# specify debug settings
# if TRUE will allow application to be run from a source-level
# debugger. Note that this will disable all optimzation.
DEBUGGER =
# specify additional compiler flags for all files
COMPILER_FLAGS =
# specify additional linker flags
LINKER_FLAGS =
# specify the version of this particular item
# (for example, -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL")
# This may also be specified in a resource.
APP_VERSION =
# (for TYPE == DRIVER only) Specify desired location of driver in the /dev
# hierarchy. Used by the driverinstall rule. E.g., DRIVER_PATH = video/usb will
# instruct the driverinstall rule to place a symlink to your driver's binary in
# ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will appear at
# /dev/video/usb when loaded. Default is "misc".
DRIVER_PATH =
## include the makefile-engine
include $(BUILDHOME)/etc/makefile-engine

View File

@ -0,0 +1,85 @@
#include "settings.h"
#include <iostream.h>
#define CONF_ADDPROP(_type, _name) \
void AutoRaiseSettings::Set##_name(_type value)\
{\
_conf##_name = value;\
}\
\
_type AutoRaiseSettings::##_name()\
{\
return _conf##_name;\
}\
CONF_ADDPROP(bool, Active)
CONF_ADDPROP(bigtime_t, Delay)
CONF_ADDPROP(int32, Mode)
//CONF_ADDPROP(BPath, AppPath)
CONF_ADDPROP(entry_ref, AppPath)
#undef CONF_ADDPROP
AutoRaiseSettings::AutoRaiseSettings()
{
_confActive = false;
_confDelay = DEFAULT_DELAY;
_confMode = Mode_All;
BPath prefPath;
find_directory(B_USER_SETTINGS_DIRECTORY, &prefPath);
prefPath.Append(SETTINGS_FILE);
_settingsFile.SetTo(prefPath.Path(), B_READ_WRITE | B_CREATE_FILE);
if (_settingsMessage.Unflatten(&_settingsFile) == B_OK){
if (_settingsMessage.FindBool(AR_ACTIVE, &_confActive) != B_OK)
printf("AutoRaiseSettings::AutoRaiseSettings();\tFailed to load active boolean from settings file. Using default\n");
if (_settingsMessage.FindInt64(AR_DELAY, &_confDelay) != B_OK)
printf("AutoRaiseSettings::AutoRaiseSettings();\tFailed to load delay from settings file. Using default\n");
if (_settingsMessage.FindInt32(AR_MODE, &_confMode) != B_OK)
printf("AutoRaiseSettings::AutoRaiseSettings();\tFailed to load mode from settings file. Using default\n");
// if (_settingsMessage.FindFlat(AR_APP_PATH, (BFlattenable *) &_appPath) != B_OK)
// printf("AutoRaiseSettings::AutoRaiseSettings();\tFailed to load application path.\n");
if (_settingsMessage.FindRef(AR_APP_PATH, &_confAppPath) != B_OK)
printf("AutoRaiseSettings::AutoRaiseSettings();\tFailed to load application path.\n");
}
else
{
printf("AutoRaiseSettings::AutoRaiseSettings()\nUnable to open settings file (either corrupted or doesn't exist), using defaults.\n");
}
_settingsFile.Unset();
}
AutoRaiseSettings::~AutoRaiseSettings()
{
BPath prefPath;
find_directory(B_USER_SETTINGS_DIRECTORY, &prefPath);
prefPath.Append(SETTINGS_FILE);
//clobber existing settings and write in new ones
_settingsFile.SetTo(prefPath.Path(), B_READ_WRITE | B_ERASE_FILE);
//empty message and refill it with whatever has been set
_settingsMessage.MakeEmpty();
_settingsMessage.AddBool(AR_ACTIVE, _confActive);
_settingsMessage.AddInt64(AR_DELAY, _confDelay);
_settingsMessage.AddInt32(AR_MODE, _confMode);
// _settingsMessage.AddFlat(AR_APP_PATH, &_appPath);
_settingsMessage.AddRef(AR_APP_PATH, &_confAppPath);
//write message to settings file
if (_settingsMessage.Flatten(&_settingsFile) != B_OK)
printf("Error occurred writing settings\n");
_settingsFile.Unset();
}

View File

@ -0,0 +1,68 @@
#ifndef SETTINGS_H
#define SETTINGS_H
/***************************************************
settings.h
Mechanisms for managing the settings setting/retireval for AutoRaise
2002 mmu_man
from Deskscope:
2000 Shamyl Zakariya
***************************************************/
#include "common.h"
/****************************************
AutoRaiseSettings
Simple class for getting and setting prefs.
Instantiating will open up settings file
Destroying will write settings plus any changes
back into the file.
Settings file won't be updated until AutoRaiseSettings
destructor is called. Doens't matter if it's allocated off
heap or stack. I recommend stack, though, to keep likelyhood
of race conditions down.
File is defined in common.h as SETTINGS_FILE
****************************************/
// make adding configuration fields easier
#define CONF_ADDPROP(_type, _name) \
protected:\
_type _conf##_name;\
public:\
void Set##_name(_type value);\
_type _name();
class AutoRaiseSettings
{
protected:
BFile _settingsFile;
// BPath _appPath;
BMessage _settingsMessage;
BMessage openSettingsFile();
void closeSettingsFile();
public:
AutoRaiseSettings();
~AutoRaiseSettings();
CONF_ADDPROP(bool, Active)
CONF_ADDPROP(bigtime_t, Delay)
CONF_ADDPROP(int32, Mode)
//CONF_ADDPROP(BPath, AppPath)
CONF_ADDPROP(entry_ref, AppPath)
};
#undef CONF_ADDPROP
#define AR_APP_PATH "ar:app_path"
#endif