// Handle backdrop icon idcmp stuff BOOL backdrop_idcmp(BackdropInfo *info,struct IntuiMessage *msg,unsigned short flags) { BOOL handled=1; BOOL busy=0; // Lister locked? if (info->lister && info->lister->flags&LISTERF_LOCK) busy=1; // Message class? switch (msg->Class) { // Size change case IDCMP_NEWSIZE: backdrop_update_size(info); break; // Refresh window case IDCMP_REFRESHWINDOW: // If we haven't already refreshed if (!(info->flags&BDIF_REFRESHED)) { UWORD ref_flags; // Get flags for refreshing ref_flags=BDSF_REFRESH; if (!(flags&BIDCMPF_LISTER)) ref_flags|=BDSF_REFRESH_DONE; // From a resize? if (info->flags&BDIF_NEW_SIZE) ref_flags|=BDSF_RECALC; // Otherwise, check that size is ok else backdrop_check_size(info); // Refresh objects backdrop_show_objects(info,ref_flags); } // Clear flags info->flags&=~(BDIF_NEW_SIZE|BDIF_REFRESHED); // Got a lister? if (info->lister) { // Clear 'sized' flag in lister info->lister->flags&=~LISTERF_RESIZED; // Save event for lister too if (flags&BIDCMPF_LISTER) handled=0; } break; // Mouse moved case IDCMP_MOUSEMOVE: // Rubber banding? if (info->flags&BDIF_RUBBERBAND) { short x,y; // Get coordinates, clip to borders x=info->window->MouseX; y=info->window->MouseY; if (x<info->size.MinX) x=info->size.MinX; if (x>info->size.MaxX) x=info->size.MaxX; if (y<info->size.MinY) y=info->size.MinY; if (y>info->size.MaxY) y=info->size.MaxY; // Have coordinates changed? if (info->select.MaxX!=x || info->select.MaxY!=y) { // Erase old box backdrop_rubber_band(info,0); // New coordinates info->select.MaxX=x; info->select.MaxY=y; // Show new box backdrop_rubber_band(info,1); } break; } // Are we dragging something? else if (info->flags&BDIF_DRAGGING && info->last_sel_object) { // Show drag objects backdrop_show_drag( info, info->last_sel_object, info->window->WScreen->MouseX, info->window->WScreen->MouseY); break; } // No gadget down, or no real-time scrolling? if (!info->down_gadget || !(environment->env->display_options&DISPOPTF_REALTIME_SCROLL)) { // Not handled handled=0; break; } // Tick case IDCMP_INTUITICKS: // Tick? if (msg->Class==IDCMP_INTUITICKS) { // Increment tick count ++info->tick_count; // No gadget down? if (!info->down_gadget) { // Turn ticks off if not dragging if (!(info->flags&(BDIF_DRAGGING|BDIF_RUBBERBAND))) ModifyIDCMP(info->window,info->window->IDCMPFlags&~IDCMP_INTUITICKS); break; } // Ignore this gadget? if (info->flags&BDIF_IGNORE_GADGET) { info->flags&=~BDIF_IGNORE_GADGET; break; } } // Fake gadget down msg->IAddress=info->down_gadget; // Gadget down case IDCMP_GADGETDOWN: // Store gadget if (info->down_gadget!=(struct Gadget *)msg->IAddress) { info->down_gadget=(struct Gadget *)msg->IAddress; info->flags|=BDIF_IGNORE_GADGET; ModifyIDCMP(info->window,info->window->IDCMPFlags|IDCMP_INTUITICKS); } // Check gadget is selected if (!(info->down_gadget->Flags&GFLG_SELECTED)) break; // Look at gadget ID switch (info->down_gadget->GadgetID) { // Up arrow case GAD_VERT_ARROW_UP: backdrop_scroll(info,0,-1); break; // Down arrow case GAD_VERT_ARROW_DOWN: backdrop_scroll(info,0,1); break; // Left arrow case GAD_HORIZ_ARROW_LEFT: backdrop_scroll(info,-1,0); break; // Right arrow case GAD_HORIZ_ARROW_RIGHT: backdrop_scroll(info,1,0); break; // Vertical slider case GAD_VERT_SCROLLER: if (environment->env->display_options&DISPOPTF_REALTIME_SCROLL) backdrop_pos_slider(info,SLIDER_VERT); break; // Horizontal slider case GAD_HORIZ_SCROLLER: if (environment->env->display_options&DISPOPTF_REALTIME_SCROLL) backdrop_pos_slider(info,SLIDER_HORZ); break; } break; // Gadget up case IDCMP_GADGETUP: info->down_gadget=0; info->flags&=~BDIF_IGNORE_GADGET; ModifyIDCMP(info->window,info->window->IDCMPFlags&~IDCMP_INTUITICKS); // Look at gadget ID switch (((struct Gadget *)msg->IAddress)->GadgetID) { // Vertical slider case GAD_VERT_SCROLLER: backdrop_pos_slider(info,SLIDER_VERT); break; // Horizontal slider case GAD_HORIZ_SCROLLER: backdrop_pos_slider(info,SLIDER_HORZ); break; // Another gadget default: handled=0; break; } break; // Mouse buttons case IDCMP_MOUSEBUTTONS: // Ignore if busy if (busy) break; // Clear down gadget info->down_gadget=0; info->flags&=~BDIF_IGNORE_GADGET; ModifyIDCMP(info->window,info->window->IDCMPFlags&~IDCMP_INTUITICKS); // Handle button handled=backdrop_handle_button(info,msg,flags); // Remember the last button pushed info->last_button=msg->Code&~IECODE_UP_PREFIX; break; // Key press case IDCMP_RAWKEY: // Dragging something? if (info->flags&(BDIF_RUBBERBAND|BDIF_DRAGGING)) { // If escape is pressed, cancel drag if (msg->Code==0x45) backdrop_stop_drag(info); break; } // Title-barred lister? if (info->lister && info->lister->more_flags&LISTERF_TITLEBARRED) break; // Not handled by default handled=0; // Look at key switch (msg->Code) { // Space toggles icon selection case 0x40: // Lister not busy? if (!busy) { BackdropObject *object; // Lock backdrop list lock_listlock(&info->objects,1); // Turn off? if (info->flags&BDIF_KEY_SELECTION) { // See if current selection is still valid if ((object=find_backdrop_object(info,info->current_sel_object))) { // Clear selection flag and redraw object->flags&=~BDOF_SELECTED; backdrop_render_object(info,object,BRENDERF_CLIP); } // Clear selection pointer info->current_sel_object=0; info->flags&=~BDIF_KEY_SELECTION; } // Turn on else { // Sort objects into position order backdrop_sort_objects(info,0,0); // Get first object object=(BackdropObject *)info->objects.list.lh_Head; if (object->node.ln_Succ) { // Set selection flag in new object and render object->flags|=BDOF_SELECTED; backdrop_render_object(info,object,BRENDERF_CLIP); // Store object pointer info->current_sel_object=object; info->flags|=BDIF_KEY_SELECTION; } } // Unlock backdrop list unlock_listlock(&info->objects); handled=1; } break; // Cursor keys changes selection case CURSORUP: case CURSORDOWN: case CURSORLEFT: case CURSORRIGHT: // In selection mode? if (!busy && info->flags&BDIF_KEY_SELECTION) { BackdropObject *object=0,*lastobject; short horiz=0; // Lock backdrop list lock_listlock(&info->objects,1); // Horizontal movement? if (msg->Code==CURSORLEFT || msg->Code==CURSORRIGHT) horiz=BSORT_HORIZ; // Need to resort? if ((horiz && !(info->flags&BDIF_LAST_SORT_HORIZ)) || (!horiz && info->flags&BDIF_LAST_SORT_HORIZ)) { // Sort objects into position order backdrop_sort_objects(info,horiz,0); } // See if current selection is still valid if ((lastobject=find_backdrop_object(info,info->current_sel_object))) { // Down or right, get next object if (msg->Code==CURSORDOWN || msg->Code==CURSORRIGHT) object=(BackdropObject *)lastobject->node.ln_Succ; // Up or left, get previous object else object=(BackdropObject *)lastobject->node.ln_Pred; } // Invalid object? if (!object || !object->node.ln_Succ || !object->node.ln_Pred) { // Get first (or last) selection if (object && !object->node.ln_Pred) object=(BackdropObject *)info->objects.list.lh_TailPred; else object=(BackdropObject *)info->objects.list.lh_Head; } // New object different from last? if (object!=info->current_sel_object) { // Was there an old selection? if (lastobject) { // Clear selection flag and redraw lastobject->flags&=~BDOF_SELECTED; backdrop_render_object(info,lastobject,BRENDERF_CLIP); } // New valid object? if (object) { // Make sure object is visible backdrop_make_visible(info,object); // Set selection flag in new object and render object->flags|=BDOF_SELECTED; backdrop_render_object(info,object,BRENDERF_CLIP); } // Store object pointer info->current_sel_object=object; } // Unlock backdrop list unlock_listlock(&info->objects); handled=1; } break; // Return opens an icon case 0x44: // In selection mode? if (!busy && info->flags&BDIF_KEY_SELECTION) { BackdropObject *object; // Lock backdrop list lock_listlock(&info->objects,0); // See if current selection is still valid if ((object=find_backdrop_object(info,info->current_sel_object))) { // Open object info->last_sel_object=object; backdrop_object_open(info,object,msg->Qualifier,1,0,0); // Clear selection pointers info->current_sel_object=0; info->last_sel_object=0; info->flags&=~BDIF_KEY_SELECTION; // Deselect object object->flags&=~BDOF_SELECTED; backdrop_render_object(info,object,BRENDERF_CLIP); } // Unlock backdrop list unlock_listlock(&info->objects); handled=1; } break; // Page up/Page down case PAGEUP: case PAGEDOWN: { ULONG oldpos,pos; long newpos,diff; // Get old position GetAttr(PGA_Top,info->vert_scroller,&oldpos); // Get new position newpos=info->offset_y-info->area.MinY; if (msg->Code==PAGEUP) newpos-=(info->size.MaxY-info->size.MinY)+1; else newpos+=(info->size.MaxY-info->size.MinY)+1; if (newpos<0) newpos=0; // Update gadget SetGadgetAttrs(info->vert_scroller,info->window,0, PGA_Top,newpos, TAG_END); // Get new position GetAttr(PGA_Top,info->vert_scroller,&pos); // Change? diff=oldpos-pos; if (diff<0) diff=-diff; if (diff>2) { // Update screen backdrop_pos_slider(info,SLIDER_VERT); } handled=1; } break; // Home/End case HOME: case END: { ULONG oldpos,pos; long diff; // Get old position GetAttr(PGA_Top,info->horiz_scroller,&oldpos); // Update gadget SetGadgetAttrs(info->horiz_scroller,info->window,0, PGA_Top,(msg->Code==HOME)?0:0xfffffff, TAG_END); // Get new position GetAttr(PGA_Top,info->horiz_scroller,&pos); // Change? diff=oldpos-pos; if (diff<0) diff=-diff; if (diff>2) { // Update screen backdrop_pos_slider(info,SLIDER_HORZ); } handled=1; } break; } break; // Not handled default: handled=0; break; } return handled; }
// Group handler void __saveds backdrop_group_handler(void) { IPCData *ipc; GroupData *group=0; // Do group if (ipc=IPC_ProcStartup((ULONG *)&group,backdrop_group_init)) { // Read objects SetBusyPointer(group->window); backdrop_read_group_objects(group); ClearPointer(group->window); // Event loop FOREVER { IPCMessage *msg; BOOL quit_flag=0; // Got an AppWindow? if (group->appwindow) { DOpusAppMessage *amsg; BOOL beep=0; // AppMessages? while (amsg=(DOpusAppMessage *)GetMsg(group->appport)) { short arg; char path[256]; BackdropObject *drop_obj; // Lock backdrop list lock_listlock(&group->info->objects,1); // Set busy pointer if (group->window) SetBusyPointer(group->window); // Dropped on an object? if (drop_obj=backdrop_get_object(group->info,amsg->da_Msg.am_MouseX,amsg->da_Msg.am_MouseY,0)) { USHORT qual; // Get qualifiers qual=(InputBase)?PeekQualifier():0; // Is shift/alt down? if (qual&(IEQUALIFIER_LSHIFT|IEQUALIFIER_LALT)==(IEQUALIFIER_LSHIFT|IEQUALIFIER_LALT)) { // Get path of first file GetWBArgPath(&amsg->da_Msg.am_ArgList[0],path,256); // Replace the image backdrop_replace_icon_image(group->info,path,drop_obj); } // Run program with args else backdrop_object_open( group->info, drop_obj, 0, 0, amsg->da_Msg.am_NumArgs, amsg->da_Msg.am_ArgList); } // Otherwise, adding objects to the group else for (arg=0;arg<amsg->da_Msg.am_NumArgs;arg++) { // Valid name? if (*amsg->da_Msg.am_ArgList[arg].wa_Name) { short x,y; // Get full path name GetWBArgPath(&amsg->da_Msg.am_ArgList[arg],path,256); // Default to no position x=-1; y=-1; // Dopus app message? if (CheckAppMessage(amsg)) { // Get icon position x=amsg->da_DragOffset.x+amsg->da_Msg.am_MouseX+amsg->da_DropPos[arg].x; y=amsg->da_DragOffset.y+amsg->da_Msg.am_MouseY+amsg->da_DropPos[arg].y; } // Add group object backdrop_group_add_object(group->name,group->info,path,x,y); } // Otherwise, set beep flag for error else if (!beep) { beep=1; DisplayBeep(group->window->WScreen); } } // Clear busy pointer if (group->window) ClearPointer(group->window); // Unlock backdrop list unlock_listlock(&group->info->objects); // Reply to message ReplyMsg((struct Message *)amsg); } } // Icon notification if (group->info->notify_req) { DOpusNotify *notify; // Get notify message if (notify=(DOpusNotify *)GetMsg(group->info->notify_port)) backdrop_check_notify(group->info,notify,0); } // IPC messages? while (msg=(IPCMessage *)GetMsg(ipc->command_port)) { // Look at message switch (msg->command) { // Activate case IPC_ACTIVATE: // Bring window to front if (group->window) backdrop_show_group(group); break; // Quit case IPC_QUIT: quit_flag=1; group->got_quit=1; break; // Hide case IPC_HIDE: backdrop_hide_group(group); break; // Show case IPC_SHOW: group->screen=(struct Screen *)msg->data; backdrop_show_group(group); break; // Reset (menus) case IPC_RESET: // Gotta window? if (group->window) { // Reset menus? if (msg->flags) { display_free_menu(group->window); display_get_menu(group->window); } // Fix menus display_fix_menu(group->window,WINDOW_GROUP,0); } break; // New font case GROUP_NEW_FONT: // Get new font backdrop_get_font(group->info); // Redraw objects backdrop_show_objects(group->info,BDSF_CLEAR|BDSF_RESET); break; // New name case GROUP_NEW_NAME: // Copy name strcpy(group->name,msg->data_free); // Update window title if (group->window) SetWindowTitles(group->window,group->name,(char *)-1); break; // Add a new icon case GROUP_ADD_ICON: // Lock backdrop list lock_listlock(&group->info->objects,1); // Set busy pointer if (group->window) SetBusyPointer(group->window); // Add object backdrop_group_add_object(group->name,group->info,msg->data_free,-1,-1); // Clear busy pointer if (group->window) ClearPointer(group->window); // Unlock backdrop list unlock_listlock(&group->info->objects); break; // New backfill pattern case LISTER_BACKFILL_CHANGE: // Window open? if (group->window) { // Install appropriate hook InstallLayerHook( group->window->WLayer, (msg->flags)?&group->pattern.hook:LAYERS_BACKFILL); // Redraw window erase_window(group->window); // Redraw icons backdrop_show_objects(group->info,0); } break; // Delete from group case GROUP_DELETE: SetBusyPointer(group->window); backdrop_remove_group_objects(group,(BackdropObject *)msg->data); ClearPointer(group->window); break; // Help case IPC_HELP: // Show help for group help_show_help(HELP_PROGRAM_GROUP,0); break; // Do a function case LISTER_DO_FUNCTION: // Arrange icons? if (msg->data>=(APTR)MENU_LISTER_ARRANGE_NAME && msg->data<=(APTR)MENU_LISTER_ARRANGE_SIZE) { // Do cleanup backdrop_cleanup(group->info,BSORT_NAME+(((ULONG)msg->data)-MENU_LISTER_ARRANGE_NAME),0); } break; } // Reply to message IPC_Reply(msg); } // Is window open? if (group->window) { struct IntuiMessage *imsg; // Check timer if (CheckTimer(group->timer)) { // Dragging something? if (group->info->flags&BDIF_DRAGGING) { // Check for deadlocks if (group->info->last_tick==group->info->tick_count) { // Stop drag backdrop_stop_drag(group->info); } // Remember tick count group->info->last_tick=group->info->tick_count; } // Re-start timer StartTimer(group->timer,0,500000); } // Window messages while (imsg=(struct IntuiMessage *)GetMsg(group->window->UserPort)) { struct IntuiMessage msg_copy; struct MenuItem *item; // Copy message msg_copy=*imsg; // Menu verify? if (imsg->Class==IDCMP_MENUVERIFY) { // See if we want to swallow it if (!backdrop_test_rmb(group->info,imsg,&msg_copy,TRUE)) { // Did event happen over the window? if (imsg->MouseX>=0 && imsg->MouseY>=0 && imsg->MouseX<group->window->Width && imsg->MouseY<group->window->Height && imsg->Qualifier&IEQUALIFIER_RBUTTON) { // Cancel menu event imsg->Code=MENUCANCEL; // Change our copy to MOUSEBUTTONS msg_copy.Class=IDCMP_MOUSEBUTTONS; msg_copy.Code=MENUDOWN; // Kludge for MagicMenu if (msg_copy.Seconds==0) CurrentTime(&msg_copy.Seconds,&msg_copy.Micros); } } } // Resize/refresh? if (imsg->Class==IDCMP_NEWSIZE || imsg->Class==IDCMP_REFRESHWINDOW) { // Handle message backdrop_idcmp(group->info,imsg,0); // Reply to message ReplyMsg((struct Message *)imsg); continue; } // Reply to message ReplyMsg((struct Message *)imsg); // Is it a backdrop message? if (backdrop_idcmp(group->info,&msg_copy,0)) continue; // Look at message class switch (msg_copy.Class) { // Window closed case IDCMP_CLOSEWINDOW: quit_flag=1; break; // Window is inactive case IDCMP_INACTIVEWINDOW: // Abort timer if running StopTimer(group->timer); break; // Window is active case IDCMP_ACTIVEWINDOW: // Start timer if not running StartTimer(group->timer,1,0); break; // Key press case IDCMP_RAWKEY: // Help? if (msg_copy.Code==0x5f && !(msg_copy.Qualifier&VALID_QUALIFIERS)) { help_get_help( msg_copy.MouseX+group->window->LeftEdge, msg_copy.MouseY+group->window->TopEdge, msg_copy.Qualifier); } // Close? else if (msg_copy.Code==0x45 && msg_copy.Qualifier&IEQUAL_ANYSHIFT) quit_flag=1; break; // Button pressed case IDCMP_MOUSEBUTTONS: // Right button? if (msg_copy.Code==MENUDOWN) { USHORT res; // Do popup menu if (group->popup && (res=DoPopUpMenu(group->window,&group->popup->ph_Menu,NULL,MENUDOWN))!=(USHORT)-1) { // Help? if (res&POPUP_HELPFLAG) { // Get help ID res&=~POPUP_HELPFLAG; // Do help help_menu_help(res,0); break; } // Do the function quit_flag=backdrop_group_do_function(group,res,0); } } break; // Menu event case IDCMP_MENUPICK: case IDCMP_MENUHELP: { struct Menu *oldstrip=group->window->MenuStrip; USHORT nextselect; // Get item nextselect=msg_copy.Code; while (item=ItemAddress(group->window->MenuStrip,nextselect)) { // get next nextselect=item->NextSelect; // Help? if (msg_copy.Class==IDCMP_MENUHELP) { help_menu_help((long)GTMENUITEM_USERDATA(item),0); break; } // Do the function quit_flag=backdrop_group_do_function(group,(ULONG)GTMENUITEM_USERDATA(item),item); // Check valid next if (!nextselect || !group->window || oldstrip!=group->window->MenuStrip) break; } } break; } } } // Check quit flag if (quit_flag) break; // Wait for event Wait( 1<<ipc->command_port->mp_SigBit| 1<<group->timer->port->mp_SigBit| ((group->info->notify_req)?(1<<group->info->notify_port->mp_SigBit):0)| ((group->window)?(1<<group->window->UserPort->mp_SigBit):0)| ((group->appwindow)?(1<<group->appport->mp_SigBit):0)); } // Close window backdrop_free_group(group); // Send goodbye IPC_Goodbye(ipc,&main_ipc,0); }
// Start dragging BOOL backdrop_start_drag(BackdropInfo *info,short x,short y) { BackdropObject *object; // Set drag flag info->flags|=BDIF_DRAGGING; // Copy RastPort and initialise GELs GUI->drag_screen_rp=GUI->screen_pointer->RastPort; GUI->drag_screen_rp.GelsInfo=&GUI->drag_info; InitGels(&GUI->drag_head,&GUI->drag_tail,&GUI->drag_info); // Custom dragging? if (DragCustomOk(GUI->drag_screen_rp.BitMap)) { // Set custom flag info->flags|=BDIF_CUSTOM_DRAG; } // Normal dragging else info->flags&=~BDIF_CUSTOM_DRAG; // Reset saved coords info->last_x=x; info->last_y=y; // Stop menu actions, start mouse reporting info->window->Flags|=WFLG_RMBTRAP|WFLG_REPORTMOUSE; // Turn ticks on ModifyIDCMP(info->window,info->window->IDCMPFlags|IDCMP_INTUITICKS); info->tick_count=1; info->last_tick=0; // Get start time CurrentTime(&info->drag_sec,&info->drag_mic); // Last selected icon? if ((object=info->last_sel_object) && object->state) { // Check icon isn't locked if (object->flags&BDOF_LOCKED) { // Can't drag at all backdrop_stop_drag(info); return 0; } } // Go through backdrop list for (object=(BackdropObject *)info->objects.list.lh_Head; object->node.ln_Succ; object=(BackdropObject *)object->node.ln_Succ) { // Is object selected? if (object->state) { // Check icon isn't locked if (object->flags&BDOF_LOCKED) continue; // Start dragging if (!(backdrop_drag_object(info,object))) { // Failed backdrop_stop_drag(info); return 0; } } } return 1; }